Class: ActiveRecord::Extensions::RangeExt

Inherits:
Object
  • Object
show all
Defined in:
lib/ar-extensions/extensions.rb

Overview

ActiveRecord::Extension to translate a ruby Range object into SQL’s BETWEEN … AND … or NOT BETWEEN … AND … . This works on Ranges of Numbers, Dates, Times, etc.

Examples

# the following two statements are identical because of how Ranges treat .. and ...
Model.find :all, :conditions=>{ :id => ( 1 .. 2 ) }
Model.find :all, :conditions=>{ :id => ( 1 ... 2 ) }

# the following four statements are identical, this finds NOT BETWEEN matches
Model.find :all, :conditions=>{ :id_ne => ( 4 .. 6 ) }
Model.find :all, :conditions=>{ :id_not => ( 4 .. 6 ) }
Model.find :all, :conditions=>{ :id_not_in => ( 4 ..6 ) }
Model.find :all, :conditions=>{ :id_not_between => ( 4 .. 6 ) }

# a little more creative, working with date ranges
Model.find :all, :conditions=>{ :created_on => (Date.now-30 .. Date.now) }

Constant Summary collapse

NOT_IN_RGX =
/^(.+)_(ne|not|not_in|not_between)$/

Class Method Summary collapse

Class Method Details

.process(key, val, caller) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/ar-extensions/extensions.rb', line 313

def self.process( key, val, caller )
  if val.is_a?( Range )
    match_data = key.to_s.match( NOT_IN_RGX )
    key = match_data.captures[0] if match_data
    fieldname = caller.connection.quote_column_name( key )
    min = caller.connection.quote( val.first, caller.columns_hash[ key ] )
    max = caller.connection.quote( val.last, caller.columns_hash[ key ] )
    str = if val.exclude_end?
      "#{match_data ? 'NOT ' : '' }(#{caller.quoted_table_name}.#{fieldname} >= #{min} AND #{caller.quoted_table_name}.#{fieldname} < #{max})"
    else 
      "#{caller.quoted_table_name}.#{fieldname} #{match_data ? 'NOT ' : '' } BETWEEN #{min} AND #{max}"
    end
    
    return Result.new( str, nil )
  end
  nil      
end