Force Mapping on a Model Instance
Consider this:
class Post < ActiveRecord::Base
has_many :comments
def last_comment
comments.last
end
end
railsconsole> p = Post.last
Post Load (0.2ms) SELECT `posts`.* FROM `posts` WHERE ORDER BY `posts`.`id` DESC LIMIT 1
railsconsole> p.last_message
Post Load (0.4ms) SELECT `comments`.* FROM `comments` WHERE `messages`.`post_id` = 14
railsconsole> p.last_message
Post Load (0.4ms) SELECT `comments`.* FROM `comments` WHERE `messages`.`post_id` = 14
You might think that there should only be 2 queries here: an initial find and then loading the association. Subsequent calls to the association must be cached. However, it is not. The association is never loaded or cached because Rails tries to be smart and only loads the last entry. And since Rails doesn't keep track of the last entry (or the first or any other optional custom request in the association), it just returns the response every time.
However, if you want to cache the link? I've searched SO and couldn't find a direct answer to this question.
source to share
When you call a connection to an ActiveRecord instance, you return a proxy object, and in the case of a has_many object, you get a CollectionProxy.
What's odd is that you can call #load on the collection proxy, but that doesn't load the association cache.
Hidden in the Rails docs: http://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-load_target
#load_target
|
class Post < ActiveRecord::Base
has_many :comments
def last_comment
comments.load_target unless comments.loaded?
comments.last
end
end
Hope others find this helpful.
source to share