在Rails中预构建视图缓存

时间:2011-07-26 21:31:34

标签: ruby-on-rails caching

有没有办法预先构建页面缓存而不通过http请求调用实际页面?

我查看了thisthis等解决方案,但这些解决方案并未生成缓存。

我有一个相对复杂的视图,并希望缓存整个事情。我想在应用程序中预先构建这个缓存​​版本,这样当用户实际点击它时,它就已经存在了。

由于

2 个答案:

答案 0 :(得分:2)

我们需要从rake任务中做类似的事情 - 我们有一部分需要显示一个很长的实体列表(~700),这些实体在某种程度上是特定于上下文的,并且由于一系列数据库结构问题和自定义排序标准,很容易采取>在进入缓存之前第一次渲染25秒>这通常会超时,因为我们的HTTP服务器设置为在30秒后终止HTTP请求而没有响应,并且预先缓存此自定义列表是一种解决方案。

如果需要辅助方法或其他实体,则需要创建ActiveController :: Base或其中一个控制器的实例,然后将其lookup_context引用传递给ActionView.Renderer的新实例。

在我们的rake任务中,我们做了以下

namespace :rake_for_time_consuming_nonsense do
  task :pre_cache_long_list do
    PreCacher.pre_fetch_partials
  end
end

class PreCacher
  def self.pre_fetch_partials
    the_controller = ActionController::Base.new
    # Set any instance variables required by your partial in the controller, 
    # they will be passed to the partial with the view_context reference
    the_controller.instance_variable_set "@cache_key", cache_key
    the_controller.instance_variable_set "@the_object", MyModel.first

    view_renderer = ActionView::Renderer.new the_controller.lookup_context
    view_renderer.render the_controller.view_context, {partial: 'my_model/the_partial', layout: false}
  end
end

这适用于Rails 3.2.13。

答案 1 :(得分:0)

我认为以下链接应该会给你一个良好的开端。 How do I get the rendered output of a controller's action without visiting the web page?

我尝试完成同样的操作,到目前为止我可以看到,您的虚假请求应该有正确的主机,因为缓存键包含主机信息。

我使用ActionController :: Integration :: Session

完成了缓存
ais = ActionController::Integration::Session.new
ais.host = host
ais.xml_http_request(:post, url, params, headers)

我还有另外一个:

class FakeRequest
  include ActionController::UrlWriter

  def initialize(url, params, session, host)
    @url = url
    @params = params
    @session = session
    default_url_options[:host] = URI.parse(host).host
  end

  def post
    process(:post)
  end

  def get
    process(:get)
  end

  def xhr
    process(:post, true)
  end

  def process(method, ajax = false)
    uri = URI.parse(url_for(@url))
    request = ActionController::TestRequest.new({'HTTP_HOST' => uri.host,'rack.input' => '','rack.url_scheme' => 'http'})
    request.query_parameters = @params
    request.path = uri.path
    request.host = uri.host
    request.env['REQUEST_METHOD'] = method.to_s.upcase
    if ajax
      request.headers['X-Requested-With'] = 'XMLHttpRequest'
    end
    @session.each_pair do |k,v|
      request.session[k] = v
    end

    response = ActionController::TestResponse.new

    controller = ActionController::Routing::Routes.recognize(request).new
    return controller.process(request, response)
  end
end

这也将返回响应对象。