【问题标题】:Rails 3: How to render ERb template in rake task?Rails 3:如何在 rake 任务中渲染 ERb 模板?
【发布时间】:2011-05-14 19:20:32
【问题描述】:

我正在使用 rake 渲染一个非常大的站点地图 HTML 文件。不幸的是,当我迁移到 rails 3 时,代码中断了。我当前的代码如下所示:

@controller = ActionController::Base.new
@controller.request = ActionController::TestRequest.new
@controller.instance_eval do
  @url = ActionController::UrlRewriter.new(request, {})
end

# collect data, open output file file

template = ERB.new(IO.read("#{RAILS_ROOT}/app/views/sitemap/index.html.erb"))
f.puts(template.result(binding))

此代码在 2.3 中有效,但在 Rails 3 中中断,因为 url_for 不再访问 @controller,而是控制器。 (我认为这就是原因。)

undefined local variable or method `controller' for #<Object:0x3794c>
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/helpers/url_helper.rb:31:in `url_options'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_dispatch/routing/url_for.rb:132:in `url_for'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/helpers/url_helper.rb:99:in `url_for'
(erb):5
/Users/me/Documents/Projects/zvg2/lib/tasks/zvg.rake:452

我也尝试过创建一个 ActionView 来做到这一点:

av = ActionView::Base.new(Rails::Application::Configuration.new(Rails.root).view_path, {
  # my assigns
}, @controller)
av.class_eval do
  include ApplicationHelper
end
f.puts(av.render(:template => "sitemap/index.html"))

但问题似乎是一样的,虽然 ActionView::Base.new 占用了我的控制器。

undefined local variable or method `controller' for nil:NilClass
/opt/local/lib/ruby/gems/1.8/gems/activesupport-3.0.1/lib/active_support/whiny_nil.rb:48:in `method_missing'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/helpers/url_helper.rb:31:in `url_options'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_dispatch/routing/url_for.rb:132:in `url_for'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/helpers/url_helper.rb:99:in `url_for'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_dispatch/routing/url_for.rb:132:in `url_for'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/helpers/url_helper.rb:99:in `url_for'
/Users/me/Documents/Projects/zvg2/app/views/sitemap/index.html.erb:5:in `_app_views_sitemap_index_html_erb__757224102_30745030_0'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/template.rb:135:in `send'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/template.rb:135:in `render'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-3.0.1/lib/active_support/notifications.rb:54:in `instrument'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/template.rb:127:in `render'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/render/rendering.rb:59:in `_render_template'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-3.0.1/lib/active_support/notifications.rb:52:in `instrument'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-3.0.1/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-3.0.1/lib/active_support/notifications.rb:52:in `instrument'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/render/rendering.rb:56:in `_render_template'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-3.0.1/lib/action_view/render/rendering.rb:26:in `render'
/Users/me/Documents/Projects/zvg2/lib/tasks/zvg.rake:450

使用 url_for 和 link_to 渲染模板的最佳实践是什么?我敢打赌,随着 Rails 变得更加模块化,应该有一个简单的方法来解决这个问题?

提前致谢!一月

【问题讨论】:

    标签: ruby-on-rails-3 rake erb


    【解决方案1】:

    当我包含 Rails.application.routes.url_helpers 而不是 ActionView::Helpers::UrlHelper 时,其中一种方法有效。这暂时有效:

    include Rails.application.routes.url_helpers # brings ActionDispatch::Routing::UrlFor
    include ActionView::Helpers::TagHelper
    
    av = ActionView::Base.new(Rails.root.join('app', 'views'))
    av.assign({
      :regions => @regions,
      :courts_by_region => @courts_by_region,
      :cities_by_region => @cities_by_region,
      :districts_by_region => @districts_by_region
    })
    f = File.new(file_name, 'w')
    f.puts(av.render(:template => "sitemap/index.html"))
    f.close
    

    希望这对其他人有所帮助。如果有更好的解决方案,我会很感兴趣。

    另外,我如何从绑定中自动获取分配的哈希?

    【讨论】:

      【解决方案2】:

      我做了这样的事情很成功:

      class Template < ActionView::Base
        include Rails.application.routes.url_helpers
        include ActionView::Helpers::TagHelper
      
        def default_url_options
          {host: 'yourhost.org'}
        end
      end  
      
      template = Template.new(Rails.root.join('app', 'views'))
      template.assign(attendee: @attendee)
      template.render(template: 'sitemap/index.html.erb')
      

      【讨论】:

      • 一件事是你不需要 .html.erb 在 Ruby On Rails 3.2.x 的模板名称中。使用.html.erb 它会产生弃用警告并要求使用:handlers:formats
      【解决方案3】:

      这对我有用(Rails 3):

      class TaskActionView < ActionView::Base
        include Rails.application.routes.url_helpers
        include ApplicationHelper
      
        def default_url_options
           {host: 'example.com'}
        end
      end
      
      def action_view
        controller = ActionController::Base.new
        controller.request = ActionDispatch::TestRequest.new
        TaskActionView.new(Rails.root.join('app', 'views'), {}, controller)
      end
      
      action_view.render(:template =>"path/to/template")
      

      这成功地包括了我的应用程序助手、标签助手和 url 助手。您需要将您的应用程序/环境主机正确放入 default_url_options 哈希中。

      【讨论】:

      • 谢谢,乔希!!! ActionController 和 ActionDispatch 的解决方法适用于生产环境和嵌套部分,而其他答案仅适用于开发环境。
      【解决方案4】:

      这对我有用:

      html = render_to_string(:index, layout: nil)
      

      【讨论】:

      • 这对你来说适用于 rails 3.2 吗?我在控制台中尝试这个未定义的方法。
      猜你喜欢
      • 2011-04-14
      • 2014-01-24
      • 1970-01-01
      • 2012-12-31
      • 2012-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-10
      相关资源
      最近更新 更多