web-dev-qa-db-fra.com

variables locales optionnelles dans Rails modèles partiels: comment sortir du désordre (défini? foo)?

J'ai été un mauvais garçon et j'ai utilisé la syntaxe suivante dans mes modèles partiels pour définir les valeurs par défaut des variables locales si une valeur n'était pas explicitement définie dans le hachage: locals lors du rendu du partiel -

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

Cela semblait bien fonctionner jusqu'à récemment, lorsque (sans aucune raison, je ne discerne) les variables non passées ont commencé à se comporter comme si elles avaient été définies sur nil (plutôt qu'indéfinies).

Comme l'ont souligné diverses personnes utiles sur SO, http://api.rubyonrails.org/classes/ActionView/Base.html dit pas à utiliser

defined? foo

et au lieu d'utiliser

local_assigns.has_key? :foo

J'essaie de me modifier, mais cela implique de changer beaucoup de modèles.

Puis-je/devrais-je simplement charger à l'avance et effectuer ce changement dans tous les modèles? Y a-t-il des problèmes que je dois surveiller? À quel point dois-je faire preuve de diligence pour les tester?

215
brahn

Je fais ça:

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

Puisque local_assigns Est un hachage, vous pouvez également utiliser fetch avec l'option default_value.

local_assigns.fetch :foo, default_value

Ceci retournera default_value Si foo n'était pas défini.

ATTENTION:

Soyez prudent avec local_assigns.fetch :foo, default_value Lorsque default_value Est une méthode, car elle sera appelée de toute façon afin de transmettre son résultat à fetch.

Si votre default_value Est une méthode, vous pouvez l'envelopper dans un bloc: local_assigns.fetch(:foo) { default_value } pour empêcher son appel lorsqu'il n'est pas nécessaire.

149
Pablo Cantero

Que diriez-vous

<% foo ||= default_value %>

Cela dit "utilisez foo si ce n'est ni nul ni vrai. Sinon, affectez default_value à foo "

83
hgmnz

Je pense que cela devrait être répété ici (de http://api.rubyonrails.org/classes/ActionView/Base.html ):

Si vous devez savoir si une valeur a été attribuée à une variable locale donnée dans un appel de rendu particulier, vous devez utiliser le modèle suivant:

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

Test utilisant défini? le titre ne fonctionnera pas. Ceci est une restriction d'implémentation.

10
gamov

Dans mon cas, j'utilise:

<% variable ||= "" %>

dans mon partiel.
Je ne sais pas si c'est bon, mais ça va.

5
Moises Portillo

Je sais que c'est un vieux fil, mais voici ma petite contribution: je voudrais utiliser local_assigns[:foo].presence dans un conditionnel à l'intérieur du partiel. Ensuite, je ne mets foo que lorsque cela est nécessaire dans l'appel de rendu:

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

Consultez te official Rails guide ici . Valable à partir du règlement 3.1.0.

4
microspino

Ceci est un dérivé de la réponse de Pablo. Cela me permet de définir une valeur par défaut ('full'), et à la fin, le 'mode' est défini à la fois dans local_assigns et dans une variable locale réelle.

haml/slim:

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

erb:

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

Je pense qu'une meilleure option permettant plusieurs variables par défaut:

<% 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
Daniel OCallaghan

Plus intuitif et compact:

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

0
muirbot

Ruby 2.5

Erb

C'est possible, mais vous devez déclarer vos valeurs par défaut dans la portée.

VARIABLE le mot à remplacer.

# 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

Si vous ne voulez pas passer de variable locale à partielle à chaque appel, procédez comme suit:

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

De cette façon, vous évitez undefined variable Erreur. Cela vous permettra d’appeler votre partiel avec/sans variables locales.

0
Haris Krajina