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)
Impleneted (and aliased 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.
25 26 27 28 29 30 |
# File 'lib/squeel/nodes/key_path.rb', line 25 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
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/squeel/nodes/key_path.rb', line 163 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.
18 19 20 |
# File 'lib/squeel/nodes/key_path.rb', line 18 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.
139 140 141 142 143 144 145 146 147 148 |
# File 'lib/squeel/nodes/key_path.rb', line 139 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 &
59 60 61 |
# File 'lib/squeel/nodes/key_path.rb', line 59 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 *
90 91 92 |
# File 'lib/squeel/nodes/key_path.rb', line 90 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 +
74 75 76 |
# File 'lib/squeel/nodes/key_path.rb', line 74 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 -
82 83 84 |
# File 'lib/squeel/nodes/key_path.rb', line 82 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 -@
66 67 68 |
# File 'lib/squeel/nodes/key_path.rb', line 66 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 /
98 99 100 |
# File 'lib/squeel/nodes/key_path.rb', line 98 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.
35 36 37 |
# File 'lib/squeel/nodes/key_path.rb', line 35 def absolute? @absolute end |
#eql?(other) ⇒ Boolean
Object comparison
40 41 42 43 44 45 |
# File 'lib/squeel/nodes/key_path.rb', line 40 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
124 125 126 |
# File 'lib/squeel/nodes/key_path.rb', line 124 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.
187 188 189 |
# File 'lib/squeel/nodes/key_path.rb', line 187 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
107 108 109 |
# File 'lib/squeel/nodes/key_path.rb', line 107 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.
151 152 153 |
# File 'lib/squeel/nodes/key_path.rb', line 151 def path_with_endpoint path + [endpoint] end |
#to_s ⇒ Object Also known as: to_str
Impleneted (and aliased to :to_str) to play nicely with ActiveRecord grouped calculations
156 157 158 |
# File 'lib/squeel/nodes/key_path.rb', line 156 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.
132 133 134 |
# File 'lib/squeel/nodes/key_path.rb', line 132 def to_sym nil end |
#|(other) ⇒ Or
Allow KeyPath to function like its endpoint, in the case where its endpoint responds to |
51 52 53 |
# File 'lib/squeel/nodes/key_path.rb', line 51 def |(other) endpoint.respond_to?(:|) ? super : no_method_error(:|) end |
#~ ⇒ KeyPath
Set the absolute flag on this KeyPath
113 114 115 116 |
# File 'lib/squeel/nodes/key_path.rb', line 113 def ~ @absolute = true self end |