Skip to content

Instantly share code, notes, and snippets.

@ekampf
Last active December 12, 2015 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ekampf/4753636 to your computer and use it in GitHub Desktop.
Save ekampf/4753636 to your computer and use it in GitHub Desktop.
Add scopes to query by created_at\updated_at to models
module Concerns
module CreatedAtScopes
extend ActiveSupport::Concern
included do
%w(created_at updated_at).each do |prop|
verb = prop.gsub('_at', '')
scope "#{verb}_last_h", lambda { where("#{prop} >= ?", (Time.now-1.hour).to_s(:db)) }
scope "#{verb}_last_6h", lambda { where("#{prop} >= ?", (Time.now-6.hour).to_s(:db)) }
scope "#{verb}_today", lambda { where("DATE(#{prop}) = ?", Date.today.to_s(:db)) }
scope "#{verb}_last7d", lambda { where("DATE(#{prop}) >= ?", (Date.today-7).to_s(:db)) }
scope "#{verb}_last30d", lambda { where("DATE(#{prop}) >= ?", (Date.today-30).to_s(:db)) }
scope "#{verb}_this_month", lambda { where("DATE(#{prop}) >= ?", Date.today.beginning_of_month.to_s(:db)) }
scope "#{verb}_last_6m", lambda { where("DATE(#{prop}) >= ?", (Date.today - 6.months).to_s(:db)) }
end
end
end
end
@arikfr
Copy link

arikfr commented Feb 11, 2013

Cool!
I would add "d" to the last7/last30 methods, so make them clearer.

@ekampf
Copy link
Author

ekampf commented Feb 11, 2013

Thats interesting... should I also turn "hour" and "hours to "h" ?

@ekampf
Copy link
Author

ekampf commented Feb 11, 2013

One thing I would want to do is get all the model's DateTime attributes and automatically scope them.
For example, users have invited_at too...

Any idea how?

@elado
Copy link

elado commented Feb 11, 2013

columns.select { |c| c.type == :datetime }.collect(&:name).each do

And if your timeframes are not exactly the same for all models you could do:

timeframe_scopes 7.days, 3.hours, 1.month

and parse it on the other side.

@amitkaz
Copy link

amitkaz commented Feb 13, 2013

Nice.

You can write with the "ago" function to use everything (untested):

scope "#{verb}_last" lambda { |t| 
  t = t.ago
  t = t.beginning_of_day if t < 2.days.ago
  where(prop => t..Time.now) 
}

object.updated_last 5.days
object.created_last 2.weeks

@gmaliar
Copy link

gmaliar commented Feb 13, 2013

Very nice!
Perhaps we can make it even more dynamic by aliasing the old method_missing and add a new one that checks for Class.updated_#{integer}_#{seconds/minutes/days/months/years}_ago method (then it transforms it into the desired scope) and if it does not find it just call the original method_missing ?

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