def post_code
self.place ? self.place.post_code : @post_code
end
end[/code]
Kod działa jak chcę, tylko skąd w @post_code są dane skoro ich nigdzie nie przypisałem?
Działa, bo jak robię edycję to dla Plant pobiera mi z Place post_code, a jak daje nowy to mam pusto, agdy robie zapisz i nie przechodzi walidacji to post_code wpisany pozostaje.
Mam w modelu dwa pola dla uproszczenia: post_code, pole wirtualne i pole location_id.
W modelu początkowo miałem:
def post_code
self.place.try(:post_code)
end
Na oba pola miałem ustawioną walidację, że muszą być wypełnione.
Jak podczas zapisu nowego planta podałem tylko post_code, to po powrocie do edycji pole post_code nie było wypełnione.
A po zmianie na taki kod w modelu:
self.place ? self.place.post_code : @post_code pole post_code jest wypełnione
Dlatego napisałem że działa.
Chodziło o to aby po powrocie do edycji, po przejściu przez walidacje pole post_code było wypełnione. A w pierwszym przypadku nie było.
Mam nadzieję, że to jest dobre rozwiązanie tego problemu.
ale nie rozumiem, chcesz przy tworzeniu Plant utworzyć Place z podanym w formularzu post_code? co robisz z tym post_code przy zapisie? to przecież jest (jak to nazwałeś) wirtualne pole, więc nie zapisujesz go do bazy.
Nie, Place to baza wszystkich kodów + miejscowości w Polsce. I za pomocą wirtualnego pola ograniczam wyświetlanie miejscowości do tych z podanym kodem. W modelu Plant zapisuje w polu place_id, id z modelu Place.
To chyba zły pomysł. Pachnie mi zmiennymi globalnymi.
Raczej zdefiniuj sobie normalną metodę zwracającą odfiltrowane wyniki, w odpowiednim miejscu kontrolera (na przykład) zbierz te wyniki do innej zmiennej i pracuj na niej. Wszystko będzie bardziej czytelne i nie będziesz miał problemu, że np. w jakiejś innej akcji (w uproszczeniu - proszę nie czepiać się, że zmienne instancji normalnie nie przeżywają do następnej akcji) pozostanie zmienna filtrująca z poprzedniej i wyniki będziesz miał za każdym razem inne.
def post_code
self.place.try(:post_code)
end
zmieniłem na:
def post_code
self.place ? self.place.post_code : @post_code
end
Chodzi o to dlaczego w @post_code jest kod w przypadku nie przejscia przez walidacje dla akcji new.
Napisałem, że jest zapach zmiennych globalnych, a nie że one same
Chyba rozumiem, w czym problem, ale o tym później. To co wydało mi się nie za dobre, to gdy napisałeś, że “za pomocą wirtualnego pola ograniczam wyświetlanie miejscowości”. Dla potrzeb filtrowania, zmienna instancji… zgodzę się, że to jeszcze nie znaczy, że kod masz zły, ale to już wydaje się podejrzane. Zależy jak to dalej oprogramowałeś, ale bezpieczniej jest zamiast zmiennej zdefiniować metodę filtrującą i po prostu przekazać jej parametr. Wtedy “zmienna filtrująca” jest zapominana jak tylko funkcja kończy z niej korzystać i wszystko jest OK.
Teraz wyczuwam na podstawie słów “Jak podczas zapisu nowego planta podałem tylko post_code, to po powrocie do edycji pole post_code nie było wypełnione.”, że oczekiwałeś iż wartość tej zmiennej zostanie jakoś zapamiętana pomiędzy dwoma akcjami (:create i :edit). Otóż żadne zmienne instancji nie przeżywają końca akcji (tej metody w kontrolerze). Jeżeli chcesz ją zapamiętać, to musisz stworzyć normalne pole w bazie danych - nie wirtualny, a standardowy atrybut. I wtedy wszystko będzie OK.
W akcji :new nie ma walidacji. Walidacja może być wywołana w akcji :create. Nie do końca rozumiem też dlaczego nieudana walidacja miałaby powodować wyczyszczenie jakiegoś atrybutu, oczekiwałbym też, że raczej zmienna będzie pusta, a nie że będzie w niej jakiś “kod”. Czy twierdzisz, że zmienna @post_code zawiera jakąś wartość dla obiektu wyśwetlanego w akcji :new? Jeśli tak, to ja bym raczej podejrzewał, że to przeglądarka wypełnia Ci pola formatki. Możesz dać w dowolnym miejscu kody coś takiego:
Tak, chodziło mi o zmienną @post_code. Oczywiście mogłem coś źle zrozumieć, kodu nie doczytać i tak dalej. Normalnie bym zapytał o to, jak tej zmiennej używasz, przejrzał testy i akcje z niej korzystające i wtedy bym wiedział, czy technika, którą stosujesz jest bezpieczna, czy nie, i dopiero wtedy moje komentarze by miały jakąś wartość.
Generalnie to zapomnij, że cokolwiek mówiłem. Przyjmijmy, że to było zagrożenie urojone.
Ale czy miałem rację zakładając, że oczekiwałeś iż ta zmienna zachowa swoją wartość pomiędzy akcjami :create i :edit?
Chodzi o to, że ja tej zmiennej nie ustawiam nigdzie, tylko raz jest użyta w tym miejscu co powyżej i nic więcej i chodzi o to skąd w tej zmiennej po nie przesciu walidacji w akcji create ta zmienna jest ustawiona.
w modelu Plant jest taki kod
attr_accessor: post_code
def post_code
self.place ? self.place.post_code : @post_code
end
Nie chodzi o to aby ta zmienna zachowała wartość tylko skąd ona w tej zmiennej @post_code (ta wartość ) się wzięła.