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

About thoughtbot

We've been helping engineering teams deliver exceptional products for over 20 years. Our designers, developers, and product managers work closely with teams to solve your toughest software challenges through collaborative design and development. Learn more about us.