为什么我需要在Rails控制器动作中使用`render layout: false`?

7

我使用了在Rails中使用Javascript指南中的remote: true技巧:

# new.html.slim
= form_for @thing, remote: true do |f|
  f.text_field :whatever
  f.submit 'Submit'

# thing_controller.rb
layout 'foo'

def create
end

# create.js.erb
alert('foobar')

这个失败了,因为create.js.erb被渲染在“foo”布局内并返回为html格式,而不是javascript格式,尽管该请求已经正确地处理为Javascript。
Processing by ThingsController#create as JS
  Parameters: {"utf8"=>"✓", "commit"=>"Submit"}
  Rendered things/create.js.erb (0.6ms)

(即使在控制器操作中没有显式的 respond_to 格式块,问题仍然存在。)
此处此处所示,将render layout: false包含在控制器操作中可以修复该问题。
# thing_controller.rb
layout 'foo'

def create
  render layout: false
end

但是我为什么需要在这里使用render layout: false?为什么Rails会在html布局中呈现javascript?我感到困惑的是,我在其他几个地方使用过相同的习语,以前从未遇到过这个问题。

2个回答

4
Rails中的动作控制器默认返回HTML响应(除非另有指示)。 layout 'foo' 强制使用 app/views/layouts/foo.html.slim 作为视图文件的模板。 因此,与 thing_controller.rb 上的操作相关联的所有视图都在布局 'foo' 内呈现,并且使用布局 'foo' 和视图文件 create.html.slim 生成最终的HTML,默认情况下将其发送回客户端。
如果您想强制返回js模板而不是HTML文件,则需要像这样在您的操作中明确定义它:
# thing_controller.rb
layout 'foo'

def create
  respond_to do |format|
    # use :template if your view file is somewhere else than rails convention
    format.js {
      :template => "somewhere/create.js.erb", 
      :layout => false
    }
  end
end

render layout: false指示Rails不要寻找任何布局文件来包装您的视图文件(即,Rails引擎只处理create.js.erb文件,而不考虑在'foo'布局上定义的HTML头),以便将其发送回客户端。


3

大多数渲染选项都会将渲染内容显示为当前布局的一部分。

您可以使用 :layout 选项告诉 Rails 使用特定文件作为当前操作的布局:

 render layout: false

你可能已经听说过Rails倡导“约定优于配置”的理念。默认渲染就是其中一个很好的例子。在Rails中,控制器会自动渲染与其操作名称相对应的视图。

你可以使用它来避免针对特定操作的渲染false,这可能会影响代码的延迟。

 layout false
 layout 'foo', :except => :create

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接