Rails:对将局部变量传递给局部变量的语法感到困惑

问题描述 投票:0回答:5

了解 Rails 在渲染部分(并将局部变量传递给它们)方面的“魔力”。

为什么这样做:

<%= render "rabbits/form" %>

这项工作:

<%= render "rabbits/form", :parent => @warren, :flash => flash %>

但这确实工作:

<%= render "rabbits/form", :locals => { :parent => @warren, :flash => flash } %>

但是这样做:

<%= render :partial =>"rabbits/form", :locals => { :parent => @warren, :flash => flash } %>

另外,我怎样才能查看这些细微差别,这样我就不需要打扰 S.O. 上的人了?

ruby-on-rails partial-views
5个回答
153
投票

简短的回答是 render 方法会查看您传入的第一个参数。如果您传入一个散列(包括

:partial => 'foo', :locals => {blah blah blah}
),那么它会将您的所有参数作为散列传入并相应地解析它们。

如果你传入一个字符串作为你的第一个参数,它假定第一个参数是你的部分名称,并将其余部分作为你的本地人传递。然而,在随后的调用中,它实际上分配了

:locals => your_locals_argument
,在这种情况下是整个
:locals => {locals hash}
,而不仅仅是
{locals hash}
;即你最终得到
:locals => {:locals => {locals hash}}
,而不是
:locals => {locals hash}
.

所以我的建议是始终以相同的方式显式传递值,这样就不会有问题。为了了解这一点,我直接转到代码本身(actionpack/lib/base.rb

render()
Rails 2 中的方法;Rails 3 不同)。这是一个很好的锻炼。

此外,不要担心“打扰” SO 上的人。这就是这个网站存在的原因。我什至从中学到了一些东西。


5
投票

如果需要指定:locals,需要指定:partial或:template

<%= render :partial => "rabbits/form", :locals => {...} %>

应该工作


2
投票

老实说,我只知道这些用例,因为过去几年我一直在跟上 Rails 的步伐,并阅读了有关添加新方法的公告。我自己也经常犯错,但通常很容易改正。

如果你问我,这是 Rails API 中尚未彻底考虑的部分之一。多年来它只是积累了越来越多的语法糖,而没有贬低任何旧行为。渲染方法有糖尿病。

更糟糕的是,渲染在控制器和视图中的行为不同。我还会查看第一个参数的内容,看它是文件、模板、操作还是部分。如果它以斜杠开头,那么它就是一个文件,或者类似的东西。

我赞成尽可能使用更短的符号。因为简短的符号确实很好地传达了意图。阅读它时,它通常会按照您的想法行事。编写部分内容并不简单。


1
投票

这里是渲染方法的来源http://api.rubyonrails.org/classes/ActionView/Rendering.html#method-i-render:

def render(options = {}, locals = {}, &block)
  case options
  # Here is your last case
  when Hash
    if block_given?
      _render_partial(options.merge(:partial => options.delete(:layout)), &block)
    elsif options.key?(:partial)
      _render_partial(options)
    else
      template = _determine_template(options)
      lookup_context.freeze_formats(template.formats, true)
      _render_template(template, options[:layout], options)
    end
  when :update
    update_page(&block)
  else
    # here the first three cases
    _render_partial(:partial => options, :locals => locals)
  end
end

希望这有帮助!


0
投票

我在 rails 7 / ruby 3.2.1 中遇到了一点麻烦,所以为了彻底起见:

# Works:
<%= render partial: 'publish_unpublish_button', locals: { something: 2, more: 5 } %> 

# Works:
<%= render 'publish_unpublish_button', something: 2, more: 5 %> 

# Won't work
<%= render 'publish_unpublish_button', locals: { something: 2, more: 5 } %> 
© www.soinside.com 2019 - 2024. All rights reserved.