Skip to content

Instantly share code, notes, and snippets.

@descentintomael
Created March 12, 2014 22:46
Show Gist options
  • Save descentintomael/9518148 to your computer and use it in GitHub Desktop.
Save descentintomael/9518148 to your computer and use it in GitHub Desktop.
This adds in a set of date related scopes for any timestamp column. Date type columns aren't yet supported.
module DateScopes
extend ActiveSupport::Concern
module ClassMethods
def include_date_scopes
include_date_scopes_for :created_at
end
def include_date_scopes_for(column, prepend_name = false)
return unless self.table_exists?
if self.columns_hash[column.to_s].type == :datetime
define_timestamp_scopes_for column, prepend_name
elsif self.columns_hash[column.to_s].type == :date
define_date_scopes_for column, prepend_name
end
end
def include_named_date_scopes_for(column)
include_date_scopes_for column, true
end
protected
def define_timestamp_scopes_for(column_name, prepend_name = false)
prefix = prepend_name ? "#{column_name}_" : ""
define_singleton_method :"#{prefix}between" do |start_date_or_time, stop_date_or_time|
start_time = (start_date_or_time.is_a?(Date) ? start_date_or_time.to_time : start_date_or_time)
stop_time = (stop_date_or_time.is_a?(Date) ? stop_date_or_time.to_time + 1.day : stop_date_or_time )
where{(__send__(column_name).gte start_time) & (__send__(column_name).lt stop_time)}
end
define_singleton_method :"#{prefix}on_or_before_date" do |date|
where{ __send__(column_name).lt date.to_date.tomorrow.midnight.gmtime }
end
define_singleton_method :"#{prefix}on_or_before" do |time|
where{__send__(column_name).lte (time.is_a?(Date) ? time.to_time : time)}
end
define_singleton_method :"#{prefix}before" do |time|
where{__send__(column_name).lt (time.is_a?(Date) ? time.to_time : time)}
end
define_singleton_method :"#{prefix}on_or_after_date" do |time|
where{__send__(column_name).gte time.to_date.midnight.gmtime }
end
define_singleton_method :"#{prefix}on_or_after" do |time|
where{__send__(column_name).gte (time.is_a?(Date) ? time.to_time + 1.day : time )}
end
define_singleton_method :"#{prefix}after" do |time|
where{__send__(column_name).gt (time.is_a?(Date) ? time.to_time + 1.day : time )}
end
define_singleton_method :"#{prefix}on" do |day|
between(day.midnight, (day + 1.day).midnight)
end
define_singleton_method :"#{prefix}day" do |day|
on(day)
end
define_singleton_method :"#{prefix}last_24_hours" do
after(24.hours.ago)
end
define_singleton_method :"#{prefix}last_hour" do
after(1.hour.ago)
end
define_singleton_method :"#{prefix}last_week" do
after(1.week.ago)
end
define_singleton_method :"#{prefix}last_30days" do
after(30.days.ago)
end
define_singleton_method :"#{prefix}today" do
on(Date.today)
end
define_singleton_method :"#{prefix}this_week" do
between((Date.today - Date.today.wday.days).midnight, (Date.today + 1.day).midnight)
end
define_singleton_method :"#{prefix}this_month" do
between((Date.today.at_beginning_of_month).midnight, (Date.today + 1.day).midnight)
end
define_singleton_method :"#{prefix}yesterday" do
on(Date.yesterday)
end
define_singleton_method :"#{prefix}most_recent" do
order("#{column_name} desc")
end
end
def define_date_scopes_for(column_name, prepend_name = false)
prefix = prepend_name ? "#{column_name}_" : ""
define_singleton_method :"#{prefix}between" do |start_date, stop_date|
where{(__send__(column_name).gte start_date) & (__send__(column_name).lte stop_date)}
end
define_singleton_method :"#{prefix}on_or_before" do |date|
where{ __send__(column_name).lte date }
end
define_singleton_method :"#{prefix}before" do |date|
where{__send__(column_name).lt date}
end
define_singleton_method :"#{prefix}on_or_after" do |date|
where{__send__(column_name).gte date}
end
define_singleton_method :"#{prefix}after" do |date|
where{__send__(column_name).gt date}
end
define_singleton_method :"#{prefix}on" do |date|
where{__send__(column_name).eq date}
end
define_singleton_method :"#{prefix}day" do |day|
on(day)
end
define_singleton_method :"#{prefix}today" do
on(Date.today)
end
define_singleton_method :"#{prefix}last_week" do
after(1.week.ago)
end
define_singleton_method :"#{prefix}last_30days" do
after(30.days.ago)
end
define_singleton_method :"#{prefix}yesterday" do
on(Date.yesterday)
end
define_singleton_method :"#{prefix}most_recent" do
order("#{column_name} desc")
end
end
end
end
@descentintomael
Copy link
Author

Also its good to note that this currently relies on the Squeel gem for some of the syntax sugar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment