【问题标题】:render_to_string from a rake task来自 rake 任务的 render_to_string
【发布时间】:2011-11-23 00:32:16
【问题描述】:

我想使用 Rake 任务来缓存我的站点地图,这样对sitemap.xml 的请求就不会永远持续下去。到目前为止,这是我所拥有的:

  @posts = Post.all

  sitemap = render_to_string :template => 'sitemap/sitemap', :locals => {:posts => @posts}, :layout => false
  Rails.cache.write('sitemap', sitemap)

但是当我尝试运行它时,我得到一个错误:

undefined local variable or method `headers' for #<Object:0x100177298>

如何在 Rake 中将模板渲染为字符串?

【问题讨论】:

标签: ruby-on-rails rake


【解决方案1】:

我是这样做的:

  av = ActionView::Base.new(Rails::Configuration.new.view_path)
  av.class_eval do
    include ApplicationHelper
  end

  include ActionController::UrlWriter
  default_url_options[:host] = 'mysite.com'

  posts = Post.all

  sitemap = av.render 'sitemap/sitemap', :posts => posts
  Rails.cache.write('sitemap', sitemap)

请注意,我将模板转换为部分模板以使其正常工作

【讨论】:

  • 你在哪里使用 default_url_options 哈希?
【解决方案2】:

有一个post 关于如何能够从 rake 任务访问 ActionView::Base 方法和上下文。

但是,这是一个猴子补丁。为什么不使用 rails 的cache mechanism 来完成缓存呢? :)

后期编辑: render_to_string 函数在 ActionController::Base 上下文中定义。

以下是关于如何通过 rake 任务使其工作的解决方案,取自 omninerd

# In a rake task:
av = ActionView::Base.new(Rails::Configuration.new.view_path)
Rails.cache.write(
  "cache_var", 
  av.render(
    :partial => "view_folder/some_partial", 
    :locals => {:a_var => @some_var}
  )
)

【讨论】:

  • 缓存机制很棒,但有时您真的只是想定期将内容离线生成到文件中。一个 rake 任务是一个完美的地方 - 很好的链接。
  • 我无法使用缓存,因为我无法在响应 HTTP 请求时渲染站点地图一次,因为它需要 30 多秒,而 Heroku 在 30 秒时超时 HTTP 请求
  • 你说得有道理。那么,粘贴链接中的方法对您有用吗?
  • 实际上,当我将 .builder 设为部分时,这 确实 起作用。现在,当我尝试调用 x_url(例如,post_url)时,我遇到了一个新错误。如何访问生成 URL 的帮助程序?
  • +Horace Loeb : 你解决了对生成 URL 的 Helpers 的访问吗?
【解决方案3】:

最近我想做一个像 Horace Loeb 提到的那样定义的 rake 任务,并将其翻译成一个独立的后台作业,但翻译起来并不容易。

这是我对 Rails 2.3.x 的实现,因为我发现的 Rails 3 implementation 不起作用。

# Public: Template to render views outside the context of a controller.
#
# Useful for rendering views in rake tasks or background jobs when a
# controller is unavailable.
#
# Examples
#
#   template = OfflineTemplate.new(:users)
#   template.render("users/index", :layout => false, :locals => { :users => users })
#
#   template = OfflineTemplate.new(ProjectsHelper, PermissionsHelper)
#   template.render("projects/recent", :projects => recent_projects)
#
class OfflineTemplate
  include ActionController::UrlWriter
  include ActionController::Helpers::ClassMethods

  # Public: Returns the ActionView::Base internal view.
  attr_reader :view

  # Public: Convenience method  to
  delegate :render, :to => :view

  # Public: Initialize an offline template for the current Rails environment.
  #
  # helpers - The Rails helpers to include (listed as symbols or modules).
  def initialize(*helpers)
    helper(helpers + [ApplicationHelper])
    @view = ActionView::Base.new(Rails.configuration.view_path, {}, self)
    @view.class.send(:include, master_helper_module)
  end

  private

  # Internal: Required to use ActionConroller::Helpers.
  #
  # Returns a Module to collect helper methods.
  def master_helper_module
    @master_helper_module ||= Module.new
  end
end

这是一个要点:https://gist.github.com/1386052

然后您可以使用上面的类创建一个 OfflineTemplate 来在 rake 任务中呈现您的视图:

task :recent_projects => :environment do 
  template = OfflineTemplate.new(ProjectsHelper, PermissionsHelper)
  puts template.render("projects/recent", :projects => recent_projects)
end

【讨论】:

    猜你喜欢
    • 2011-06-22
    • 2015-04-01
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 2017-10-04
    • 2014-04-19
    相关资源
    最近更新 更多