31st
Sometimes you need to compare an attribute of an in-memory ActiveRecord instance against its attribute in the database. The way I usually do that is to grab a fresh instance from the database like this:
class Something < ActiveRecord::Base
def previous(attribute)
self.class.find(id)[attribute]
end
end
That worked just fine in Rails 1.2. But Rails 2.0 has request-scoped query caching enabled by default, meaning that if you have already executed the same SQL that is generated by find(id), you’re going to get the exact same instance back from that call to find. This makes it impossible to compare in-memory attributes against attributes stored in the database.
The solution is to use ActiveRecord’s uncache method. This is a class method, so you’ll need to grab your class to call it like this:
class Something < ActiveRecord::Base
def previous(attribute)
self.class.uncached { self.class.find(id)[attribute] }
end
end
If you ever need to use ActiveRecord’s has_many with finder_sql, remember that the key to finder_sql is that the String get eval’d in the context of the ActiveRecord instance rather than the ActiveRecord class. So make sure you use single quotes! This prevents the String from being interpolated too soon.
Do this:
has_many :foos,
:finder_sql => 'select ... where some_id=#{id}'
Not this:
has_many :foos,
:finder_sql => "select ... where some_id=#{id}"
In the former case, the #{id} will be the id of the ActiveRecord instance. In the latter case, the #{id} will be the id of the ActiveRecord class.
placement = ImagePlacement.create!(:ignored => true) placement.ignored? # true
attr_accessible :login, :email, :password, :pass...This method is a nice way to lock down which attributes can be changed in an ActiveRecord, but it can be maddening when you’re trying to add a new attribute and you didn’t notice the attr_accessible declaration.