DEV Community

Discussion on: Collection Caching in Rails with Local Variables

Collapse
 
craz8 profile image
Tom Fakes • Edited

If you can isolate what it is about the user that causes the differences, you should use that as part of your cache key instead of current_user.

e.g. If you look at 'current_user.admin?' to decide what to display, then that part of the code becomes:

cached: ->(collection_item) { [collection_item, current_user.admin?] }

And now you have only 2 versions of the cached item instead of one for each user. Getting this right is tricky, but worth it!

One thing I hate about Rails Views is that @ variables (and helper methods like current_user) can be used anywhere, and someone can come along at any time, add an @testing_mode or whatever to your partial and break the site until Customer Support gets calls about 'weird stuff happening'

Collapse
 
craz8 profile image
Tom Fakes

I think View Components is going to improve things a lot in this area by isolating the 'partial' from the global context to reduce this backdoor data access that breaks caching

Collapse
 
briankephart profile image
Brian Kephart

I haven't used that library, but yeah, isolated context with all variables passed in as arguments would make it harder to screw up the caching.

Collapse
 
briankephart profile image
Brian Kephart

That would be ideal. In this case however, we have a variety of roles (owner, manager, assistant manager, teacher, substitute teacher), all with different permissions. Isolating those roles would still be an improvement, except there is still behavior specific to whether a user is attached to the item in another, non-role-based way (like this specific person is the teacher of a class, so they can check it out). So the user goes in the cache key.

Still, employees interact with the schedule repeatedly throughout the day, and items on the schedule can be shared between daily/weekly/individual/all-employee views, so even at the user level caching pays off.

Any thoughts on the lambda use? I haven't gotten any comments yet (here or on Twitter) indicating that anyone else has used it. I also can't tell whether the usage is really, really officially supported (Good: specifically approved via PR! Bad: Not documented anywhere outside of the PR).

Collapse
 
craz8 profile image
Tom Fakes

I've never seen this lambda version of the cache key. The Rails collection cache code is quite easy to read. This is the line from github that gets your lambda - and if you don't provide one, they create a default one!

github.com/rails/rails/blob/b378bd...

I usually create a wrapper object that implements a cache_key method to do the key generation. It also is then used inside the partial, so it's a little more noticable when you use data that isn't part of the cache key

For your case, you can do more in here for a complicated case

[ collection_item, current_user.user_role, current_user.teaches_class?(collection_item) ]

I've had object IDs and 4-5 booleans or enums in my cache key before now. Having 30 possible variants is still better than having 1 per user (unless you have only 30 users, in which case you may have optimized too soon)