使用分页(kaminari)时,如何使用dalli实现片段缓存?

时间:2013-01-27 04:22:24

标签: ruby-on-rails ruby-on-rails-3 dalli

我知道dalli(缓存)是非常强大的插件,可以增强静态页面的性能 但是,具有分页功能的动态页面会经常更新呢? 设置dalli的正确方法是什么?

我遇到的一个问题例如:dalli在使用分页时将不同的参数[:page]识别为同一页面:(

如果将dalli用于

,您将如何设计系统?
  • 经常更新的页面
  • 不经常更新的页面

例如。我有4个模型,例如UserCommunityTopicComment(defined Polymorphic to both Community, and Topic. They can be created or shown in #show pages)

就像

  • 社区> (has_many)>主题> (has_many)>评论
  • 社区> (has_many)>评论
  • 所有这些都属于用户(创作者)

我目前的代码就像这样(这有点长。很抱歉) 我在使用缓存时遇到了分页问题......

------------------------------- 设置 - --------------------------------------

配置/环境/ development.rb

config.consider_all_requests_local       = true
config.action_controller.perform_caching = true
config.cache_store = :dalli_store

的routes.rb

resources :communities do
    resources :topics do
        resources :comments do
    end
end

------------------------------- 社区 - --------------------------------------

控制器/ communities_controller.rb#索引&安培;显示

caches_page :show
caches_action :edit, :new

def index
    ....
    if params[:sort] == 'new'
        @communities = Community.scoped.page(params[:page]).order("created_at DESC")
    elsif params[:sort] = 'popular'
        @communities = Community.scoped.page(params[:page]).order("follow_count DESC")
    elsif params[:sort] = 'reputation'
        @communities = Community.scoped.page(params[:page]).order("reputation_count DESC")
    else
        @communities = Community.scoped.page(params[:page]).order("created_at DESC")
    end
    ....
end

def show
    @community = Community.find(params[:community_id])
    @comments @community.comments.page(params[:page]
    @topics = @community.topics.limit(10)
end

视图/社区/ index.html.erb 注意:但是,即使我移动到下一个参数[:page],内容也是一样的:(似乎缓存识别不同的页面作为相同的内容......

#here, the url will could be something like this example.com/communities?utf8=✓&location=14&genre=3&search=strawberry
 But this is going to create gigantic petterns of the caches:(  
 So I want to make it work only when params[:sort] was not empty. Because, no other parameters come with when params[:sort] is not empty. 
 It could be like, example.com/communities?sort=new, example.com/communities?sort=popular, example.com/communities?sort=reputation


...
<% if params[:sort] %>
    <% @key = "community_index_" + params[:sort] + params[:page] %>

    <% cache(:controller => "communities", :action => "index", :action_suffix => @key) do %>
        <%= page_entries_info(@communities, :entry_name => 'community').html_safe %>
        <%= paginate @communities, :window => 4 %>

        <% @communities.each do |community| %>  
            <%= render 'communities/community', :community => community %>
        <% end %>
    <% end %>
<% end %>
...

视图/社区/ show.html.erb

...
<% @key = params[:community_name] + "_community_show_information" %>
<% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %>
    <h2>Information</h2>
    <div class="CommunityInformation">
        <%= render 'communities/information'%>
    </div>
<% end %>


<% @key = params[:community_name] + "_community_show_wall_" + params[:page] + %>
<% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %>
<%= paginate @comments, :window => 4 %>
    <h2>Topic</h2>
    <div class="WallInformation">
        <%  @comments.eager.recent.each do |comment| %>
            <%= render 'communities/comment', :comment => comment %>
        <% end %>
    </div>
<% end %>

<% @key = params[:community_name] + "_community_show_topics" %>
<% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %>
    <h2>Topic</h2>
    <div class="TopicInformation">
        <%  @topics.eager.recent.each do |topic| %>
            <%= render 'communities/topic', :topic => topic %>
        <% end %>
    </div>
<% end %>
...

模型/ community_sweeper.rb

class CommunitySweeper < ActionController::Caching::Sweeper
  observe Community


  def after_save(record)
    expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the community#index)')
    expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular community#show)')
  end
end

end

-------------------------------------的主题 - --------------------------------------

控制器/ topics_controller.rb#索引&安培;显示

caches_page :show
caches_action :edit, :new

def index
    ....
    @community = Community.find(params[:community_id])
    @topics = @community.topics.page(params[:page]
    ....
end

def show
    @topic = Topic.find(params[:id])
    @comments = @topic.comments.page(params[:page]
end

views / topics / index.html.erb

...
<% @key = params[:community_id] + "_topic_index_"  + params[:page] %>
    <% cache(:controller => "topics", :action => "index", :action_suffix => @key) do %>
        <%= page_entries_info(@communities, :entry_name => 'community').html_safe %>
        <%= paginate @communities, :window => 4 %>

        <% @communities.each do |community| %>  
            <%= render 'communities/community', :community => community %>
        <% end %>
    <% end %>
<% end %>
...

视图/主题/ show.html.erb

...    
<% @key = params[:community_name] + "_topic_show_" + params[:id] + "_comments" + params[:page] %>
    <% cache(:controller => "topics", :action => "show", :action_suffix => @key) do %>
         <%= paginate @comments, :window => 4 %>
         <%= page_entries_info(@comments, :entry_name => 'comment').html_safe %>

         <h2>Comment</h2>
         <div class="CommentInformation">
         <% @comments.each do |comment| %>
             <%= render 'topics/comment', :comment => comment %>
         <% end %>
    </div>
<% end %>
...

模型/ topic_sweeper.rb

class TopicSweeper < ActionController::Caching::Sweeper
  observe Topic


  def after_save(record)
    expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the topic#index)')
    expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular topic#show)')
  end
end

-------------------------------------的注释 - --------------------------------------

模型/ comment_sweeper.rb

class CommentSweeper < ActionController::Caching::Sweeper
  observe Comment


  def after_save(record)
    expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the topic#index)')
    expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular topic#show)')
  end
end

1 个答案:

答案 0 :(得分:2)

我正在继续回答

How should I set up dalli for a dynamic page with lots of content updates?

请注意我不是专家,但我确实尝试了你的方法并放弃了它,因为随着我的应用程序的增长它变得越来越复杂,我选择了上一个问题中提到的基于缓存密钥片段的方法。有几点需要牢记。

  1. 缓存清理程序方法要求您在对应用程序进行更改时确保清理程序是最新的,这意味着需要额外的维护和测试工作。

  2. 在动态应用程序中,您可能无法轻松缓存整个页面,尤其是如果视图显示来自许多模型的信息。

  3. 除非页面参数成为缓存键的一部分,否则您无法处理分页问题。

  4. 当您的缓存已满时,memcached将在放入新的缓存片段时删除使用最少/最旧的缓存项。

  5. 因此,当您的模型更改并让memcached清除旧的过时缓存项时,只需插入新的缓存片段就没有问题。

  6. 因此,视图中的片段缓存可能是最简单的解决方案,因为它将处理分页,您不必处理手动缓存失效

    所以看一下你的观点,我可能会做的是

    <% if params[:sort] %>
    
            <%= page_entries_info(@communities, :entry_name => 'community').html_safe %>
            <%= paginate @communities, :window => 4 %>
    
            <% @communities.each do |community| %>  
                <% cache(community, :suffix => "community_index") do 
                    <%= render 'communities/community', :community => community %>
                <% end %>
            <% end %>
    <% end %>
    

    我所做的是缓存每个社区记录的呈现,并且分页变得无关紧要