Class: Squeel::Visitors::AttributeVisitor
- Defined in:
- lib/squeel/visitors/attribute_visitor.rb
Overview
A visitor that tries to convert visited nodes into Arel::Attributes or other nodes that can be used for grouping, ordering, and the like.
Constant Summary
Constants inherited from Base
Instance Attribute Summary
Attributes inherited from Base
Instance Method Summary collapse
-
#implies_context_change?(v) ⇒ Boolean
private
Whether the given value implies a context change.
-
#visit_Array(o, parent) ⇒ Array
private
Visit elements of an array that it’s possible to visit – leave other elements untouched.
-
#visit_Hash(o, parent) ⇒ Array
private
Visit a Hash.
-
#visit_Squeel_Nodes_As(o, parent) ⇒ Arel::Nodes::As
private
Visit a Squeel As node, resulting in am ARel As node.
-
#visit_Squeel_Nodes_Function(o, parent) ⇒ Object
private
Visit a Function node.
-
#visit_Squeel_Nodes_KeyPath(o, parent) ⇒ Object
private
Visit a keypath.
-
#visit_Squeel_Nodes_Operation(o, parent) ⇒ Object
private
Visit an Operation node.
-
#visit_Squeel_Nodes_Order(o, parent) ⇒ Arel::Nodes::Ordering
private
Visit an Order node.
-
#visit_Squeel_Nodes_Stub(o, parent) ⇒ Arel::Attribute
private
Visit a stub.
-
#visit_Symbol(o, parent) ⇒ Arel::Attribute
private
Visit a symbol.
-
#visit_with_context_change(k, v, parent) ⇒ Object
private
Change context (by setting the new parent to the result of a #find or #traverse on the key), then accept the given value.
-
#visit_without_context_change(k, v, parent) ⇒ Object
private
If there is no context change, we’ll just return the value unchanged, currently.
Methods inherited from Base
#accept, #can_accept?, can_accept?, #initialize, #quote, #quoted?, #visit
Constructor Details
This class inherits a constructor from Squeel::Visitors::Base
Instance Method Details
#implies_context_change?(v) ⇒ Boolean (private)
Returns Whether the given value implies a context change.
150 151 152 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 150 def implies_context_change?(v) can_accept?(v) end |
#visit_Array(o, parent) ⇒ Array (private)
Visit elements of an array that it’s possible to visit – leave other elements untouched.
33 34 35 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 33 def visit_Array(o, parent) o.map { |v| can_accept?(v) ? accept(v, parent) : v }.flatten end |
#visit_Hash(o, parent) ⇒ Array (private)
Visit a Hash. This entails iterating through each key and value and visiting each value in turn.
17 18 19 20 21 22 23 24 25 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 17 def visit_Hash(o, parent) o.map do |k, v| if implies_context_change?(v) visit_with_context_change(k, v, parent) else visit_without_context_change(k, v, parent) end end.flatten end |
#visit_Squeel_Nodes_As(o, parent) ⇒ Arel::Nodes::As (private)
Visit a Squeel As node, resulting in am ARel As node.
144 145 146 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 144 def visit_Squeel_Nodes_As(o, parent) accept(o.left, parent).as(o.right) end |
#visit_Squeel_Nodes_Function(o, parent) ⇒ Object (private)
Visit a Function node. Each function argument will be accepted or contextualized if appropriate. Keep in mind that this occurs with the current parent within the context.
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 92 def visit_Squeel_Nodes_Function(o, parent) args = o.args.map do |arg| case arg when Nodes::Function, Nodes::KeyPath accept(arg, parent) when Symbol, Nodes::Stub Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_sym]) else quote arg end end Arel::Nodes::NamedFunction.new(o.name, args, o.alias) end |
#visit_Squeel_Nodes_KeyPath(o, parent) ⇒ Object (private)
Visit a keypath. This will traverse the keypath’s “path”, setting a new parent as though the keypath’s endpoint was in a deeply-nested hash, then visit the endpoint with the new parent.
64 65 66 67 68 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 64 def visit_Squeel_Nodes_KeyPath(o, parent) parent = traverse(o, parent) accept(o.endpoint, parent) end |
#visit_Squeel_Nodes_Operation(o, parent) ⇒ Object (private)
Visit an Operation node. Each operand will be accepted or contextualized if appropriate. Keep in mind that this occurs with the current parent within the context.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 112 def visit_Squeel_Nodes_Operation(o, parent) args = o.args.map do |arg| case arg when Nodes::Function accept(arg, parent) when Symbol, Nodes::Stub Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_sym]) else quote arg end end op = case o.operator when :+ Arel::Nodes::Addition.new(args[0], args[1]) when :- Arel::Nodes::Subtraction.new(args[0], args[1]) when :* Arel::Nodes::Multiplication.new(args[0], args[1]) when :/ Arel::Nodes::Division.new(args[0], args[1]) else Arel.sql("#{arel_visitor.accept(args[0])} #{o.operator} #{arel_visitor.accept(args[1])}") end o.alias ? op.as(o.alias) : op end |
#visit_Squeel_Nodes_Order(o, parent) ⇒ Arel::Nodes::Ordering (private)
Visit an Order node.
75 76 77 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 75 def visit_Squeel_Nodes_Order(o, parent) accept(o.expr, parent).send(o.descending? ? :desc : :asc) end |
#visit_Squeel_Nodes_Stub(o, parent) ⇒ Arel::Attribute (private)
Visit a stub. This will return an attribute named after the stub against the current parent’s contextualized table.
53 54 55 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 53 def visit_Squeel_Nodes_Stub(o, parent) contextualize(parent)[o.symbol] end |
#visit_Symbol(o, parent) ⇒ Arel::Attribute (private)
Visit a symbol. This will return an attribute named after the symbol against the current parent’s contextualized table.
43 44 45 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 43 def visit_Symbol(o, parent) contextualize(parent)[o] end |
#visit_with_context_change(k, v, parent) ⇒ Object (private)
Change context (by setting the new parent to the result of a #find or #traverse on the key), then accept the given value.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 161 def visit_with_context_change(k, v, parent) parent = case k when Nodes::KeyPath traverse(k, parent, true) else find(k, parent) end if Array === v v.map {|val| accept(val, parent || k)} else can_accept?(v) ? accept(v, parent || k) : v end end |
#visit_without_context_change(k, v, parent) ⇒ Object (private)
If there is no context change, we’ll just return the value unchanged, currently. Is this really the right behavior? I don’t think so, but it works in this case.
185 186 187 |
# File 'lib/squeel/visitors/attribute_visitor.rb', line 185 def visit_without_context_change(k, v, parent) v end |