Rails:对将locals传递给partials的语法感到困惑

时间:2010-12-09 20:00:37

标签: ruby-on-rails partial-views

了解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的人?

4 个答案:

答案 0 :(得分:151)

简短的回答是render方法查看传入的第一个参数。如果传入一个哈希(包括:partial => 'foo', :locals => {blah blah blah}),那么它会将所有参数作为哈希传递并相应地解析它们。

如果传入一个字符串作为第一个参数,它会假定第一个参数是您的部分名称,并将余数作为您的本地传递。但是,在后续调用中,它实际上会分配:locals => your_locals_argument,在这种情况下是整个:locals => {locals hash},而不仅仅是{locals hash};即最终得到:locals => {:locals => {locals hash}},而不是:locals => {locals hash}

所以我的建议只是始终以相同的方式显式传递值,而且你不会遇到问题。为了了解这一点,我直接使用了代码本身(Rails 2中的 actionpack / lib / base.rb render()方法; Rails 3不同)。这是一个很好的练习。

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

答案 1 :(得分:5)

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

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

应该有效

答案 2 :(得分:2)

为了获得荣誉,我只知道这些用例,因为我在过去几年一直关注Rails,并阅读了一条新的方法,即添加了一种新方法。我自己经常犯错误,但通常很容易纠正。

如果你问我,这是Rails API的其中一个部分尚未经过深思熟虑。它多年来积累了越来越多的语法糖,没有弃用任何旧的行为。渲染方法有糖尿病。

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

我赞成尽可能使用较短的符号。因为简短的符号确实可以很好地传达意图。阅读时,它通常会按照您的想法执行。写它不是那么直接。

答案 3 :(得分: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

希望这有帮助!