Class: LegacyMigrations::Squirrel::Query::ConditionGroup
- Inherits:
-
Object
- Object
- LegacyMigrations::Squirrel::Query::ConditionGroup
- Defined in:
- lib/legacy_migrations/squirrel/squirrel.rb
Overview
ConditionGroups are groups of Conditions, oddly enough. They most closely map to models in your schema, but they also handle the grouping jobs for the #any and #all blocks.
Instance Attribute Summary collapse
-
#binding ⇒ Object
Returns the value of attribute binding.
-
#logical_join ⇒ Object
Returns the value of attribute logical_join.
-
#model ⇒ Object
Returns the value of attribute model.
-
#path ⇒ Object
Returns the value of attribute path.
-
#reflection ⇒ Object
Returns the value of attribute reflection.
Instance Method Summary collapse
-
#-@ ⇒ Object
(also: #desc)
Negates the condition.
-
#all(&blk) ⇒ Object
Creates a ConditionGroup that has the logical_join set to “AND”.
-
#any(&blk) ⇒ Object
Creates a ConditionGroup that has the logical_join set to “OR”.
-
#assign_joins(join_dependency, ancestries = nil) ⇒ Object
Takes the JoinDependency object and filters it down through the ConditionGroups to make sure each one knows the aliases necessary to refer to each table by its correct name.
-
#association(name, &blk) ⇒ Object
Similar to #column, this will create an association even if you can’t use the normal method version.
-
#column(name) ⇒ Object
Creates a Condition and queues it for inclusion.
-
#conditions ⇒ Object
Returns all the conditions, which is the union of the Conditions and ConditionGroups that belong to this ConditionGroup.
- #from ⇒ Object
-
#initialize(model, logical_join, binding, from_record = nil, path = nil, reflection = nil, &blk) ⇒ ConditionGroup
constructor
Creates a ConditionGroup by passing in the following arguments: * model: The AR subclass that defines what columns and associations will be accessible in the given block.
-
#instance(instance_var) ⇒ Object
This is a bit of a hack, due to how Squirrel is built.
-
#limit(lim, off = nil) ⇒ Object
Similar to #paginate, but does not flag the result set for pagination.
-
#negative? ⇒ Boolean
Returns true if this block has been negated using #not, #desc, or #-.
-
#not(&blk) ⇒ Object
Negates the condition.
-
#order_by(*columns) ⇒ Object
Sets the arguments for the :order parameter.
-
#paginate(opts = {}) ⇒ Object
Flags the result set to be paginated according to the :page and :per_page parameters to this method.
-
#paginate? ⇒ Boolean
Returns true if this ConditionGroup or any of its subgroups have been flagged for pagination.
-
#to_find_conditions ⇒ Object
Generates the :conditions parameter for this ConditionGroup and all subgroups.
-
#to_find_include ⇒ Object
Generates the parameter for :include for this ConditionGroup and all its subgroups.
-
#to_find_limit ⇒ Object
Generates the :limit parameter.
-
#to_find_offset ⇒ Object
Generates the :offset parameter.
-
#to_find_order ⇒ Object
Generates the :order parameter for this ConditionGroup.
Constructor Details
#initialize(model, logical_join, binding, from_record = nil, path = nil, reflection = nil, &blk) ⇒ ConditionGroup
Creates a ConditionGroup by passing in the following arguments:
-
model: The AR subclass that defines what columns and associations will be accessible
in the given block.
-
logical_join: A string containing the join that will be used when concatenating the
conditions together. The root level ConditionGroup created by Query defaults the join to be “AND”, but the #any and #all methods will create specific ConditionGroups using “OR” and “AND” as their join, respectively.
-
binding: The
binding
of the block passed to the original #find. Will be used to
eval
what self
would be. This is necessary for using methods like params
and session
in your controllers.
-
path: The “path” taken through the models to arrive at this model. For example, if
your User class has_many Posts which has_many Comments each of which belongs_to User, the path to the second User would be [:posts, :comments, :user]
-
reflection: The association used to get to this block. If nil, then no new association
was traversed, which means we’re in an #any or #all grouping block.
-
blk: The block to be executed.
This method defines a number of methods to be available inside the block, one for each of the columns and associations in the specified model. Note that you CANNOT use user-defined methods on your model inside Squirrel queries. They don’t have any meaning in the context of a database query.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 190 def initialize model, logical_join, binding, from_record = nil, path = nil, reflection = nil, &blk @model = model @from = from_record @logical_join = logical_join @conditions = [] @condition_blocks = [] @reflection = reflection @path = [ path, reflection ].compact.flatten @binding = binding @order = [] @negative = false @paginator = false @block = blk existing_methods = self.class.instance_methods(false) (model.column_names - existing_methods).each do |col| (class << self; self; end).class_eval do define_method(col.to_s.intern) do column(col) end end end (model.reflections.keys - existing_methods).each do |assn| (class << self; self; end).class_eval do define_method(assn.to_s.intern) do association(assn) end end end execute_block end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args) ⇒ Object (private)
:nodoc:
410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 410 def method_missing meth, *args #:nodoc: m = eval <<-end_eval, binding begin method(:#{meth}) rescue NameError nil end end_eval if m m.call(*args) else super(meth, *args) end end |
Instance Attribute Details
#binding ⇒ Object
Returns the value of attribute binding.
167 168 169 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 167 def binding @binding end |
#logical_join ⇒ Object
Returns the value of attribute logical_join.
167 168 169 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 167 def logical_join @logical_join end |
#model ⇒ Object
Returns the value of attribute model.
167 168 169 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 167 def model @model end |
#path ⇒ Object
Returns the value of attribute path.
167 168 169 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 167 def path @path end |
#reflection ⇒ Object
Returns the value of attribute reflection.
167 168 169 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 167 def reflection @reflection end |
Instance Method Details
#-@ ⇒ Object Also known as: desc
Negates the condition. Essentially prefixes the condition with NOT in the final query.
289 290 291 292 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 289 def -@ @negative = !@negative self end |
#all(&blk) ⇒ Object
Creates a ConditionGroup that has the logical_join set to “AND”.
253 254 255 256 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 253 def all &blk @condition_blocks << ConditionGroup.new(model, "AND", binding, @from, path, &blk) @condition_blocks.last end |
#any(&blk) ⇒ Object
Creates a ConditionGroup that has the logical_join set to “OR”.
247 248 249 250 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 247 def any &blk @condition_blocks << ConditionGroup.new(model, "OR", binding, @from, path, &blk) @condition_blocks.last end |
#assign_joins(join_dependency, ancestries = nil) ⇒ Object
Takes the JoinDependency object and filters it down through the ConditionGroups to make sure each one knows the aliases necessary to refer to each table by its correct name.
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 315 def assign_joins join_dependency, ancestries = nil ancestries ||= join_dependency.join_associations.map{|ja| ja.ancestry } unless @conditions.empty? my_association = unless @path.blank? join_dependency.join_associations[ancestries.index(@path)] else join_dependency.join_base end @conditions.each do |column| column.assign_join(my_association) end end @condition_blocks.each do |association| association.assign_joins(join_dependency, ancestries) end end |
#association(name, &blk) ⇒ Object
Similar to #column, this will create an association even if you can’t use the normal method version.
239 240 241 242 243 244 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 239 def association name, &blk name = name.to_s.intern ref = @model.reflect_on_association(name) @condition_blocks << ConditionGroup.new(ref.klass, logical_join, binding, @from, path, ref.name, &blk) @condition_blocks.last end |
#column(name) ⇒ Object
Creates a Condition and queues it for inclusion. When calling a method defined during the creation of the ConditionGroup object is the same as calling column(:column_name). This is useful if you need to access a column that happens to coincide with the name of an already-defined method (e.g. anything returned by instance_methods(false) for the given model).
232 233 234 235 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 232 def column name @conditions << Condition.new(name) @conditions.last end |
#conditions ⇒ Object
Returns all the conditions, which is the union of the Conditions and ConditionGroups that belong to this ConditionGroup.
382 383 384 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 382 def conditions @conditions + @condition_blocks end |
#from ⇒ Object
223 224 225 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 223 def from @from end |
#instance(instance_var) ⇒ Object
This is a bit of a hack, due to how Squirrel is built. It can be used to fetch instance variables from the location where the call to #find was made. For example, if called from within your model and you happened to have an instance variable called “@foo”, you can access it by calling instance “@foo” from within your Squirrel query.
397 398 399 400 401 402 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 397 def instance instance_var s = eval("self", binding) if s s.instance_variable_get(instance_var) end end |
#limit(lim, off = nil) ⇒ Object
Similar to #paginate, but does not flag the result set for pagination. Takes a limit and an offset (by default the offset is 0).
278 279 280 281 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 278 def limit lim, off = nil @limit = ( lim || @limit ).to_i @offset = ( off || @offset ).to_i end |
#negative? ⇒ Boolean
Returns true if this block has been negated using #not, #desc, or #-
387 388 389 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 387 def negative? @negative end |
#not(&blk) ⇒ Object
Negates the condition. Also works to negate ConditionGroup blocks in a more straightforward manner, like so: any.not do id == 1 name == “Joe” end
# => “NOT( id = 1 OR name = ‘Joe’)”
304 305 306 307 308 309 310 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 304 def not &blk @negative = !@negative if blk @block = blk execute_block end end |
#order_by(*columns) ⇒ Object
Sets the arguments for the :order parameter. Arguments can be columns (i.e. Conditions) or they can be strings (for “RANDOM()”, etc.). If a Condition is used, and the column is negated using #not or #desc, then the resulting specification in the ORDER clause will be ordered descending. That is, “order_by name.desc” will become “ORDER name DESC”
262 263 264 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 262 def order_by *columns @order += [columns].flatten end |
#paginate(opts = {}) ⇒ Object
Flags the result set to be paginated according to the :page and :per_page parameters to this method.
268 269 270 271 272 273 274 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 268 def paginate opts = {} @paginator = true page = (opts[:page] || 1).to_i per_page = (opts[:per_page] || 20).to_i page = 1 if page < 1 limit( per_page, ( page - 1 ) * per_page ) end |
#paginate? ⇒ Boolean
Returns true if this ConditionGroup or any of its subgroups have been flagged for pagination.
284 285 286 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 284 def paginate? @paginator || @condition_blocks.any?(&:paginate?) end |
#to_find_conditions ⇒ Object
Generates the :conditions parameter for this ConditionGroup and all subgroups. It generates them in [“sql”, params] format because of the requirements of LIKE, etc.
360 361 362 363 364 365 366 367 368 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 360 def to_find_conditions segments = conditions.collect{|c| c.to_find_conditions }.compact return nil if segments.length == 0 cond = "(" + segments.collect{|s| s.first }.join(" #{logical_join} ") + ")" cond = "NOT #{cond}" if negative? values = segments.inject([]){|all, now| all + now[1..-1] } [ cond, *values ] end |
#to_find_include ⇒ Object
Generates the parameter for :include for this ConditionGroup and all its subgroups.
333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 333 def to_find_include @condition_blocks.inject({}) do |inc, cb| if cb.reflection.nil? inc.merge_tree(cb.to_find_include) else inc[cb.reflection] ||= {} inc[cb.reflection] = inc[cb.reflection].merge_tree(cb.to_find_include) inc end end end |
#to_find_limit ⇒ Object
Generates the :limit parameter.
371 372 373 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 371 def to_find_limit @limit end |
#to_find_offset ⇒ Object
Generates the :offset parameter.
376 377 378 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 376 def to_find_offset @offset end |
#to_find_order ⇒ Object
Generates the :order parameter for this ConditionGroup. Because this does not reference subgroups it should only be used from the outermost block (which is probably where it makes the most sense to reference it, but it’s worth mentioning)
348 349 350 351 352 353 354 355 356 |
# File 'lib/legacy_migrations/squirrel/squirrel.rb', line 348 def to_find_order if @order.blank? nil else @order.collect do |col| col.respond_to?(:full_name) ? (col.full_name + (col.negative? ? " DESC" : "")) : col end.join(", ") end end |