2010-12-09 150 views
96

理解Rails与渲染局部变量(以及传递局部变量)有关的“魔术”。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.上的人?

+3

在下面的评论中,您说的是rails api文档不可搜索。你应该试试这个网站:http://apidock.com/rails。它也有ruby和rspec。 – ryeguy 2010-12-09 21:46:21

回答

150

简短的回答是渲染方法看你传递的第一个参数。如果你传入一个散列(其中包括: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()方法在Rails 2中; Rails 3是不同的)。这是一个很好的练习。

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

5

,如果你需要指定:当地人,你需要指定:局部或:模板

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

应该工作

+0

它与ruby评估散列的方式有关,如果你对这种方式感兴趣。 – sethvargo 2010-12-09 20:05:00

+0

事实上,它确实有效......正如我在我的问题中指出的那样......但是我想知道的是*为什么?*以及在哪里记录?只有通过观察来源?而且,如果这是在Rails中查找和理解这些无数细微差别的唯一方法,那么我想知道如何从源代码中找到并解释这个问题。我不能只是点击“渲染”,然后深入到源代码(无论如何不是),或者我可以吗? – Meltemi 2010-12-09 20:08:46

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 

希望这个帮助!

2

为了更好的体会,我只知道这些用例,因为在过去的几年里我一直在跟踪Rails,并阅读了一些新增加的方法。我经常自己犯了一个错误,但通常很容易纠正。

这是Rails API的其中一部分,如果你问我的话,它还没有经过深思熟虑。这些年来它只是积累了越来越多的语法糖,而没有贬低任何旧的行为。渲染方法有糖尿病。

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

我赞成尽可能使用较短的表示法。因为短符号确实很好地传达了意图。阅读时,它通常会做你认为它的作用。写它并不是那么简单。