Rails:在视图中呈现一个视图(而不是部分)。

时间:2022-10-08 17:05:51

I have a controller that responds to both html and js. The html view renders the whole page (including the header and footer), while the js only replaces #main. Aside from the header and footer, both formats render the same content. I can get this effect with three files:

我有一个同时响应html和js的控制器。html视图呈现整个页面(包括页眉和页脚),而js只替换#main。除了页眉和页脚之外,两种格式都呈现相同的内容。我可以通过三个文件得到这个效果:

_show.html.erb
<div>Content!</div>

show.html.erb
<%= render "show" %>

show.js.erb
$("#main").fadeIn("<%= escape_javascript(render 'show') %>");

This works, but I'd prefer if I didn't need a separate _show partial. Unfortunately, this doesn't work:

这是可行的,但是如果我不需要单独的_show部分,我宁愿这样做。不幸的是,这并不工作:

show.html.erb
<div>Content!</div>

show.js.erb
$("#main").fadeIn("<%= escape_javascript(render 'show') %>");

As Rails will look for the show partial, not the actual view.

Rails将查找show partial,而不是实际的视图。

Is there a way to get Rails to look for the view file, rather than a partial?

是否有一种方法可以让Rails查找视图文件,而不是部分文件?

4 个解决方案

#1


24  

Rendering a non-partial view inside another view isn't exactly the Rails Way™. Your current solution is probably better, and not an uncommon approach. Rename it _body, or something else appropriate, if you feel weird about the the partial name being the same as the action.

呈现一个公正不阿的视图在另一个视图并不是Rails™。您当前的解决方案可能更好,而且是一种常见的方法。将其重命名为_body,或者其他合适的名称,如果您觉得部分名称与操作相同,就会感到奇怪。

However if your view can be shared, as it seems like it could in this case, you could just make it a layout.

但是,如果您的视图可以被共享,就像在本例中一样,您可以将其设置为一个布局。

This is facilitated by the fact that, somewhat against the principle of least surprise, Rails will render an html template for a js action if no js template exists. This means that you could remove both the js template, and the partial, and just create a layout entitled, for example, fadein.js.erb:

这是因为,如果不存在js模板,Rails将呈现一个用于js操作的html模板,这在一定程度上违背了最小惊奇原则。这意味着您可以同时删除js模板和部分模板,并创建一个名为fadein.js.erb的布局:

# yourviews/show.html.erb
<div>Content!</div>

# layouts/fadein.js.erb
$("#main").fadeIn("<%= escape_javascript(yield) %>");

# YourController.rb
def show
  # ...
  respond_to do |wants|
    wants.html
    wants.js { render :layout => "fadein" }
  end
end

#2


18  

Like others have mentioned, rendering another non-partial view in another view is "Not the rails way", if however you still insist on doing it, one method is:

正如其他人提到的,在另一个视图中呈现另一个非局部视图是“非rails方式”,如果您仍然坚持这样做,一个方法是:

<%= render :file => '<replace with relative/absolute path>' %>

#3


10  

This is not a good practice as you can see by the comments. Rails have the concepts of view, partial and layout. That said, the view is the only one you should keep using only once. So my suggestions are:

从评论中可以看出,这不是一个好的做法。Rails具有视图、部分和布局的概念。也就是说,视图是惟一应该只使用一次的视图。所以我的建议是:

  1. If you feel that more than one extra view could be rendered inside your current view, you are most likely looking for a layout
  2. 如果您觉得在当前视图中可以呈现多个额外的视图,那么您很可能正在寻找布局
  3. If you feel that one of your views should be rendered in many pages, you are looking for a partial
  4. 如果您认为您的一个视图应该在许多页中呈现,那么您正在寻找部分视图
  5. If this view should render only one extra view inside it, and that view should only be rendered inside the current view, you can pick any of the above or none of it - that's it, go with a single file
  6. 如果这个视图应该只呈现其中一个额外的视图,并且那个视图应该只呈现在当前视图中,那么您可以选择上面的任何一个,或者不呈现其中的任何一个——就是这样,使用一个文件

#4


1  

you just need to pass a context to your render method:

您只需要将上下文传递给呈现方法:

<%= render :template => "show" -%>

#1


24  

Rendering a non-partial view inside another view isn't exactly the Rails Way™. Your current solution is probably better, and not an uncommon approach. Rename it _body, or something else appropriate, if you feel weird about the the partial name being the same as the action.

呈现一个公正不阿的视图在另一个视图并不是Rails™。您当前的解决方案可能更好,而且是一种常见的方法。将其重命名为_body,或者其他合适的名称,如果您觉得部分名称与操作相同,就会感到奇怪。

However if your view can be shared, as it seems like it could in this case, you could just make it a layout.

但是,如果您的视图可以被共享,就像在本例中一样,您可以将其设置为一个布局。

This is facilitated by the fact that, somewhat against the principle of least surprise, Rails will render an html template for a js action if no js template exists. This means that you could remove both the js template, and the partial, and just create a layout entitled, for example, fadein.js.erb:

这是因为,如果不存在js模板,Rails将呈现一个用于js操作的html模板,这在一定程度上违背了最小惊奇原则。这意味着您可以同时删除js模板和部分模板,并创建一个名为fadein.js.erb的布局:

# yourviews/show.html.erb
<div>Content!</div>

# layouts/fadein.js.erb
$("#main").fadeIn("<%= escape_javascript(yield) %>");

# YourController.rb
def show
  # ...
  respond_to do |wants|
    wants.html
    wants.js { render :layout => "fadein" }
  end
end

#2


18  

Like others have mentioned, rendering another non-partial view in another view is "Not the rails way", if however you still insist on doing it, one method is:

正如其他人提到的,在另一个视图中呈现另一个非局部视图是“非rails方式”,如果您仍然坚持这样做,一个方法是:

<%= render :file => '<replace with relative/absolute path>' %>

#3


10  

This is not a good practice as you can see by the comments. Rails have the concepts of view, partial and layout. That said, the view is the only one you should keep using only once. So my suggestions are:

从评论中可以看出,这不是一个好的做法。Rails具有视图、部分和布局的概念。也就是说,视图是惟一应该只使用一次的视图。所以我的建议是:

  1. If you feel that more than one extra view could be rendered inside your current view, you are most likely looking for a layout
  2. 如果您觉得在当前视图中可以呈现多个额外的视图,那么您很可能正在寻找布局
  3. If you feel that one of your views should be rendered in many pages, you are looking for a partial
  4. 如果您认为您的一个视图应该在许多页中呈现,那么您正在寻找部分视图
  5. If this view should render only one extra view inside it, and that view should only be rendered inside the current view, you can pick any of the above or none of it - that's it, go with a single file
  6. 如果这个视图应该只呈现其中一个额外的视图,并且那个视图应该只呈现在当前视图中,那么您可以选择上面的任何一个,或者不呈现其中的任何一个——就是这样,使用一个文件

#4


1  

you just need to pass a context to your render method:

您只需要将上下文传递给呈现方法:

<%= render :template => "show" -%>