如何使用分页和搜索表单进行缓存?

时间:2017-03-30 23:37:50

标签: ruby-on-rails ruby ruby-on-rails-3 caching pagination

我在rails上使用ruby并缓存了我的产品视图,我可以找到带有搜索表单的产品。我也希望使用分页,但添加时,它不起作用,也搜索表单。找到代码行,但不知道如何使用它,代码如下。

<% cache ["v1-#{params[:page]-#{params[:q]", cache_key_for_products]
> do %>

我的代码

Index.html.erb

<div class="products">
  <div class="container">
    <center><h1>All products</h1></center>
    <div class="row">
      <% cache(cache_key_for_products) do %>
      <%= render @products %>
      <% end %>
    </div>
    <%= will_paginate @comments, :container => false %>
  </div>
</div>

_product.html.erb

<% cache product do %>
<div class="col-md-3 col-lg-3 col-sm-6 col-xs-12">
  <div class="product-block">
    <h4 id="product-name"><%= product.name %></h4>
    <%= link_to product_path(product), class: 'product_link' do %>
      <%= image_tag(product.image_url, class: "img-responsive") %>
    <% end %>
    <div class="price">
      <h4>&pound; <%= product.price %></h4>
    </div>
  </div>
</div>
<% end %>

products_helper.rb

module ProductsHelper
  def cache_key_for_products
    count          = Product.count
    max_updated_at = Product.maximum(:updated_at).try(:utc).try(:to_s, :number)
    "products/#{params[:q] || "all"}-#{count}-#{max_updated_at}#{signed_in? && current_user.admin? ? "-admin" : "normal"}"
  end
end

products_controller.rb

def index
    if params[:q].present?
      search_term = params[:q]
      if Rails.env.development?
        @products = Product.where("name LIKE ?", "%#{search_term}%")
      else
        @products = Product.where("name ilike ?", "%#{search_term}%")
      end
    else
      @products = Product.all.paginate(:page => params[:page], :per_page => 30)
    end
  end

1 个答案:

答案 0 :(得分:1)

在您的控制器中,看起来您在不执行搜索时正确分页,但还需要将分页添加到搜索查询中:

  def index
    if params[:q].present?
      search_term = params[:q]
      if Rails.env.development?
        @products = Product.where("name LIKE ?", "%#{search_term}%").paginate(:page => params[:page], :per_page => 30)
      else
        @products = Product.where("name ilike ?", "%#{search_term}%").paginate(:page => params[:page], :per_page => 30)
      end
    else
      @products = Product.all.paginate(:page => params[:page], :per_page => 30)
    end
  end

此外,您正在缓存每个搜索结果集,这意味着在许多不同的搜索中,相同的产品可能会被多次缓存。这将很快膨胀您的缓存。最好一次缓存每个产品,并从缓存中获取这些产品,无论搜索结果如何。

我看到你正在缓存每个产品(_product.html.erb部分)。在index.html.erb中将代码更改为:

<div class="products">
  <div class="container">
    <center><h1>All products</h1></center>
    <div class="row">
      <%= render @products, cache: true %>
    </div>
    <%= will_paginate @comments, :container => false %>
  </div>
</div>

这将利用Rails 5 has built in

的多次获取片段缓存
  

1.3.1收集缓存

     

渲染助手还可以缓存为a渲染的各个模板   采集。它甚至可以在前一个示例中使用每个   一次读取所有缓存模板而不是逐个读取。这是   通过传递缓存来完成:渲染集合时为true:

     

&lt;%=渲染部分:'产品/产品',集合:@products,缓存:   true%&gt;之前渲染的所有缓存模板都将在此处获取   一次以更快的速度。此外,没有的模板   尚未缓存的将被写入缓存并在下一次提取多个   渲染。

否则如果你是&lt; Rails 5,使用Multi Fetch Fragments gem来启用此功能。

index.html.erb中,您可以将集合缓存呈现修改为使用自定义缓存键的内容:

<%= render @products, cache: Proc.new{|item| [item, 'show']} %>