Rails:从外部控制器渲染视图

pra*_*ajo 21 ruby ruby-on-rails ruby-on-rails-4

我正在尝试使用视图创建HTML字符串.我想从一个不是控制器的类中渲染它.如何在控制器外部使用rails渲染引擎?与ActionMailer的做法类似?

谢谢!

cor*_*ard 41

Rails 5现在以更方便的方式支持这个,处理创建请求以及幕后的东西:

rendered_string = ApplicationController.render(
  template: 'users/show',
  assigns: { user: @user }
)
Run Code Online (Sandbox Code Playgroud)

这将呈现app/views/users/show.html.erb并设置@user实例变量,因此您无需对模板进行任何更改.它会自动使用ApplicationController(application.html.erb默认情况下)指定的布局.

测试显示了一些额外的选项和方法.

  • 使用控制器类会触发管理员和身份验证问题。这对我有用:`ActionView::Base.new('app/views').render(file: 'invoices/show', locals: {invoiceObjIn: inv}, layout: 'layouts/invoice')` (3认同)
  • 我遇到此错误:“Devise 在您的请求环境中找不到 'Warden::Proxy' 实例。”。你如何解决这个问题? (2认同)

cwe*_*ton 38

您可以使用ActionView :: Base来实现此目的.

view = ActionView::Base.new(ActionController::Base.view_paths, {})
view.render(file: 'template.html.erb')
Run Code Online (Sandbox Code Playgroud)

的ActionView :: Base的初始化需要:

  1. 上下文,表示模板搜索路径
  2. 一个assigns散列,提供变量模板

如果您想包含帮助程序,可以使用class_eval来包含它们:

view.class_eval do
  include ApplicationHelper
  # any other custom helpers can be included here
end
Run Code Online (Sandbox Code Playgroud)

  • 在我看来,使用 ActionView::Base 是最好的答案。为了方便起见,我可能会更进一步并对其进行子类化,但这只是我。我从来没有让 AbstractController 按照其他人描述的方式工作,但也许我的 Rails 版本太新了。不管怎样,这种方式感觉不那么脏。 (2认同)

小智 10

在 Rails 5 中:

view = ActionView::Base.new(ActionController::Base.view_paths)
view.render(file: 'template.html.erb')
Run Code Online (Sandbox Code Playgroud)

在 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' })
Run Code Online (Sandbox Code Playgroud)
  • ActionView::Renderer.new()需要一个lookup_contextarg,render()方法需要一个context,所以我们首先设置它们
  • ActionView::Base 是默认的ActiveView上下文,必须用with_empty_template_cache方法初始化,否则render()会报错
  • {}, nil必需 assignscontrollerargs 过去{}, nil在 Rails 5 中默认为
  • Rails 6.1 需要完整的文件路径file: 'app/views/template.html',而 Rails 5 仅需要文件名


Jes*_*sse 6

没有必要用太多 gem 来过度膨胀你的应用程序。我们知道 ERB 已经包含在您的 Rails 应用程序中。

@jdf = JDF.new
@job = ERB.new(File.read(Rails.root + "app/views/entries/job.xml.erb"))
result =  @job.result(binding)
Run Code Online (Sandbox Code Playgroud)

上面有我正在开发的应用程序的代码片段。

  • @jdf是要在erb视图中评估的对象。
  • 就我而言,我需要渲染xml.
  • result 是一个字符串,可以保存或发送到您喜欢的任何地方。

  • 这很好,除非你依赖像 `link_to` 等帮助器。 (2认同)