compare datetime in find conditions - ruby-on-rails

I am trying to get all users that are updated maximum 90 seconds ago:
User.find(:all, :include => { :core => :image },
:conditions => ["updated_at > ?", Time.now - 90.seconds] )
But it doesn't work.
why?
how can i do?
thanks

If you set config.time_zone in your environment.rb to anything other than UTC, you need to do
User.find(:all, :include => { :core => :image },
:conditions => ["updated_at > ?", Time.now.utc - 90.seconds] )
I'm going to assume that image is an attribute of an association called core?

Do you need to specify users.updated_at

It can be time zone problem. Try to find out Time.now - 1.day, if it'll work, so set your Time.zone in application controller.
And second, you can try your construction without :include option if it cause your problem

Related

How do date comparisons work in ActiveRecord?

I am new to Rail and trying to make a query in ActiveRecord. I am trying to get all of the records with the status of 'Landed', that are over 60 days old. My query works up to the point of getting all of the projects with the status of 'Landed'. When I add in the last condition of "created_at < ? ", then I always get an empty relation. I know that I have projects that fit that description, so I am doing something wrong in my query and dont understand. I believe my error is in the date comparison, but I am not sure.
1. Projects
belongs_to :status
has_many :project_status_histories
2. Status
has_many :projects
has_many :project_status_histories
3. Project_Status_Histories
belongs_to :status
belongs_to :project
Project.find(:all, :joins => [:project_status_histories, :status], :conditions => {:projects => {:status_id => Status.where(:name => 'Landed').first.id }, :project_status_histories => {:created_at => ["created_at < ?", (Date.today - 60.days)]}})
I have tried to build the query, step by step, with the dbconsole and am not having any luck. Thanks for all the help in advance.
I don't think it's the date arithmetic. One nice way to do this would be with named scopes. Add the following to project.rb:
scope :landed, joins(:status).where('statuses.name' => 'Landed')
scope :recent, lambda \
{ joins(:project_status_histories) \
.where('project_status_histories.created_at < ?', Date.today - 60.days) }
Then you can retrieve the relevant records/objects with:
Project.landed.recent
This worked for me in my test. You should also check out the rails guide, from which I stole most of this:
http://guides.rubyonrails.org/active_record_querying.html#scopes
Your query is a little bit complicated...
I would rather do it like this:
Project.where("status.name = ? AND project_status_histories.created_at < ?", "Landed", Time.now.day - 60.days)
I think this should work better. Let me know if it doesn't, maybe I've wrote something wrong, unfortunately I can't test it right now...
[Edit]
You also might want to see what is the generated SQL, use the "explain" method for that, just add it to the end of your query and print the result, for instance with your query:
Project.find(:all, :joins => [:project_status_histories, :status], :conditions => {:projects => {:status_id => Status.where(:name => 'Landed').first.id }, :project_status_histories => {:created_at => ["created_at < ?", (Date.today - 60.days)]}}).explain

How do you select individual groups of 1000 objects?

At first I was trying to do this :
Photo.find(:all, :conditions => ["id < 2000 AND id > 999"])
But then I realized that this isn't necessarily 1000 objects. How do I select exactly a thousand objects. So that I can run a process that works 1,000 objects at a time. Such as this..
Photo.find(:all, :conditions => ["id < 2000 AND id > 999"]).each{|instance| instance.photo.reprocess!(:tiny_thumb) }
You'd want to use :limit and :offset:
# First chunk
Photo.find(:all, :order => :id, :limit => 1000)
# Second chunk
Photo.find(:all, :order => :id, :limit => 1000, :offset => 1000)
You need to include the :order to ensure consistent results, otherwise the entries won't necessarily come out in the same order that will mess up your chunking.
Use find_in_batches: http://apidock.com/rails/ActiveRecord/Batches/find_in_batches
with a :batch_size of 1000, which also happens to be the default.

Rails: Getting the most recent datetime in a child model

