【发布时间】:2015-04-04 15:20:21
【问题描述】:
我正在尝试使用视图创建 HTML 字符串。我想从一个不是控制器的类中渲染它。如何在控制器外部使用 rails 渲染引擎?类似于 ActionMailer 的做法?
谢谢!
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-4
我正在尝试使用视图创建 HTML 字符串。我想从一个不是控制器的类中渲染它。如何在控制器外部使用 rails 渲染引擎?类似于 ActionMailer 的做法?
谢谢!
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-4
Rails 5 和 6 以更方便的方式支持这一点,可以在后台处理创建请求等:
rendered_string = ApplicationController.render(
template: 'users/show',
assigns: { user: @user }
)
这将呈现app/views/users/show.html.erb 并设置@user 实例变量,因此您无需对模板进行任何更改。它会自动使用ApplicationController 中指定的布局(默认为application.html.erb)。 Full documentation can be found here.
The test shows a handful of additional options and approaches.
【讨论】:
views 目录中创建逻辑。
ActionView::Base.new('app/views').render(file: 'invoices/show', locals: {invoiceObjIn: inv}, layout: 'layouts/invoice')
Devise could not find the 'Warden::Proxy' instance on your request environment.。你如何解决这个问题?
在 Rails 5 中:
view = ActionView::Base.new(ActionController::Base.view_paths)
view.render(file: 'template.html.erb')
在 Rails 6.1 中:
lookup_context = ActionView::LookupContext.new(ActionController::Base.view_paths)
context = ActionView::Base.with_empty_template_cache.new(lookup_context, {}, nil)
renderer = ActionView::Renderer.new(lookup_context)
renderer.render(context, { file: 'app/views/template.html.erb' })
ActionView::Renderer.new() 采用 lookup_context arg,render() 方法采用 context,所以我们先设置它们ActionView::Baseis the default ActiveView context,必须用with_empty_template_cache方法初始化,否则render()会报错{}, nil 是 required assigns 和 controller args,过去在 Rails 5 中默认为 {}, nil
file: 'app/views/template.html',而 Rails 5 只需要文件名【讨论】:
在ApplicationController上直接调用render方法可能会报错
Helper Devise: could not find the `Warden::Proxy` instance on request environment
相反,我们可以像使用 ApplicationController.renderer.render 一样
rendered_string = ApplicationController.renderer.render(
partial: 'users/show',
locals: { user: user }
)
【讨论】:
最好使用控制器来呈现视图,因为这就是它们的用途,然后然后将其转换为字符串,因为这是您的最终目标。
require 'open-uri'
html = open(url, &:read)
【讨论】:
没有必要用太多的 gem 来过度膨胀你的应用程序。我们知道 ERB 已经包含在您的 Rails 应用程序中。
@jdf = JDF.new
@job = ERB.new(File.read(Rails.root + "app/views/entries/job.xml.erb"))
result = @job.result(binding)
上面是我正在开发的应用程序的代码 sn-p。
@jdf 是要在 erb 视图中评估的对象。 xml。result 是一个字符串,可以保存或发送到您喜欢的任何地方。【讨论】:
link_to 这样的助手。
您可以使用ActionView::Base 来实现此目的。
view = ActionView::Base.new(ActionController::Base.view_paths, {})
view.render(file: 'template.html.erb')
ActionView::Base 初始化需要:
assigns 哈希,为模板提供变量如果您想包含助手,可以使用 class_eval 来包含它们:
view.class_eval do
include ApplicationHelper
# any other custom helpers can be included here
end
【讨论】:
view.render(file: 'template.html.erb', layout: 'layouts/layout.html.erb')
为了将来参考,我最终找到了 这个方便的宝石让这变得轻而易举:
【讨论】:
“我正在尝试使用视图创建 HTML 字符串。” -- 如果您的意思是您在视图模板的上下文中,那么只需使用辅助方法或渲染部分。
如果您使用其他“普通旧 Ruby 对象”,请记住您可以直接使用 ERB 模块:
erb = ERB.new("path/to/template")
result = erb.result(binding)
诀窍是获取为模板中的代码提供上下文的“绑定”对象。 ActionController 和其他 Rails 类免费公开它,但我找不到解释它来自哪里的参考。
http://www.ruby-doc.org/stdlib-2.2.0/libdoc/erb/rdoc/ERB.html#method-i-result
【讨论】:
从技术上讲,ActionMailer 是AbstractController::Base 的子类实现。如果您想自己实现此功能,您可能还想从AbstractController::Base 继承。
这里有一篇很好的博文:https://www.amberbit.com/blog/2011/12/27/render-views-and-partials-outside-controllers-in-rails-3/,它解释了所需的步骤。
【讨论】: