Rails: Render view from outside controller

2019-01-23 13:34发布

I'm trying to create an HTML string using a view. I would like to render this from a class that is not a controller. How can I use the rails rendering engine outside a controller? Similar to how ActionMailer does?

Thanks!

7条回答
劫难
2楼-- · 2019-01-23 13:40

Technically, ActionMailer is a subclass implementation of AbstractController::Base. If you want to implement this functionality on your own, you'll likely want to inherit from AbstractController::Base as well.

There is a good blog post here: https://www.amberbit.com/blog/2011/12/27/render-views-and-partials-outside-controllers-in-rails-3/ that explains the steps required.

查看更多
Fickle 薄情
3楼-- · 2019-01-23 13:50

For future reference, I ended up finding this handy gem that makes this a breeze:

https://github.com/yappbox/render_anywhere

查看更多
贪生不怕死
4楼-- · 2019-01-23 13:50

"I'm trying to create an HTML string using a view." -- If you mean you're in the context of a view template, then just use a helper method or render a partial.

If you're in some other "Plain Old Ruby Object", then keep in mind you're free to use the ERB module directly:

erb = ERB.new("path/to/template")
result = erb.result(binding)

The trick is getting that 'binding' object that gives the context for the code in the template. ActionController and other Rails classes expose it for free, but I couldn't find a reference that explains where it comes from.

http://www.ruby-doc.org/stdlib-2.2.0/libdoc/erb/rdoc/ERB.html#method-i-result

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-01-23 13:55

You can use ActionView::Base to achieve this.

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

The ActionView::Base initialize takes:

  1. A context, representing the template search paths
  2. An assigns hash, providing the variables for the template

If you would like to include helpers, you can use class_eval to include them:

view.class_eval do
  include ApplicationHelper
  # any other custom helpers can be included here
end
查看更多
放我归山
6楼-- · 2019-01-23 13:59

Rails 5 now supports this in a much more convenient manner that handles creating a request and whatnot behind the scenes:

rendered_string = ApplicationController.render(
  template: 'users/show',
  assigns: { user: @user }
)

This renders app/views/users/show.html.erb and sets the @user instance variable so you don't need to make any changes to your template. It automatically uses the layout specified in ApplicationController (application.html.erb by default).

The test shows a handful of additional options and approaches.

查看更多
混吃等死
7楼-- · 2019-01-23 13:59

Best to render the view using a controller, as that's what they're for, and then convert it to a string, as that is your ultimate goal.

require 'open-uri'
html = open(url, &:read)
查看更多
登录 后发表回答