Class: Squeel::Adapters::ActiveRecord::Context

Inherits:
Context
  • Object
show all
Defined in:
lib/squeel/adapters/active_record/context.rb,
lib/squeel/adapters/active_record/3.0/context.rb,
lib/squeel/adapters/active_record/4.1/context.rb

Defined Under Namespace

Classes: NoParentFoundError

Instance Attribute Summary

Attributes inherited from Context

#arel_visitor, #base, #engine

Instance Method Summary collapse

Methods inherited from Context

#contextualize

Constructor Details

#initialize(object) ⇒ Context

Returns a new instance of Context



14
15
16
17
18
19
20
# File 'lib/squeel/adapters/active_record/context.rb', line 14

def initialize(object)
  super
  @base = object.join_base
  @engine = @base.arel_engine
  @arel_visitor = get_arel_visitor
  @default_table = Arel::Table.new(@base.table_name, :as => @base.aliased_table_name, :engine => @engine)
end

Instance Method Details

#classify(object) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/squeel/adapters/active_record/context.rb', line 53

def classify(object)
  if Class === object
    object
  elsif object.respond_to? :base_klass
    object.base_klass
  else
    raise ArgumentError, "#{object} can't be converted to a class"
  end
end

#find(object, parent = @base) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/squeel/adapters/active_record/context.rb', line 22

def find(object, parent = @base)
  if JoinPart === parent
    case object
    when String, Symbol, Nodes::Stub
      assoc_name = object.to_s
      @object.join_associations.detect { |j|
        j.reflection.name.to_s == assoc_name && j.parent == parent
      }
    when Nodes::Join
      @object.join_associations.detect { |j|
        j.reflection.name == object._name && j.parent == parent &&
        (object.polymorphic? ? j.reflection.klass == object._klass : true)
      }
    else
      @object.join_associations.detect { |j|
        j.reflection == object && j.parent == parent
      }
    end
  end
end

#find!(object, parent = @base) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/squeel/adapters/active_record/4.1/context.rb', line 31

def find!(object, parent = @base)
  if ::ActiveRecord::Associations::JoinDependency::JoinPart === parent
    result =
      case object
        when String, Symbol, Nodes::Stub
          assoc_name = object.to_s
          find_string_symbol_stub_association(@base.children, @base, assoc_name, parent)
        when Nodes::Join
          find_node_join_association(@base.children, @base, object, parent)
        else
          find_other_association(@base.children, @base, object, parent)
        end

    result || raise(NoParentFoundError, "can't find #{object} in #{parent}")
  else
    raise NoParentFoundError, "can't find #{object} in #{parent}"
  end
end

#find_node_join_association(join_associations, current_parent, object, target_parent) ⇒ Object (private)



69
70
71
72
73
74
75
76
# File 'lib/squeel/adapters/active_record/4.1/context.rb', line 69

def find_node_join_association(join_associations, current_parent, object, target_parent)
  join_associations.each do |assoc|
    return assoc if assoc.reflection.name == object._name && current_parent.equal?(target_parent) &&
      (object.polymorphic? ? assoc.reflection.klass == object._klass : true)
    child_assoc = find_node_join_association(assoc.children, assoc, object, target_parent)
    return child_assoc if child_assoc
  end && false
end

#find_other_association(join_associations, current_parent, object, target_parent) ⇒ Object (private)



78
79
80
81
82
83
84
# File 'lib/squeel/adapters/active_record/4.1/context.rb', line 78

def find_other_association(join_associations, current_parent, object, target_parent)
  join_associations.each do |assoc|
    return assoc if assoc.reflection == object && current_parent.equal?(target_parent)
    child_assoc = find_other_association(assoc.children, assoc, object, target_parent)
    return child_assoc if child_assoc
  end && false
end

#find_string_symbol_stub_association(join_associations, current_parent, assoc_name, target_parent) ⇒ Object (private)



61
62
63
64
65
66
67
# File 'lib/squeel/adapters/active_record/4.1/context.rb', line 61

def find_string_symbol_stub_association(join_associations, current_parent, assoc_name, target_parent)
  join_associations.each do |assoc|
    return assoc if assoc.reflection.name.to_s == assoc_name && current_parent.equal?(target_parent)
    child_assoc = find_string_symbol_stub_association(assoc.children, assoc, assoc_name, target_parent)
    return child_assoc if child_assoc
  end && false
end

#get_arel_visitorObject (private)



77
78
79
# File 'lib/squeel/adapters/active_record/context.rb', line 77

def get_arel_visitor
  @engine.connection.visitor
end

#get_table(object) ⇒ Object (private)



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/squeel/adapters/active_record/context.rb', line 65

def get_table(object)
  if [Symbol, String, Nodes::Stub].include?(object.class)
    Arel::Table.new(object.to_s, :engine => @engine)
  elsif Nodes::Join === object
    object._klass ? object._klass.arel_table : Arel::Table.new(object._name, :engine => @engine)
  elsif object.respond_to?(:aliased_table_name)
    Arel::Table.new(object.table_name, :as => object.aliased_table_name, :engine => @engine)
  else
    raise ArgumentError, "Unable to get table for #{object}"
  end
end

#traverse(keypath, parent = @base, include_endpoint = false) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/squeel/adapters/active_record/context.rb', line 43

def traverse(keypath, parent = @base, include_endpoint = false)
  parent = @base if keypath.absolute?
  keypath.path_without_endpoint.each do |key|
    parent = find(key, parent) || key
  end
  parent = find(keypath.endpoint, parent) if include_endpoint

  parent
end

#traverse!(keypath, parent = @base, include_endpoint = false) ⇒ Object



50
51
52
53
54
55
56
57
58
# File 'lib/squeel/adapters/active_record/4.1/context.rb', line 50

def traverse!(keypath, parent = @base, include_endpoint = false)
  parent = @base if keypath.absolute?
  keypath.path_without_endpoint.each do |key|
    parent = find!(key, parent)
  end
  parent = find!(keypath.endpoint, parent) if include_endpoint

  parent
end