Class: Squeel::Nodes::KeyPath
- Inherits:
-
Object
- Object
- Squeel::Nodes::KeyPath
- Includes:
- Operators, PredicateOperators
- Defined in:
- lib/squeel/nodes/key_path.rb
Overview
A node that stores a path of keys (of Symbol, Stub, or Join values) and an endpoint. Used similarly to a nested hash.
Instance Attribute Summary collapse
-
#endpoint ⇒ Object
readonly
The endpoint, either another key as in the path, or a predicate, function, etc.
-
#path ⇒ Array<Symbol, Stub, Join>
readonly
The path.
Instance Method Summary collapse
-
#%(val) ⇒ KeyPath
Delegate % to the KeyPath’s endpoint, with a bit of special logic for stubs or functions.
-
#&(other) ⇒ And
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to &.
-
#*(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to *.
-
#+(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to +.
-
#-(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to -.
-
#-@ ⇒ Not
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to -@.
-
#/(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to /.
-
#absolute? ⇒ Boolean
Whether or not the KeyPath should be interpreted relative to its current location (if nested in a Hash, for instance) or as though it’s at the base.
-
#eql?(other) ⇒ Boolean
Object comparison.
-
#hash ⇒ Object
For use with equality tests.
-
#initialize(path, endpoint, absolute = false) ⇒ KeyPath
constructor
Create a new KeyPath.
-
#method_missing(method_id, *args) ⇒ KeyPath
Appends to the KeyPath or delegates to the endpoint, as appropriate.
-
#no_method_error(method_id) ⇒ Object
private
Raises a NoMethodError manually, bypassing #method_missing.
-
#op(operator, other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to #op.
-
#path_with_endpoint ⇒ Array
The KeyPath’s path, including its endpoint, as a single array.
-
#to_s ⇒ Object
(also: #to_str)
Implement (and alias to :to_str) to play nicely with ActiveRecord grouped calculations.
-
#to_sym ⇒ NilClass
expand_hash_conditions_for_aggregates assumes our hash keys can be converted to symbols, so this has to be implemented, but it doesn’t really have to do anything useful.
-
#|(other) ⇒ Or
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to |.
-
#~ ⇒ KeyPath
Set the absolute flag on this KeyPath.
Constructor Details
#initialize(path, endpoint, absolute = false) ⇒ KeyPath
Create a new KeyPath.
29 30 31 32 33 34 |
# File 'lib/squeel/nodes/key_path.rb', line 29 def initialize(path, endpoint, absolute = false) @path, @endpoint = path, endpoint @path = [@path] unless Array === @path @endpoint = Stub.new(@endpoint) if Symbol === @endpoint @absolute = absolute end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_id, *args) ⇒ KeyPath
Appends to the KeyPath or delegates to the endpoint, as appropriate
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/squeel/nodes/key_path.rb', line 162 def method_missing(method_id, *args) super if method_id == :to_ary if endpoint.respond_to? method_id @endpoint = @endpoint.send(method_id, *args) self elsif Stub === endpoint || Join === endpoint @path << endpoint if args.empty? @endpoint = Stub.new(method_id) elsif (args.size == 1) && (Class === args[0]) @endpoint = Join.new(method_id, Arel::InnerJoin, args[0]) else @endpoint = Nodes::Function.new method_id, args end self else super end end |
Instance Attribute Details
#endpoint ⇒ Object (readonly)
Returns The endpoint, either another key as in the path, or a predicate, function, etc.
22 23 24 |
# File 'lib/squeel/nodes/key_path.rb', line 22 def endpoint @endpoint end |
Instance Method Details
#%(val) ⇒ KeyPath
Delegate % to the KeyPath’s endpoint, with a bit of special logic for stubs or functions.
138 139 140 141 142 143 144 145 146 147 |
# File 'lib/squeel/nodes/key_path.rb', line 138 def %(val) case endpoint when Stub, Function Array === val ? self.in(val) : self.eq(val) self else endpoint % val self end end |
#&(other) ⇒ And
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to &
63 64 65 |
# File 'lib/squeel/nodes/key_path.rb', line 63 def &(other) endpoint.respond_to?(:&) ? super : no_method_error(:&) end |
#*(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to *
94 95 96 |
# File 'lib/squeel/nodes/key_path.rb', line 94 def *(other) endpoint.respond_to?(:*) ? super : no_method_error(:*) end |
#+(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to +
78 79 80 |
# File 'lib/squeel/nodes/key_path.rb', line 78 def +(other) endpoint.respond_to?(:+) ? super : no_method_error(:+) end |
#-(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to -
86 87 88 |
# File 'lib/squeel/nodes/key_path.rb', line 86 def -(other) endpoint.respond_to?(:-) ? super : no_method_error(:-) end |
#-@ ⇒ Not
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to -@
70 71 72 |
# File 'lib/squeel/nodes/key_path.rb', line 70 def -@ endpoint.respond_to?(:-@) ? super : no_method_error(:-@) end |
#/(other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to /
102 103 104 |
# File 'lib/squeel/nodes/key_path.rb', line 102 def /(other) endpoint.respond_to?(:/) ? super : no_method_error(:/) end |
#absolute? ⇒ Boolean
Whether or not the KeyPath should be interpreted relative to its current location
(if nested in a Hash, for instance) or as though it's at the base.
39 40 41 |
# File 'lib/squeel/nodes/key_path.rb', line 39 def absolute? @absolute end |
#eql?(other) ⇒ Boolean
Object comparison
44 45 46 47 48 49 |
# File 'lib/squeel/nodes/key_path.rb', line 44 def eql?(other) self.class == other.class && self.path == other.path && self.endpoint.eql?(other.endpoint) && self.absolute? == other.absolute? end |
#hash ⇒ Object
For use with equality tests
123 124 125 |
# File 'lib/squeel/nodes/key_path.rb', line 123 def hash [self.class, endpoint, *path].hash end |
#no_method_error(method_id) ⇒ Object (private)
Raises a NoMethodError manually, bypassing #method_missing. Used by special-case operator overrides.
186 187 188 |
# File 'lib/squeel/nodes/key_path.rb', line 186 def no_method_error(method_id) raise NoMethodError, "undefined method `#{method_id}' for #{self}:#{self.class}" end |
#op(operator, other) ⇒ Operation
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to #op
111 112 113 |
# File 'lib/squeel/nodes/key_path.rb', line 111 def op(operator, other) endpoint.respond_to?(:op) ? super : no_method_error(:/) end |
#path_with_endpoint ⇒ Array
Returns The KeyPath’s path, including its endpoint, as a single array.
150 151 152 |
# File 'lib/squeel/nodes/key_path.rb', line 150 def path_with_endpoint path + [endpoint] end |
#to_s ⇒ Object Also known as: to_str
Implement (and alias to :to_str) to play nicely with ActiveRecord grouped calculations
155 156 157 |
# File 'lib/squeel/nodes/key_path.rb', line 155 def to_s path.map(&:to_s).join('.') << ".#{endpoint}" end |
#to_sym ⇒ NilClass
expand_hash_conditions_for_aggregates assumes our hash keys can be converted to symbols, so this has to be implemented, but it doesn’t really have to do anything useful.
131 132 133 |
# File 'lib/squeel/nodes/key_path.rb', line 131 def to_sym nil end |
#|(other) ⇒ Or
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to |
55 56 57 |
# File 'lib/squeel/nodes/key_path.rb', line 55 def |(other) endpoint.respond_to?(:|) ? super : no_method_error(:|) end |
#~ ⇒ KeyPath
Set the absolute flag on this KeyPath
117 118 119 120 |
# File 'lib/squeel/nodes/key_path.rb', line 117 def ~ @absolute = true self end |