I my app, my views are generated according to users actions and rights.
I would like to implement rails_digest to cache my pages but I need to do this per user.
I know it's possible in fragment cache:
<% cache "mypage", project, user %>
But this doesn't seem to work in rails_digest.
Any clue?
I found the way to do it:
just write: <% cache [user, project] do %> ... <% end %>
When something changes in the project, all you need to do is project.touch. The cache will be reset for everyone.
Related
In a Rails 6 app, I have a page that shows all the users who are admins.
Since the list changes very seldom I'd like to cache the fragment.
How can I handle such a cache?
I suppose to invalidate it I should have some kind of after_save callback in the user model to check if the saved user just became an admin or he's not anymore.
Any ideas?
No need for callbacks. You can set cache key, so every time there is new admin, key will change and new cache will be generated. For example:
<% cache "admin-list-#{#admins.count}" do %>
<% #admins.each do |admin| %>
<%= admin.name %>
<% end %>
<% end %>
In case when admin details will change and number of admin users will be the same, you can use collection caching:
https://guides.rubyonrails.org/caching_with_rails.html#collection-caching
<%= render partial: 'users/admin', collection: #admins, cached: true %>
To test caching in development use this command:
rails dev:cache
I am trying to build an ecommerce page using rails. In my products page I want to add products with an image, description, color and price. Everything works properly except for the images. I am not able to assign proper image to the desired product. If i use this syntax : <%= image_tag("/assets/6.jpeg", class: "img-fluid") %>, then this particular image is assigned to all other products and it's definitely not logical!
I have already added the images which I need for my project in the app/assets/images folder. I want to have the possibility to dynamically add/modify the photos on my page.
Please help me how to solve this issue. Thanking you guys in advance!
if images file are saved 1.jpeg-?.jpeg you could loop say
<% #product.each_with_index do |product, index| %>
<% i = index + 1 %>
<%= image_tag("assets/#{i}.jpeg"), class: 'image-fluid' %>
<% end %>
I mean for what you're asking this would work but is probably not the best way to go about this.
In my app I am trying to incorporate better fragment caching.
Is it a best practice to do call fragments like this:
<% cache("user/#{current_user.id}/info") do %>
<%= current_user.email %> information goes here
<% end %>
Yes you are doing it right!
Why?
The cache fragment's key must reflect the "uniqueness" of the content:
Statement: Your content is uniq for each user
Conclusion: Your fragment's key must be different for each user
Usage: using the user's id is the best choice since every user id is uniq!
I'm using fragment cache but i have inline code that is user specific like:
<% cache #page do %>
stuff here
<% if current_user %>
user specific
<% end %>
more here
<% end %>
So i want to exclude the several blocks of code that are user specific. Is there a way to do that in Rails or should i make an if statement in the beginning and make different caches for logged users and regular visitors? (i will have major duplication of code this way).
For per-user fragments, you can put models in array an array:
<% cache [#page, current_user] do %>
Rails will make a cache-key out of them, like:
pages/page_id-page_timestamp/users/user_id-user_timestamp
This way your fragments will be invalidated on a user/page update since the time-stamps are coming from their updated_at (see cache_key for details).
Using Rails 3.1.1 and Heroku.
I believe this should be a fairly easy fix but I cannot find (and easily verify) how to do this. I have a very slow controller (6 sec) Product#show, with lots of N+1 and other things I will have to solve.
The website is a two-column website (main-column and right-column) where the main content from Product#show is shown in one column and daily product are shown in the other, including a "Random Product from the Database".
What I want to do is to let the content in main-column that is created by Product#show be cached (and thus bypass the controller and win 6 seconds). I do, however, want the right column to be dynamic (and loaded for each page request).
If I use caches_page :show it will cache the entire website, including the right-column, which makes me have to expire the cache every day in order to be able to load a new Daily Product. Not a good solution.
If I use cache('product-show' + #product.slug) do it only caches the view (right?) and still have to go through the controller.
So, how can I solve this?
You can achieve this with fragment caching like below:
def show
if !fragment_exist?("main_content")
#products = Product.all
#users_count = User.count
end
#random_products = Product.order("RANDOM()").limit(10)
end
show.html.erb
<!--MAIN CONTENT-->
<% cache("main_content") do %>
<%= #users_count %>
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% end %>
<!--SIDE CONTENT-->
<% #random_products.each do %>
<%= product.name %>
<% end %>
Use fragment caching, and don't load things in the controller.
If you have a very complex query, let it live in the controller as a scope, and only evaluate it in the view.
If you have a complex process to do so the query must be executed, use a helper method.
If you manage to just load lazy queries in the controller, if the cache is hit none of them will be executed.