when things happen

Jared Carroll

Recently in a Rails app, I ran into a strange bug.

In this app, we had users and articles. A User could write any number of Article s.

class User < ActiveRecord::Base

  has_many :articles

end

class Article < ActiveRecord::Base

  belongs_to :user

end

On a User‘s personal page we show their recent articles. At first I implemented it using another #has_many like:

class User < ActiveRecord::Base

  has_many :articles

  has_many :recent_articles,
    :class_name => 'Article',
    :conditions => ['created_on > ?', 2.weeks.ago]

end

class Article < ActiveRecord::Base

  belongs_to :user

end

Now this worked for a day.

This is why.

Say this app went online at 7/15/2007. When that User class was loaded its #has_many calls got executed once, which means the value of 2.weeks.ago was 7/1/2007. So User#recent_articles would return articles created after 7/1/2007.

On 7/16/2007 User#recent_articles would still return articles created after 7/1/2007. Which is wrong because 2 weeks ago is 7/2/2007 not 7/1/2007.

In other words, ActiveRecord is only going to execute that User#recent_articles #has_many declaration once. The solution is to create an instance method instead.

class User < ActiveRecord::Base

  def recent_articles
    articles.find :all,
      :conditions => ['created_on > ?', 2.weeks.ago]
  end

end