Mam problem od kilku godzin, aby sprawdzenie atrybutów zagnieżdżonych działało w mojej aplikacji rails. Małe zastrzeżenie polega na tym, że muszę sprawdzać atrybuty zagnieżdżone dynamicznie w oparciu o ich atrybuty rodzica, ponieważ ilość wymaganych informacji zmienia się w czasie w zależności od miejsca w procesie, w którym znajduje się rodzic.Rails accept_nested_attributes_for validation na obiekcie transakcyjnym
Oto moja konfiguracja: Mam obiekt nadrzędny z wieloma różnymi skojarzonymi modelami i chcę sprawdzać kolejno zagnieżdżone atrybuty tych za każdym razem, gdy zapisuję obiekt nadrzędny. Biorąc pod uwagę fakt, że walidacje zmieniają się dynamicznie, musiałem napisać metodę zwyczaj sprawdzania poprawności w modelu
class Parent < ActiveRecord::Base
attr_accessible :children_attributes, :status
has_many :children
accepts_nested_attributes_for :children
validate :validate_nested_attributes
def validate_nested_attributes
children.each do |child|
child.descriptions.each do |description|
errors.add(:base, "Child description value cant be blank") if description.value.blank? && parent.status == 'validate_children'
end
end
end
end
class Child < ActiveRecord::Base
attr_accessible :descriptions_attributes, :status
has_many :descriptions
belongs_to :parent
accepts_nested_attributes_for :descriptions
end
W moim kontroler nazywam update_attributes na rodzica, gdy chcę, aby zapisać. Problem polega na tym, że prawdopodobnie szyny przeprowadzają walidacje w bazie danych, a nie w stosunku do obiektu, który został zmodyfikowany przez użytkownika lub kontroler. Więc może się zdarzyć, że wartość użytkownika zostanie usunięta przez użytkownika, a sprawdzanie poprawności zostanie zakończone, a późniejsze sprawdzanie poprawności nie przejdzie, ponieważ element w bazie danych jest niepoprawny.
Oto krótki przykład tego scenariusza:
parent = Parent.create({:status => 'validate_children', :children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => 'Not blank!'}}}})
#true
parent.update_attributes({:children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => nil}}}})
#true!!/since child.value.blank? reads the database and returns false
parent.update_attributes({:children_attributes => {0 => {:descriptions_attributes => { 0 => {:value => 'Not blank!'}}}})
#false, same reason as above
Walidacja pracuje dla organizacji pierwszego stopnia, na przykład jeśli dziecko ma atrybut "value", mogę przeprowadzić walidację w taki sam sposób jak ja. Problem polega na głębokich skojarzeniach, które najwyraźniej nie mogą być zatwierdzone przed zapisaniem.
Czy ktoś może wskazać mi właściwy kierunek rozwiązania? Jedyny sposób, jaki widzę obecnie, to zapisywanie rekordów, ich walidacja i usuwanie/przywracanie, jeśli walidacja się nie powiedzie, ale szczerze mam nadzieję, że coś będzie czystsze.
Dziękuję wszystkim z góry!
ROZWIĄZANIE
Okazuje się, biegałam walidacji na głębokich modeli zagnieżdżonych poprzez odniesienie tych bezpośrednio w walidacji niestandardowej, w ten sposób:
class Parent < ActiveRecord::Base
[...]
has_many :descriptions, :through => :children
[...]
def validate_nested_attributes
descriptions.each do |description|
[...]
end
end
end
które z jakiegoś powodu prowadzi do problemów Miałem powyżej. Dzięki Santoshowi za przetestowanie mojego przykładu kodu i zgłoszenie, że działa, to wskazało mi właściwy kierunek, aby to zrozumieć.
W celu późniejszego wykorzystania, kod w pytaniu oryginalnym działa w przypadku tego typu dynamicznych, głęboko zagnieżdżonych sprawdzeń.
Istnieje kilka błędów w kodzie. To może być literówka. 1. "Wartość podrzędna nie może być pusta" - pojedynczy cudzysłów w jednym cudzysłowie. 2. && parent.status = 'validate_children' - To nie jest porównanie. jego zadanie –
przykro mi z powodu literówek! Kod tutaj jest tylko uproszczonym przykładem mojej aplikacji, więc nie jest to powód, dla którego nie działa, ale dzięki za wskazanie tego :) –