ruby-on-rails Rails:混淆了将局部变量传递给部分变量的语法

hgqdbh6s  于 2023-03-04  发布在  Ruby
关注(0)|答案(5)|浏览(213)

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

xbp102n0

xbp102n01#

简短的回答是,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,Rails 2中的render()方法;Rails 3是不同的)。这是一个很好的练习。
另外,不要担心“打扰”SO上的人。这就是这个网站存在的原因。我甚至从中学到了一些东西。

gev0vcfq

gev0vcfq2#

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

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

应该可以

3lxsmp7m

3lxsmp7m3#

老实说,我只知道这些用例,因为我在过去的几年里一直在关注Rails,并阅读了添加新方法的公告。我自己经常犯错误,但通常很容易纠正。
如果你问我的话,这是Rails API中还没有被彻底考虑过的部分之一。多年来,它只是积累了越来越多的语法糖,而没有放弃任何旧的行为。render方法患有糖尿病。
更糟糕的是,render在控制器和视图中的行为是不同的。我还查看了第一个参数的内容,看看它是一个文件、模板、操作还是部分。如果它以斜杠开头,那么它是一个文件,或者类似的东西。
我赞成尽可能使用较短的符号。因为较短的符号确实能很好地传达意图。当阅读它时,它通常会做你认为它做的事情。编写部分代码并不是直截了当的。

91zkwejq

91zkwejq4#

下面是来自www.example.com的render方法的源代码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

希望这能有所帮助!

pbossiut

pbossiut5#

我在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 } %>

相关问题