Module: DateScopes::ClassMethods

Defined in:
lib/date_scopes.rb

Instance Method Summary collapse

Instance Method Details

#has_date_scopes(options = {}) ⇒ Object

Adds a number of dynamic scopes and a virtual accessor to your model. Functionality is detailed more fully in the README for this gem, but a brief demo is given here:

Examples:

class Post < ActiveRecord::Base
  has_date_scopes
end

Post.published                  #posts with published_at before Time.now
Post.unpublished                #posts with published_at after Time.now
post = Post.new
post.published = true           #virtual setter, sets published_at to Time.now
post.published_at == Time.now   #true
post.published? == true         #true
post.published = false          #virtual setter, sets published_at to nil
post.published_at.nil?          #true

Parameters:

  • opts (Hash)

    The options

Raises:

  • (ActiveRecordError)

    An exception will be raised if the required column is not present, telling you the name of the column it expects.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/date_scopes.rb', line 26

def has_date_scopes(options = {})
  options.to_options!.reverse_merge! :column => 'published'
  column_name = "#{options[:column]}_at"
  
  raise ActiveRecord::ActiveRecordError, "Could not find the #{column_name} column on the #{table_name} table" unless column_names.include? column_name
  
  on_scope_sql = "#{table_name}.#{column_name} <= ?"
  
  un_scope_sql = "#{table_name}.#{column_name} >= ? OR #{table_name}.#{column_name} IS NULL"
  
  scope options[:column], lambda { where(on_scope_sql, Time.now) }
  %w{un non non_ not_}.each do |prefix|
    scope prefix+options[:column].to_s, lambda { where(un_scope_sql, Time.now) }
  end
  
  define_method options[:column].to_s+'=' do |value|
    value = %w{true 1}.include? value.downcase if value.is_a? String
    value = value == 1 if value.is_a? Fixnum
    
    if value && !self[column_name]

      self[column_name] = Time.now

    elsif !value

      self[column_name] = nil
    end
  end
  
  define_method options[:column] do
    return false unless time = self[column_name]
    time <= Time.now
  end
  alias_method options[:column].to_s+'?', options[:column]
  
end