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


99

了解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 } %>

另外,我该如何查找这些细微差别,这样我就不必打扰别人了?


3
在下面的评论中,您说的是rails api文档不是可搜索的。您应该改用以下网站:apidock.com/rails。它还在那里有ruby和rspec。
ryeguy 2010年

Answers:


152

简短的答案是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.rbrender()方法在轨道2; 3的Rails不同)。这是一个很好的练习。

此外,不必担心在SO上“让人”生硬。这就是为什么这个网站存在。我什至从中学到了一些东西。


5

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

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

应该管用


如果您对此感到好奇,它与ruby评估哈希的方式有关。
sethvargo 2010年

确实,它确实起作用。如我在问题中所指出的那样……但是我想知道为什么?在哪里记录?只看源头?而且,如果这是在Rails中查找和了解这些细微差别的唯一方法,那么我想知道如何以及从何处查找和解释这一点。我不能只单击“渲染”然后向下钻取到源代码(无论如何不使用TextMate),还是可以吗?
Meltemi 2010年

1
啊!所以您实际上很感兴趣:)。是的,解决这些问题的唯一方法是a。)像您一样直觉,b。)查看源代码。我不知道如何深入了解源代码……对不起
sethvargo 2010年

好吧,我会咬......怎么,你看看这个样的东西?你只是在钻研你的clone https://github.com/rails/rails.git吗?或者,还有更好的方法?很抱歉,但我是比较新的回报率和还没有找到一个好的/易/一致的方式来查找Rails文档...,使得IS任何。http://api.rubyonrails.org/是不是很容易搜索到。而git的来源也不是…… 感叹
Meltemi 2010年

我绝不是专家,但我使用的是Aptana工作室。它与eclipse建立在相同的平台上(如果您熟悉的话)。它使您可以像单击所说的那样“单击”并跟踪。您也可以进行代码内搜索,并且它具有内置的终端等。注意–它是一个很大的文件
sethvargo 2010年

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

希望有帮助!


这确实有帮助,谢谢!但这并不能帮助我自己...如果您知道我的意思...
Meltemi 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.