web-dev-qa-db-ja.com

Rails:パーシャルにローカルを渡す構文の混乱

Rails "magic"パーシャルのレンダリング(およびそれらへのローカルの受け渡し)に関する理解。

これが機能する理由:

<%= render "rabbits/form" %>

そしてこの作品:

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

しかし、これはnot動作します:

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

しかし、これは:

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

また、どうすればこれらのニュアンスを調べることができますので、S.O。の人々を煩わせる必要はありませんか?

98
Meltemi

簡単な答えは、渡すメソッドが最初に渡すレンダーメソッドです。ハッシュ(_: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() method in Rails 2 ; Rails 3は異なります)。これは良い練習です。

さらに、SOで人々を "bothering"することを心配しないでください。それがこのサイトが存在する理由です。これから何かを学びました。

151
Doug R

:localsを指定する必要がある場合は、:partialまたは:templateを指定する必要があります

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

動作するはずです

5
sethvargo

正直なところ、これらのユースケースについて知っているのは、過去数年間Railsに追いついており、新しい方法が追加されたという発表を読んだからです。私はよく自分で間違いを犯しますが、通常は簡単に修正できます。

これはRails APIの一部の1つです。私に尋ねると、徹底的に検討されていません。古いものを非推奨にすることなく、長年にわたってより多くの構文糖を蓄積した動作:renderメソッドには糖尿病があります。

さらに悪いことに、レンダリングはコントローラーとビューで異なる動作をします。また、最初の引数の内容を調べて、ファイル、テンプレート、アクション、またはパーシャルのいずれであるかを確認します。スラッシュで始まる場合は、ファイル、またはそのようなものです。

可能な限り短い表記を使用することに賛成です。短い表記は意図を非常によく伝えるからです。それを読むとき、それは通常あなたがそれがすると思うことをします。それを書くことは簡単ではありません。

2
iain

http://api.rubyonrails.org/classes/ActionView/Rendering.html#method-i-render の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

このヘルプを願っています!

1