Caching is by far the most logic-intensive part of my view code, so I would like to do fragment caching from inside a decorator, however, I cant do it.
When i do this from my decorator:
def cached_name
h.cache do
"a name here"
end
end
I get this:
You have a nil object when you didn’t expect it! You might have
expected an instance of Array. The error occurred while evaluating
nil.length
I instantiate my decorator from inside a controller
@presenter = SomePresenter::new
I am using HAML for my views
How can I succesfully cache from inside my decorator, so my view can do stuff like this
= @decorator.cached_logic_heavy_stuff
UPDATE: I have created a git repo showing my issue: https://github.com/houen/presenter_caching
UPDATE: This maybe works – see the repo
include Haml::Helpers
def another_way_to_try
self.init_haml_helpers
buffer = haml_buffer.buffer
h.with_output_buffer(buffer) do
h.cache do
h.concat "i should still not be empty"
end
end
end
Rails’
cachemethod tries to infer a cache key based on the view that it’s being called from. Since you’re not actually calling it from a view (but from inside an instance of a decorator class), I expect that it’s bombing when trying to build a cache key.You might try passing a cache key explicitly, via
h.cache "your cache key" do. With a full stack trace, you can figure out where it’s throwing the exception, and then work around that, as well. Without the full stack trace, it’s harder to help you, though.Edit: Looking at Rails’ caching code, I think this might be a deeper issue; it’s attempting to get the length of
output_buffer, which isn’t going to be available outside of your views’ contexts (that is, within Draper). You might try adding:But without testing it, I’m thinking it might not work exactly as planned without some more work. This is just a rough guess – I’d be surprised if this is actually the issue, but hopefully it gets you on the right path.
The note in the source there:
indicates that this isn’t a fully-solved problem, so you may need to do a little digging around in the Rails internals to make this one work.