2

course.rb

  has_many :current_users, :through => :user_statuses, :source => :user, :conditions => ['user_statuses.updated_at > ?', 1.hour.ago]

console

Loading development environment (Rails 3.2.2)
>> course = Course.find(1)
  Course Load (0.3ms)  SELECT `courses`.* FROM `courses` WHERE `courses`.`id` = 1 LIMIT 1
=> #<Course id: 1, title: "Course 1", created_at: "2012-04-17 19:17:15", updated_at: "2012-04-17 19:17:15">
>> Time.now
=> 2012-04-23 08:29:45 -0400
>> course.current_users.count
   (0.4ms)  SELECT COUNT(*) FROM `users` INNER JOIN `user_statuses` ON `users`.`id` = `user_statuses`.`user_id` WHERE `user_statuses`.`user_id` = 1 AND (user_statuses.updated_at > '2012-04-23 12:28:40')
=> 0
>> Time.now
=> 2012-04-23 08:30:07 -0400
>> course.current_users.count
   (0.4ms)  SELECT COUNT(*) FROM `users` INNER JOIN `user_statuses` ON `users`.`id` = `user_statuses`.`user_id` WHERE `user_statuses`.`user_id` = 1 AND (user_statuses.updated_at > '2012-04-23 12:28:40')
=> 0
>>

Notice when checking the 1.hour.ago condition it uses the same time as a starting point despite the 30 second difference between the times when I made the request. Exiting console and restarting it clears it out, but it happens again with a new time. This behavior exists in testing and a browser as well. How do I get a model to use a time based condition for a has_many :through find?

Preacher
  • 2,410
  • 1
  • 19
  • 29

2 Answers2

2

I believe you want to use a dynamic condition on your models relation.

Have a look at this SO question

Basically when your model loads, 1.hour.ago is evaluated only once. If I understand your question, you want it to be evaluated on each request.

Something like this (rails 3.1+) :

:conditions => lambda { |course| "user_statuses.updated_at > '#{1.hour.ago}'" }
Community
  • 1
  • 1
Kyle
  • 21,978
  • 2
  • 60
  • 61
0

Putting the query in the model at all didn't work, either in a has_many :through setup or in a method. So I ended up removing the association and putting the query in the controller. This allows the current time to be calculated when the request is made.

model:

has_many :user_statuses

controller:

@course = Course.find(params[:id])
@current_users = @course.user_statuses.where('updated_at > ?', 1.hour.ago)
Preacher
  • 2,410
  • 1
  • 19
  • 29