Kiedy używać self w modelu?
Pytanie: kiedy muszę używać self w moich modelach w Rails?
Mam metodę set
w jednym z moich modeli.
class SomeData < ActiveRecord::Base
def set_active_flag(val)
self.active_flag = val
self.save!
end
end
Kiedy to robię, wszystko działa dobrze. Jednak kiedy to robię:
class SomeData < ActiveRecord::Base
def set_active_flag(val)
active_flag = val
save!
end
end
Wartość active_flag nie zmienia się, raczej zawodzi po cichu. Czy ktoś może to wyjaśnić?
Nie mogę znaleźć żadnych duplikatów, ale jeśli ktoś znajdzie, to też jest w porządku.4 answers
Gdy wykonujesz akcję na instancji wywołującej metodę, używasz self.
Z tym kodem
class SocialData < ActiveRecord::Base
def set_active_flag(val)
active_flag = val
save!
end
end
Definiujesz zupełnie nową zmienną lokalną o zasięgu o nazwie active_flag, ustawiając ją na wartość przekazaną, nie jest ona z niczym powiązana, więc jest natychmiast odrzucana, gdy metoda kończy się tak, jakby nigdy nie istniała.
self.active_flag = val
Każe jednak instancji zmodyfikować swój własny atrybut o nazwie active_flag, zamiast zupełnie nowej zmiennej. Dlatego to działa.
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-05-29 19:25:24
Dzieje się tak z powodu zakresu. Gdy jesteś wewnątrz metody i próbujesz ustawić nową zmienną, taką jak ta:
class SomeData < ActiveRecord::Base
def set_active_flag(val)
active_flag = val
end
end
Tworzysz nową zmienną, która mieszka wewnątrz set_active_flag. Gdy tylko to się skończy, znika, nie zmieniając w żaden sposób self.active_flag
(rzeczywistej zmiennej instancji).
Jednakże (było to dla mnie źródłem nieporozumień): kiedy próbujesz odczytać zmienną instancji w Rubim, jak to:
class SomeData < ActiveRecord::Base
def whats_my_active_flag
puts active_flag
end
end
Zostanie zwrócona self.active_flag
(zmienna rzeczywistej instancji).
Oto dlaczego:
Ruby zrobi wszystko, aby uniknąć powrotu nil
.
- początkowo pyta "czy
active_flag
istnieje w zakresiewhats_my_active_flag
?
W przeciwieństwie do innych języków, w których nie ma żadnego znaczenia, nie ma znaczenia, czy są to Języki Obce, czy Języki Obce.]}
- ponownie pyta o to samo: "czy
active_flag
istnieje w tym scope? - odpowiedź brzmi "tak" , a więc mówi "mam coś dla Ciebie" i zwraca to!
active_flag
w whats_my_active_flag
, a następnie poprosisz o to, przejdzie to ponownie przez kroki:
- pyta "czy
active_flag
istnieje w zakresiewhats_my_active_flag
? - odpowiedź brzmi "yup" , więc zwraca tę wartość
W obu przypadkach, nie zmieni wartości self.active_flag
, chyba że wyraźnie go polecisz.
Łatwy sposób na opisz to zachowanie: "nie chce cię rozczarować" i wróć nil
-- więc stara się znaleźć wszystko, co może.
W tym samym czasie "nie chce mieszać danych, których nie zamierzałeś zmienić", więc nie zmienia samej zmiennej instancji.
Mam nadzieję, że to pomoże!
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
2013-12-23 06:31:57
Ma na celu upewnienie się, że używasz metody setter i nie wyznaczasz nowej zmiennej. Jest to szczegół użycia Ruby i AR, który często podskakuje ludziom (drugim jest (błędne) użycie zmiennej instancji).
Uwaga jest już update_attributes!Chociaż rozumiem pragnienie abstrakcji.
Jest też przełącznik!, który może być jeszcze ładniejszy, w zależności od interfejsu do flagi.
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-05-29 19:24:57
Kiedy używasz active_flag = val
ruby myślał, że definiujesz lokalną zmienną, najlepszym sposobem jest self.active_flag = val
, jeśli ją masz, mam nadzieję, że wiesz, że send(:active_flag=, val)
również zadziała.
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
2017-10-30 15:30:51