-
Notifications
You must be signed in to change notification settings - Fork 236
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
several cache-related questions #401
Comments
I can only reply to 2.) and I think it looks totally fine to me. The point of Cells is to get away from ugly view fragment caching by modelling your view as an object (with multiple states, if you want that). Only |
Ok, got it, thanks But what about code change? Right now I have to |
Bring it on, sounds like a good feature! |
This is not as straightforward to implement as I thought. Rails' Will look into this closer when I have free time |
Yeah, but we have a better internal API where you can find the respective state template and hash it, on the class level. No problem! I'm here if you need help - maybe join Gitter and we chat there at some point. |
Yeah, that's what I thought too, but then again, someone can do def show
render :surprise
end and how will we know that... How do I find the chat-room in gitter? |
I would not dive into this template cache digest thing as it over-complicates things. We rather should go for a simpler cache getter/cleaning methods in the core. f. ex. this is some code i am using to delete the cache for specific cells: class SomeCell
cache :show do
"#{model.id}/#{model.updated_at.strftime('%Y%m%d%H%M%S')}"
end
cache :public_show do
"#{model.id}/#{model.updated_at.strftime('%Y%m%d%H%M%S')}"
end
# Delete the cache for a single or multiple states (views)
# If states is empty deletes all defined caches
# Needed whenever a view is updated, for manual deletion of the cache:
#
# Model.select(:id, :updated_at).each{|i| SomeCell.delete_cache( i, :show)}
#
# @param [aModel] obj
# @param [Array<Symbol>, Symbol] states name of cache partial see defs on top
def self.delete_cache(obj, states)
state_keys = states.is_a?(Array) ? states : [states]
state_keys ||= version_procs.keys
state_keys.each do |i|
key = cache_key(i, obj)
#btw. this does not seem to work maybe bcs my local prefix 'cache' in rails.cache_config is not prepended
::Rails.cache.delete(key)
end
end
# Get a cache key for a given object and state
# @param [aModel] obj
# @param [Array<Symbol>, Symbol] states name of cache partial see defs on top
# @return [String]
def self.cache_key(state, obj)
cell = self.(obj)
# ??
state_cache_key(state, version_procs[state].evaluate(cell))
end
end the specs continue to have a rather ugly lookup: describe 'cache keys' do
it 'has keys' do
obj = FactoryGirl.create(:a_model)
cell = cell(:some, obj)
# WTF ??
key = cell.class.state_cache_key(:show, cell.class.version_procs[:show].evaluate(cell))
expect(key).to eq ("cells/some/show/#{obj.id}/#{obj.updated_at.strftime('%Y%m%d%H%M%S')}")
end
end This could be continued with methods to destroy all caches for a cell, all caches for an object across cells, etc. I am using redis + gem readthis for caching and think about to just use http://redis.io/commands/keys command, which by the help of *-lookups would render all of the above useless. |
Yeah, after spending some time fiddling with template digesting I gave up and now use a Capistrano task that clears cell caches for cells whose file were changed between deploys |
Has anything changed? Recently run into this issue myself. I simply added a 'version' to the cell as part of my cache key, and I change that if I update the code. Not ideal, but it works. Btw, great gem! I've redesigned a monstrous Rails app recently and persevered with cells for the frontend and it has proven to be much cleaner and simpler to maintain. It is especially useful to bundle assets along with the cells. |
Here is my example for caching: module PokemonTypeCardDefaultStyle
class Cell < ::SomeBase::Cell
# === Caching === #
cache(
:show,
:cache_key,
expires_in: :cache_valid_time_period_length,
if: :can_be_cached?,
)
def can_be_cached?
# Use following code when child cell(s) is/are used
# [
# child_cell_1,
# ].all?(&:can_be_cached?)
true
end
def cache_valid_time_period_length
# Use following code when child cell(s) is/are used
# [
# child_cell_1,
# ].map(&:cache_valid_time_period_length).min
# Long time
100.years
end
def self.cache_key
super.merge(
# Update this if cell logic updated (code update != logic update)
logic: :v2017_10_26_1054,
template: TEMPLATE_FILES_CONTENT_CACHE_KEY,
translations: TRANSLATION_FILES_CONTENT_CACHE_KEY,
assets: ASSET_FILES_CONTENT_CACHE_KEY,
)
end
def cache_key
super.merge(
current_locale: ::I18n.config.locale,
pokemon_type: pokemon_type.cache_key,
)
end
# === Caching === #
def show
render
end
private
Contract ::Pokemon::Type
attr_reader :pokemon_type
TEMPLATE_FILES_CONTENT_CACHE_KEY = begin
view_folder_path = File.expand_path("views", __dir__)
file_paths = Dir.glob(File.join(view_folder_path, "**", "*"))
file_digests = file_paths.map do |file_path|
next nil unless File.file?(file_path)
::Digest::MD5.hexdigest(File.read(file_path))
end.compact
::Digest::MD5.hexdigest(file_digests.join(""))
end
private_constant :TEMPLATE_FILES_CONTENT_CACHE_KEY
TRANSLATION_FILES_CONTENT_CACHE_KEY = begin
folder_path = ::Rails.root.join(
"config/locales/path/to/cell/translations",
)
file_paths = Dir.glob(File.join(folder_path, "**", "*"))
file_digests = file_paths.map do |file_path|
::Digest::MD5.hexdigest(File.read(file_path))
end
::Digest::MD5.hexdigest(file_digests.join(""))
end
private_constant :TRANSLATION_FILES_CONTENT_CACHE_KEY
ASSET_FILES_CONTENT_CACHE_KEY = begin
folder_path = ::Rails.root.join(
*[
"app/assets/images/path/to/cell/assets",
].join("/").split("/"),
)
file_paths = Dir.glob(File.join(folder_path, "**", "*"))
file_digests = file_paths.map do |file_path|
next nil unless File.file?(file_path)
::Digest::MD5.hexdigest(File.read(file_path))
end
::Digest::MD5.hexdigest(file_digests.join(""))
end
private_constant :ASSET_FILES_CONTENT_CACHE_KEY
end
end If you need to a cell to depend on super cell's cache key: module PokemonTypeCardCompactStyle
class Cell < ::PokemonTypeCardDefaultStyle::Cell
# === Caching === #
def self.cache_key
super.merge(
# Update this if cell logic updated (code update != logic update)
logic: [
super.fetch(:logic, nil),
:v2018_09_17_1426,
].compact.join("+"),
template: TEMPLATE_FILES_CONTENT_CACHE_KEY,
)
end
def cache_key
super.merge(
current_locale: ::I18n.config.locale,
pokemon_type: pokemon_type.cache_key,
)
end
# === Caching === #
def show
render
end
TEMPLATE_FILES_CONTENT_CACHE_KEY = begin
view_folder_path = File.expand_path("views", __dir__)
file_paths = Dir.glob(File.join(view_folder_path, "**", "*"))
file_digests = file_paths.map do |file_path|
next nil unless File.file?(file_path)
::Digest::MD5.hexdigest(File.read(file_path))
end.compact
::Digest::MD5.hexdigest(file_digests.join(""))
end
private_constant :TEMPLATE_FILES_CONTENT_CACHE_KEY
end |
yeah, i ended up doing something similar two years ago. i'm not using cells right now though |
Currently I've come up with something like this
And then I have
show.erb
which has all the html (and this state is cached), and (uncached)js.erb
that has all the access to cell instance variablesWhat d'you think?
Btw, for some weird reason I have to write
call(:html) + render(:js).html_safe
, otherwise the js template gets escapedThe text was updated successfully, but these errors were encountered: