Zmienne lokalne w widokach cz.1

Dosyć często spotykam się z użyciem zmiennych lokalnych w widokach Rails’ów. W większości wypadków po dokładniejszej analizie okazuje się, że możliwe jest pozybycie się zmiennych lokalnych w widokach i zastąpienie ich np. wywołaniem metody czy utworzeniem specjalnego obiektu).

Dzisiaj przykład, z którym spotykam się dosyć często w kodzie pisanym przez świeżo upieczonych koderów Rails:

<% colour_message = nil %> <% f.fields_for :widget_attributes do |waf| -%> <% if waf.object.name.downcase =~ /colour\Z/ and colour_message.nil? %> Standard colours are as follows: Red Light blue <% colour_message = :shown -%> <% end %> <% end -%>
Tutaj zmienna colour_message została użyta do przechowania stanu wyświetlenia wiadomości (chodzi o to, że “Standard colours” powinna zostać wyświetlona tylko 1 raz, pomimo tego, że jest wołana w pętli (fields_for :widget_attributes możemy spokojnie zastąpić dowolną pętlą).

Czy można poprawić ten kod?

Korzystając z bloków, możemy napisać metodę helpera której zadaniem będzie wywołanie bloku tylko 1 raz niezależnie od tego ile razy ona sama zostanie wywołana:

widok:

<% f.fields_for :widget_attributes do |waf| -%> <% if waf.object.name.downcase =~ /colour\Z/ %> <% once do -%> Standard colours are as follows: Red Light blue <% end -%> <% end %> <% end -%>

[code=ruby]module ApplicationHelper

def once(name = “default”)
name = name.to_s
yield unless instance_variable_get("@_once#{name}")
instance_variable_set("@_once#{name}", true)
end

end[/code]
Dzięki tej metodzie, możemy pozbyć się zmiennej lokalnej w widoku i oczywiście wykorzystać ten wzorzec w innych widokach w aplikacji. Warto jeszcze dodać, że jeśli chcemy w jednym widoku skorzystać z “once” więcej niż 1 raz to musimy nazwać każde jej wywołanie, np:

[code=ruby]<% for i in (1…10) do -%>
<% once(:something) do -%>
# do something only once
<% end -%
<% end -%>

<% for i in (1…10) do -%>
<% once(:something_else) do -%>
# do something else only once
<% end -%
<% end -%>[/code]