with rails mvc how from ruby-on-rails partials

ruby on rails - rails - Variables locales opcionales en plantillas parciales de rieles: ¿cómo puedo salir del lío(definido? foo)?



render partial mvc (12)

He sido un niño malo y utilicé la siguiente sintaxis en mis plantillas parciales para establecer valores predeterminados para las variables locales si un valor no se definió explícitamente en el hash: locals al representar el parcial:

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

Esto pareció funcionar bien hasta hace poco, cuando (sin ninguna razón pude discernir) las variables no pasadas comenzaron a comportarse como si hubieran sido definidas como nulas (en lugar de indefinidas).

Como han señalado varias personas útiles en SO, http://api.rubyonrails.org/classes/ActionView/Base.html dice no usar

defined? foo

y en lugar de usar

local_assigns.has_key? :foo

Estoy intentando modificar mis formas, pero eso significa cambiar muchas plantillas.

¿Puedo / debo cobrar por adelantado y hacer este cambio en todas las plantillas? ¿Hay algún truco que deba vigilar? ¿Qué tan diligentemente necesito probar cada uno?


Ruby 2.5

Erb

Es posible, pero debe declarar sus valores predeterminados en el ámbito.

VARIABLE la palabra para el reemplazo.

# 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 %> ...


Creo que esto debería repetirse aquí (de http://api.rubyonrails.org/classes/ActionView/Base.html ):

Si necesita averiguar si a una determinada variable local se le ha asignado un valor en una llamada de render en particular, necesita usar el siguiente patrón:

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

Prueba utilizando definido? El titular no funcionará. Esta es una restricción de implementación.


Creo que una mejor opción que permite múltiples variables predeterminadas:

<% 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] %>


Dado que local_assigns es un hash, también puede usar fetch con el default_value opcional.

local_assigns.fetch :foo, default_value

Esto devolverá default_value si foo no fue establecido.

ADVERTENCIA:

Tenga cuidado con local_assigns.fetch :foo, default_value cuando default_value es un método, ya que se llamará de todos modos para pasar su resultado a fetch .

Si su default_value es un método, puede envolverlo en un bloque: local_assigns.fetch(:foo) { default_value } para evitar su llamada cuando no sea necesario.


En mi caso, yo uso:

<% variable ||= "" %>

en mi parcial
No tengo idea si eso es bueno pero para mi está bien.


Esta es una derivada de la respuesta de Pablo. Esto me permite establecer un valor predeterminado (''completo''), y al final, ''modo'' se establece tanto en local_assigns como en una variable local real.

haml / slim:

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

erb

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


Hago esto:

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


Más intuitivo y compacto:

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


Qué tal si

<% foo ||= default_value %>

Esto dice "use foo si no es nulo o verdadero. De lo contrario, asigne el valor default_value a foo"


Sé que es un hilo viejo, pero aquí está mi pequeña contribución: usaría local_assigns[:foo].presence en un conditional dentro del parcial. Luego configuro foo solo cuando sea necesario en la llamada de render:

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

Echa un vistazo a la guía oficial de rieles aquí . Válido desde RoR 3.1.0.


Se puede crear un ayudante para que se vea así:

somearg = opt(:somearg) { :defaultvalue }

Implementado como:

module OptHelper def opt(name, &block) was_assigned, value = eval( "[ local_assigns.has_key?(:#{name}), local_assigns[:#{name}] ]", block.binding) if was_assigned value else yield end end end

Ver mi blog para más detalles sobre cómo y por qué.

Tenga en cuenta que esta solución le permite pasar nulo o falso como valor sin que se invalide.


Si no quiere pasar una variable local a parcial cada vez que la llame, haga esto:

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

De esta manera evitas errores de undefined variable . Esto le permitirá llamar a su parcial con / sin variables locales.