I have the parent model of user and user has_many :events. From the user view, how can I find the most recent datetime (event.time) of event?
I'm thinking that a find_by will work, but I'm not sure on how to do that.
Something like this.
user.events.find(:first, :order => "time DESC")
You can read more here:
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M001777
user.events.find(:all, :order => 'time desc', :limit => 100)
where limit is number of recent events you need or:
user.events.find(:first, :order => 'time desc')
if you need one most recent event.
user.events.find(:first, :order => 'time desc').time
like this you can get the event time
Just in case anyone stumbles upon this, the find first helper:
user.events.find(:first, :order => 'time desc').time
is now deprecated and removed as of Rails 3.2. You should use
user.events.order("time desc").first.try(:time)
instead.

Ruby on Rails query by datetime range ( last 24, 48, etc... hours )

I'm trying to build a query that will search for recent entries based on column 'last_login_at'. This is a datetime field with time zone (i.e. Time.zone.now)
When I execute
User.find(:all, :conditions => ["last_login_at < ?", 24.hours.ago])
I get nothing.
Alternatively I can define today as Time.zone.today and yesterday as Time.zone.today - 1.day
and run
User.find(:all, :conditions => ["last_login_at between ? and ?", today, yesterday])
and it still returns 0 results. I know there are some entries that fall into this category.
Old question, but here's newer syntax:
User.where(last_login_at: 3.days.ago..DateTime.now)
Ensure that the timezones you have recorded within the database and those your rails app is outputting are equal. This can sometimes cause an issue. Otherwise try this named scope:
class User < ActiveRecord::Base
named_scope :last_loggedin_before, lambda { |time_ago| { :conditions => ['last_login_at < ?', time_ago] } }
named_scope :last_loggedin_within, lambda { |time_ago| { :conditions => ['last_login_at > ?', time_ago] } }
end
allowing you to do:
User.last_loggedin_before 24.hours.ago
or
User.last_loggedin_within 24.hours.ago

How to find a record created on the previous month?

I have a table where new records are added daily. How would I go about finding records created in the previous month?
Set up a named scope:
named_scope :in_last_month, :conditions => [ "records.created_at > ?", 1.month.ago ]
To call it (in your controller):
Record.in_last_month
The named_scope is a rather elegant way to go, I think, but if you take that route you will want to use it with a lambda method so that the time doesn't get scoped to when the application is initially loaded.
For example, this:
named_scope :last_month, :conditions =>
['created_at > ? AND created_at < ?',
Date.today.last_month.beginning_of_month, Date.today.beginning_of_month]
will work properly the first month your application is up, but improperly the next month, unless the app gets restarted.
But this:
named_scope :last_month, lambda {
{:conditions => ['created_at > ? AND created_at < ?',
Date.today.last_month.beginning_of_month, Date.today.beginning_of_month]}}
will work every time, because the lambda method gets executed on every call, reevaluating the Date.todays.
The accepted answer and lambda improvement do not work in Rails 4.
Update for Rails 4:
scope :last_month, -> {
where( 'created_at > ? AND created_at < ?',
Date.today.last_month.beginning_of_month,
Date.today.beginning_of_month )}
Assuming your records are timestamped, you can just do something like this:
Thing.find(:all, :conditions => ["created_at > ?", Time.now - 1.month])
If they're not timestamped, you should start storing the information since it's something you'll want to look up later.
Thanks everyone, I ended up going with this:
find(:all, :conditions => ['created_at > ? AND created_at < ?', Date.today.last_month.beginning_of_month, Date.today.beginning_of_month])
In one of my projects i used this way:
Thing.where('created_at BETWEEN ? AND ? ', DateTime.now.beginning_of_month - 1.month, DateTime.now.beginning_of_month)
in Rails 3 using last_month throws an error: Date.today.last_month.beginning_of_month
NoMethodError: undefined method `last_month'
Try this for Rails 4+, note that Date.current will use your application's timezone (specified in application.rb):
scope :created_last_month, lambda {
where(created_at: Date.current.last_month.beginning_of_month..Date.current.last_month.end_of_month)
}
Do you have the "usual" fields on your table? See the RoR wiki for a list of them. That way, you can express special queries to find an answer.
Thing.find(:all, :conditions => ["created_at > ?", 1.month.ago.at_beginning_of_month])
this is a good candidate for SQL's BETWEEN syntax
named_scope :last_month, :conditions => ['created_at BETWEEN ? AND ?', Date.today.last_month.beginning_of_month, Date.today.beginning_of_month])

Resources