I’ve noticed that in my applications I often have to choose between the 
efficiency of caching and the efficiency of the .includes() method, and I’m 
wondering if these two are mutually exclusive. Am I doing something wrong?

Here’s an example. Let’s say I’ve got a Posts model, and each Post has_many 
Authors.

Controller:
@recent = Posts.order(created_at: :desc).includes(:authors)

View:
<% cache @recent do %>
  <% @recent.each do |post| %>
    <%= post.authors.map{ |a| a.name }.joins('') + post.title %>
  <% end %>
<% end %>

Okay, so my issue here is:

If the cache key is just based on the Posts, then the controller code will 
pull the Authors association for no reason (we don’t actually need it, 
because the author names are cached until the Post models are touched). 
This makes me think I should remove the .includes() call from my 
controller, since it will cause an unnecessary db query 99% of the time.

On the other hand, if I remove the .includes() call from my controller, 
then whenever the cache *does* expire, I have an *n*-queries situation, 
which also seems bad.

Is there any way to have the best of both worlds here?

A related question:

I’ve also found it helpful to use lower-level caching in my Post model to 
cache the “recent” query like so:

post.rb
self.recent do
  Rails.cache.fetch('recent_posts’, expires_in: 1.day) do
    self.order(created_at: :desc).to_a
  end
end

Here I have a similar problem. If I don’t include the `.to_a` at the end, 
then I’m only caching the *scope*, which will still evaluate and seemingly 
(at least in development) trigger a db query on every pageview. If I *do* 
include 
the `.to_a` then I forfeit the ability to use `.includes()` in my 
individual controller actions or views.

Again, is there a way to have the best of both worlds here?

Thanks for any ideas and pointers people might have! Cheers,

Brian

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rubyonrails-talk/0c11567b-dfba-49bc-9393-15979dd945d1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to