-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merge multi_fetch_fragments. #18948
Merge multi_fetch_fragments. #18948
Conversation
Seems like a legit approach to me 👍. Much smoother implementation than the original as well. |
Glad to hear it 👍 Given your thoughts on having the caching be automatic, do you want to keep the support for a custom cache key? <%= render partial: 'item', collection: @items, cache: ->(item) { [item, 'show'] } %> |
Yeah, I think that case still makes sense. But when you’re using the custom cache key like this, it should ignore the specific <% cache %> calls within the partials. I think using a custom cache key is going to be the minority case, so focusing on the default case first makes sense.
|
Got it 👍 |
f1295fa
to
2797cdc
Compare
@@ -33,6 +33,8 @@ class Railtie < Rails::Railtie # :nodoc: | |||
if app.config.action_view.cache_template_loading.nil? | |||
ActionView::Resolver.caching = app.config.cache_classes | |||
end | |||
|
|||
PartialRenderer.collection_cache = Rails.cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Railties tests fail because PartialRenderer
doesn't respond to collection_cache=
here. But I don't understand why it doesn't.
PartialRenderer
is set to be autoloaded, so this reference should require CollectionCaching
and include it into the renderer. I'm all ears if anybody has any ideas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've declared collection_cache
to be a mattr_reader
. There doesn't seem to be a corresponding writer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do'h! Thanks 😄
Kasper
Den 16/02/2015 kl. 07.04 skrev George Claghorn notifications@github.com:
In actionview/lib/action_view/railtie.rb:
@@ -33,6 +33,8 @@ class Railtie < Rails::Railtie # :nodoc:
if app.config.action_view.cache_template_loading.nil?
ActionView::Resolver.caching = app.config.cache_classes
end
+
You've declared collection_cache to be a mattr_reader. There doesn't seem to be a corresponding writer.PartialRenderer.collection_cache = Rails.cache
—
Reply to this email directly or view it on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ditched the initializer and used Rails.try(:cache)
in the collection_cache
definition. I still changed it to a mattr_accessor
, so Action View users outside of Rails can switch cache store if the in memory one isn't a fit.
Awesome, @kaspth! |
8c2fff0
to
af55fe0
Compare
@georgeclaghorn Thanks for the review 😄 @dhh I've pushed a commit that does a How close is this to what you want? |
@kaspth So when we hit a render collection call, you look in the partial to see if there's a <% cache call, right? Because we don't want all render collection to obviously cache unless the partials have that call. If that's the way it is, then that sounds like the way it should be! And thanks for getting this working so quickly. Very excited to try this in my latest app! |
Yes, it will only look in the cache if there's a cache call. Check these lines: https://github.com/kaspth/rails/blob/automatic-collection-caching/actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb#L30-L40 |
included do | ||
# Use Rails.cache or the fallback cache store if Action View is used without Rails. | ||
mattr_accessor(:collection_cache) do | ||
Rails.try(:cache) || ActiveSupport::Cache::MemoryStore.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could be set in railtie? Not sure if there is a Rails
defined if actionview
is used standalone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I had it as a railtie first, but then I switched to this. I should have just checked the console:
kaspth:action view kasperhansen$ irb -raction_view
irb(main):001:0> Rails
NameError: uninitialized constant Rails
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about to move Rails.cache
to ActiveSupport.cache
(and all configs and stuff) and just delegate it from Rails.cache
there? So this line will change to ActiveSupport.cache
and default storage will be chosen there?
Does it make sense? Would be this PR accepted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think we should be hanging off globals in ActiveSupport. Rails is the global context for this stuff.
On Feb 16, 2015, at 11:22, Josef Šimánek notifications@github.com wrote:
In actionview/lib/action_view/renderer/partial_renderer/collection_caching.rb:
@@ -0,0 +1,74 @@
+require 'active_support/core_ext/object/try'
+
+module ActionView
- module CollectionCaching
- extend ActiveSupport::Concern
- included do
# Use Rails.cache or the fallback cache store if Action View is used without Rails.
mattr_accessor(:collection_cache) do
Rails.try(:cache) || ActiveSupport::Cache::MemoryStore.new
What about to move Rails.cache to ActiveSupport.cache (and all configs and stuff) and just delegate it from Rails.cache there? So this line will change to ActiveSupport.cache and default storage will be chosen there?
Does it make sense? Would be this PR accepted?
—
Reply to this email directly or view it on GitHub.
af55fe0
to
b31c9ca
Compare
end | ||
|
||
def inferred_cache_name | ||
@options[:as] || @template.virtual_path.split('/').last.sub('_', '') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation says virtual_path
isn't set for inline templates: https://github.com/rails/rails/blob/master/actionview/lib/action_view/template.rb#L162.
Can someone smarter than me say if an inline template would get this far in the eligibility logic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Collection rendering is for partials only, so a render inline: …
won't ever be here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great 👍
@georgeclaghorn I guess I was illegible 😎 @dhh you had another concern on the original issue:
What do you mean by disregarded? If it's the last scenario, then we're doing it. As far as I can understand my own code 😅 |
It should do the former. This setup should work with only 1 cache:
The partial with the cache call has to match what we expect from the render collection cache. If it does not, no caching. Because otherwise the render collection cache would make a bunch of caches that don't expire on the right things. In the example above, notification.event might change sooner than notification, but if render collection just caches on notification, it won't invalidate. Makes sense? |
Right. I think it actually does work like that. We do check if the cache call matches the name (i.e. notification and not notification.event). So as long as we just generate the same key as Is that what you meant by Just Work in the original issue? |
Yes, cools. Then we’re on the same page 👍
|
@dhh phew! This cache stuff screws with your head. I'll add a test to verify this 👍 |
Haha, yeah, it’s a lot of balls to keep in the air at the same time! We’re deducing a lot of stuff here. Both the caching fit and the caching key that mixes in the partial digest.
|
@@ -34,6 +34,8 @@ class Railtie < Rails::Railtie # :nodoc: | |||
ActionView::Resolver.caching = app.config.cache_classes | |||
end | |||
end | |||
|
|||
PartialRenderer.collection_cache = Rails.cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expect this to use config.action_controller.cache_store
(ActionController::Base.cache_store
) since that's already used for fragment caching, and falls back to Rails.cache
if unconfigured.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
So I used the new tests from #20284 and then tried to tackle the The following contents for
Many of these are not idiomatic Ruby style; but still it's very strange if caching works OK when you have one space in For 1-4 above you can run |
…ate Rails include that: rails/rails#18948" This reverts commit dde8d19.
Sweet, you've found some bugs! Rather than burden this already closed pull request, can you open a new issue or if you've beat the regex (or want to do it) can you open a pull request? 😄 We should add more tests for Action View Template's |
Is this behavior mentioned in the guides? |
Not sure if this should be in a new issue or if a comment here is fine. I recently came across an issue using https://github.com/n8/multi_fetch_fragments on a long list of complicated partials. It turns out the computation of digests for the partial was being repeated ghiculescu/multi_fetch_fragments@59612d5 is my fix for it. It's a pretty simplistic fix - just disable Rails' digesting if we are providing our own cache keys - but it serves my needs. I think it would be good to add a similar sort of option to pass through to https://github.com/rails/rails/pull/18948/files#diff-738cc3c10058587e78559e48066ad0bfR54 since otherwise similar issues will come up for other people. @kaspth does this make sense? Happy to log this somewhere else if you prefer. edit: just came across n8/multi_fetch_fragments#31 so I'm not the only one having this issue. |
@ghiculescu hey 👋 Rails 5 has got you covered. It keeps a template digest cached throughout a request in development (they are expired when the request is finished, so reloading is still possible). See #20361 and my attached pull request for more. |
It's an issue in production too @kaspth - though apparently fixed in rails 5 as well #14645 (comment) |
@ghiculescu prepared SQL statements are an entirely different feature altogether from template digests. Is there something I'm not getting here? |
Any idea why |
I don't know. I haven't looked into it. However I could see a problem if you were creating many many cache items, say hundreds...to keep them all in memory before trying to write them all at the same time. So maybe it would be better to have that be configurable instead of a default. Either way if you want to add it feel free to submit a PR and we can talk more there. |
@schneems Makes total sense thanks for the explanation. I'll take a look. |
@mickey you mean other than there being no But yeah, do try to implement |
@kaspth Yes sorry about that. I discovered a little earlier that |
Isn't this incomplete since 11644fd which made it automatic if the partials are set up just right? |
Nope, check master that has the latest implementation. |
Got it, found b4558c1. For some reason I was browsing your fork instead of rails/rails. ¯\_(ツ)_/¯ |
@aried3r that's the one, yeah. 👍 |
In favor of rails/rails#18948
Fixes #18900.
Makes caching a collection of template partials faster using
read_multi
on the Rails cache store.
Some caching implementations have optimized
read_multi
so we don't haveto check in the cache store for every template.
@dhh, I will be tackling automatic caching next. This is just so my approach and choices, so far, can be reviewed.