web-dev-qa-db-ja.com

Rails部分テンプレートのオプションのローカル変数:(定義済み?foo)混乱から抜け出すにはどうすればよいですか?

私は悪い子で、パーシャルをレンダリングするときに値がローカルハッシュで明示的に定義されていない場合、ローカルテンプレートの次の構文を使用してローカル変数のデフォルト値を設定しました-

<% foo = default_value unless (defined? foo) %>

これは最近まで(理由はありませんが)渡されなかった変数が(未定義ではなく)nilに定義されているかのように振る舞うようになりました。

SOに関するさまざまな有用な人々から指摘されているように、 http://api.rubyonrails.org/classes/ActionView/Base.htmlnot使用する

defined? foo

代わりに使用する

local_assigns.has_key? :foo

私は自分のやり方を修正しようとしていますが、それは多くのテンプレートを変更することを意味します。

事前に請求して、すべてのテンプレートでこの変更を行うことができますか?監視する必要があるトリッキーはありますか?それぞれをどれだけ熱心にテストする必要がありますか?

215
brahn

私はこれをします:

<% some_local = default_value if local_assigns[:some_local].nil? %>
310
jonnii

local_assignsはハッシュなので、オプションのdefault_valueとともに fetch を使用することもできます。

local_assigns.fetch :foo, default_value

fooが設定されていない場合、これはdefault_valueを返します。

警告:

local_assigns.fetch :foo, default_valueがメソッドである場合、結果をfetchに渡すためにとにかく呼び出されるので、default_valueに注意してください。

default_valueがメソッドである場合、それをブロックにラップすることができます:local_assigns.fetch(:foo) { default_value }は、不要なときに呼び出しを防ぐことができます。

149
Pablo Cantero

どう?

<% foo ||= default_value %>

これは「nilまたはtrueでない場合はfooを使用します。そうでない場合はdefault_valueをfooに割り当てます」

83
hgmnz

私はこれをここで繰り返すべきだと思います( http://api.rubyonrails.org/classes/ActionView/Base.html から):

特定のレンダリング呼び出しで特定のローカル変数に値が割り当てられているかどうかを調べる必要がある場合は、次のパターンを使用する必要があります。

<% if local_assigns.has_key? :headline %>
  Headline: <%= headline %>
<% end %>

定義を使用してテストしますか?見出しは機能しません。これは実装の制限です。

10
gamov

私の場合、次のものを使用します。

<% variable ||= "" %>

私の部分的に。
それが良いかどうかはわかりませんが、私の場合は大丈夫です

5
Moises Portillo

私はそれが古いスレッドであることを知っていますが、ここに私の小さな貢献があります:パーシャル内のconditionallocal_assigns[:foo].presenceを使用します。次に、レンダーコールで必要な場合にのみfooを設定します。

<%= render 'path/to/my_partial', always_present_local_var: "bar", foo: "baz" %>

Te official Rails guide here をご覧ください。 RoR 3.1.0から有効。

4
microspino

これはPabloの答えの派生物です。これにより、デフォルト( 'full')を設定でき、最終的に、 'mode'はlocal_assignsと実際のローカル変数の両方に設定されます。

haml/slim:

- mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full')

erb:

<% mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full') %>
1
sethcall

複数のデフォルト変数を許可するより良いオプションだと思います:

<% options = local_assigns.reverse_merge(:include_css => true, :include_js => true) %>
<%= include_stylesheets :national_header_css if options[:include_css] %>
<%= include_javascripts :national_header_js if options[:include_js] %>
1

より直感的でコンパクト:

<% some_local = default_value unless local_assigns[:some_local] %>

0
muirbot

Ruby 2.5

エルブ

可能ですが、スコープでデフォルト値を宣言する必要があります。

変数置換するWord。

# index.html.erb
...
<%= render 'some_content', VARIABLE: false %>
...

# _some_content.html.erb
...
<% VARIABLE = true if local_assigns[:VARIABLE].nil? %>
<% if VARIABLE %>
    <h1>Do you see me?</h1>
<% end %>
...
0
dimpiax

ローカル変数を呼び出すたびに部分変数に渡したくない場合は、次のようにします。

<% local_param = defined?(local_param) ? local_param : nil %>

これにより、undefined variableエラーを回避できます。これにより、ローカル変数あり/なしでパーシャルを呼び出すことができます。

0
Haris Krajina