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