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
Jared Carroll

Pair with one of our expert developers to level up your skills with Coaching by thoughtbot. Save time learning best practices and techniques for reducing technical debt in Ember, Ruby, Haskell, and Go in 1-on-1 sessions tailored to your goals.