opcjonalne zmienne lokalne w szablonach częściowych rails: jak wyjść z (zdefiniowanego? Foo) bałagan?

Byłem złym dzieckiem i użyłem następującej składni w moich szablonach częściowych, aby ustawić domyślne wartości dla zmiennych lokalnych, jeśli wartość nie była wyraźnie zdefiniowana w hashu: locals podczas renderowania częściowego --

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

Wydawało się, że to działa dobrze do niedawna, kiedy (bez powodu nie mogłem rozpoznać) nieprzepisowe zmienne zaczęły zachowywać się tak, jakby zostały zdefiniowane jako nil (a nie undefined).

Jak wskazywały różne pomocne osoby na tak, http://api.rubyonrails.org/classes/ActionView/Base.html mówi Nie aby używać

defined? foo

I zamiast używać

local_assigns.has_key? :foo

Próbuję zmienić moje sposoby, ale to oznacza zmianę wielu szablonów.

Czy Mogę / powinienem po prostu ładować do przodu i wprowadzić tę zmianę we wszystkich szablonach? Czy jest jakaś sztuczka, na którą muszę uważać? Jak pilnie muszę przetestować każdą z nich?

Author: brahn, 2010-01-14

12 answers

Robię to:

<% some_local = default_value if local_assigns[:some_local].nil? %>
 289
Author: jonnii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-17 22:03:33

Ponieważ local_assigns jest Hashem, możesz również użyć fetch z opcjonalnym default_value.

local_assigns.fetch :foo, default_value

Zwróci default_value Jeśli foo nie zostało ustawione.

Ostrzeżenie:

Bądź ostrożny z local_assigns.fetch :foo, default_value, Gdy default_value jest metodą, ponieważ i tak zostanie ona wywołana, aby przekazać jej wynik do fetch.

Jeśli twoja default_value jest metodą, możesz ją zawinąć w blok: local_assigns.fetch(:foo) { default_value }, aby zapobiec jej wywołaniu, gdy nie jest potrzebna.

 135
Author: Pablo Cantero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-01 15:52:00

A może

<% foo ||= default_value %>

Tu jest napisane " użyj foo, jeśli nie jest to nil lub true. W przeciwnym razie Przypisz default_value do foo "

 77
Author: hgmnz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-13 22:35:17

Myślę, że należy to powtórzyć tutaj (z http://api.rubyonrails.org/classes/ActionView/Base.html):

Jeśli chcesz dowiedzieć się, czy pewnej zmiennej lokalnej przypisano wartość w konkretnym wywołaniu renderowania, musisz użyć następującego wzorca:

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

Testowanie za pomocą zdefiniowanych? nagłówek nie zadziała. Jest to ograniczenie implementacji.

 10
Author: gamov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-09 06:31:18

Wiem, że to stary wątek, ale oto mój mały wkład: użyłbym {[1] } Wwarunkowym wewnątrz częściowego. Następnie ustawiam foo tylko wtedy, gdy jest to potrzebne w wywołaniu renderowania:

<%= render 'path/to/my_partial', always_present_local_var: "bar", foo: "baz" %>
Zobacz te oficjalny przewodnik po szynach tutaj . Obowiązuje od RoR 3.1.0.
 3
Author: microspino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-28 22:04:56

W moim przypadku używam:

<% variable ||= "" %>
W mojej części.
Nie mam pojęcia czy to dobre ale dla mojego jest OK
 3
Author: Moises Portillo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-28 22:50:59

Myślę, że lepsza opcja, która pozwala na wiele zmiennych domyślnych:

<% 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
Author: Daniel OCallaghan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-13 03:39:44

To pochodna odpowiedzi Pabla. Pozwala mi to ustawić wartość domyślną ('full'), a na końcu 'mode' jest ustawiany zarówno w local_assigns, jak i w rzeczywistej zmiennej lokalnej.

Haml / slim:

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

Erb:

<% mode ||= local_assigns[:mode] = local_assigns.fetch(:mode, 'full') %>
 1
Author: sethcall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-13 15:59:03

Bardziej intuicyjny i kompaktowy:

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

 0
Author: muirbot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-16 20:07:34

Jeśli nie chcesz przekazać zmiennej lokalnej do partial za każdym razem, gdy ją wywołasz, zrób to:

<% local_param = defined?(local_param) ? local_param : nil %>
W ten sposób unikniesz błędu. Pozwoli to na wywołanie częściowego z / bez zmiennych lokalnych.
 0
Author: Haris Krajina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-04 19:32:14

Ruby 2.5

Erb

To możliwe, ale musisz zadeklarować swoje domyślne wartości w zakresie.

Zmienna słowo do zastąpienia.

# 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
Author: dimpiax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-12 15:52:24

Helper może być utworzony tak, aby wyglądał tak:

somearg = opt(:somearg) { :defaultvalue }

Zaimplementowane jak:

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

Zobacz mój blog Po szczegóły jak i dlaczego.

Zauważ, że to rozwiązanie pozwala na podanie nil lub false jako wartości bez jej nadpisywania.

 -5
Author: Jaime Cham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-30 02:16:29