Witam,
szukam jakiedos dobrego rozwiazania nastepujacego problemu. Walidacja odbywa sie za pomoca validates_uniqueness_of w modelu. Jesli okaze sie podczas walidacji, ze dany rekord istnieje, chcialbym go po prostu stworzyc jakis link w widoku do tego istniejacego rekordu. Myslalem o zalatwieniu sprawy juz podczas walidacji, mowiac scislej przez przekazanie odpowiedniego linku do rekordu w przekazywanej informacji :message z metody validates_uniqueness_of, ktora i tak trafia do widoku przez standardowa metode flash. Czy jest to mozliwe? Z gory serdecznie dziekuje za jakas pomoc w tej sprawie.
[code]tag = Tag.find_or_create(:name => “my tag”)
This will indeed return a tag - creating it on the fly if you don’t have one in your database. You can also interrogate it to see if it’s a new record (wanna guess with the method name is?)
tag.new_record? #returns true if it’s a new record. Duh.[/code]
find_or_create chyba zawsze zwróci zapisany rekord, czy się mylę?
Nie dam sobie głowy uciąć ale chyba można tak:
tag = Tag.find_or_create_by_name!("my tag", {:atrybuty_do_create => "jak nie istnieje tag i zostanie stworzony"})
Dzieki sebcioz za ciekawe rozwiazanie. Rozumiem, ze masz na mysli, ze w kontrolerze mozna sobie taki tag utworzyc i sprawdzic latwo, czy istnieje juz taki record w bazie.
Mysle paneq, ze metoda find_and_create najpierw sprawdza, czy jest taki rekord w bazie, a jak nie ma to dopiero tworzy taki obiekt i zapisuje do bazy. Czyli do zapisu dochodzi tylko kiedy nie ma takiego recordu.
Sorry za wnikliwosc, ale czy jest jakis sposob, ktory pozwoli po walidacji metoda validates_uniqueness_of uzyskac cos podobnego. Chodzi o to, ze walidacja odbywa sie w specyficzny sposów
validates_uniqueness_of :last_name , :message => "jest już zajęte dla danego Imienia i Pseudonimu! <br/>Jeśli dane sa poprawne zmien/wprowadz Pseudonim.",:scope => [:first_name, :nick],:case_sensitive =>false
Dzieki takiej walidacji unikalnosc nowego rekordu jest weryfikowana na podstawie 3 pol, last_name, first_name oraz nick. Dodam, ze w modelu jest wiecej pól, ale tylko te 3 maja byc unikalne. Moze moznaby z poziomu bazy zapewnic taka unikalnosc, ale w tym wprzypadku tak nie jest. Wiec tutaj walidacja dba o unikalnosc. Ale do czego zmierzam… Moze by tu zadzialala taka funkcja
find_by_first_name_and_last_name_and_nick_or_create (params[:client])
Client to model, gdzie sa te 3 pola wymienione powyzej oraz jeszcze inne.
Jak myslicie, takie rozwiazanie byloby poprawne. Czy moze w tym konkretnym przypadku nalezaloby podejsc jakos inaczej?
Generalnie, problem wydaje sie dosc zyciowy i powinien byc popularny. Np. wprowadzam nowego klienta do bazy i okazuje sie, ze on juz istnieje. Jednak zamiast przechodzic do wyszukiwarki klientow i tracic czas na odszukanie go (bo na przyklad chce sprawdzic, czy inne dane jego sa prawidlowe i czegos nie brakuje)… bardzo wygodnym byloby wygenerowanie linku do tego Klienta wraz z walidacja metoda validates_uniqueness_of i komunikatem o istniejacym kliencie. To wydaje sie dosc logiczne. Reasumujac, jak walidacja informuje mnie, ze klient istnieje, to chce go zaraz sprawdzic przez klikniecie odpowiedniego linku.
Sorry, troche sie rozpisalem…
Totalnie nie zrozumiałem o ci ci chodzi na początku i dalej za bardzo nie widzę żadnego problemu.
Przypuszczam, ze rozumiesz idee. Walidacja w ten sposob zapisana powoduje, ze klient jest unikalny tylko wtedy, gdy 3 pola w bazie sa takie same. To zasluga metody validates_uniqueness_of i takiego jej zapisu. W formularzu klienta wpisujesz na przyklad imie, nazwisko, nick, wiek, data urodzenia, uwagi etc. Klikasz ok, aby wprowadzic dane. Walidacja sprawdza czy klient jest unikalny tylko po 3 polach imie, nazwisko, nick (takie zalozenia).
Jesli uzyjesz metody po prostu find_by_last_name_or_create (params[:client]) to metoda find nie zadziala jak nalezy, bo wyszuka Klienta po nazwisku, a kowalskich moze byc wiele. W tym wyszukiwaniu musze wyszukiwac tylko unikalnych Klientow. Moze jakims rozwiazaniem moglaby byc taka postac metody find or create jak sugerowalem w poprzednim poscie.
Ale, tak sobie mysle, ze projektanci rails zdawali sobie sprawe z tego, ze ktos w kontrolerze bedzie chcial badac wyniki walidacji, i na tej podstawie podejmowac odpowiednie dzialania… U mnie np. moznaby zrobic tak. Jesli pojawi sie blad w walidacji, sprawdzam w kontrolerze czego on dotyczy i jesli wynikiem bledu jest istniejacy klient (czyli zadzialala metoda validates_uniqueness_of), to tworze link do danego klienta (zeby go mozna szybko podejrzec)… Ma to jakis sens i wydawaloby sie sie naturalne… Nie uwazasz? Tylko jak by to mozna zrobic ladnie w ruby on rails…
Podczas walidacji nie powinno się robić takich rzeczy jak tworzenie rekordu.
Ja bym użył:
before_validate do |r|
Foo.find_or_create ...
end
Jeżeli chcesz rzucić jakimś błędem możesz zrobić jeszcze tak:
[code]before_validate do |r|
foo = Foo.find
if foo.blank?
Foo.create
else
r.errors.add :base, ‘error message’
end
end[/code]
@MarcinZS http://stackoverflow.com/questions/3046607/rails-find-or-create-by-more-than-one-attribute/3046645#3046645
Dzieki Panowie za rozne podpowiedzi, a co sadzicie o takim postawieniu sprawy, nieco z innej strony? Moze by tak.
[code] rescue_from ActiveRecord::RecordNotUnique, :with => :my_rescue_method
…
protected
def my_rescue_method
tu moznaby wygenerowac link do recordu, ktory juz istnieje (nie jest unikalny)
end[/code]
Zagraloby to z metoda metody validates_uniqueness_of…?
rozwiązanie seeweera wydaje mi się bardziej poprawne, wyjątków używa się raczej do obsługiwania zdarzeń, które nie powinny wystąpić ale… może się zdarzyć, typu błąd zapisu do pliku itp, czy to że Twój rekord już istnieje to planowana sytuacja czy wynik jakiegoś błędu ?
Witaj Arturze, ale wyjatek dotyczy tylko tego concretnego bledu RecordNotUnique, a nie zapisu czy innego rodzaju wyjatkow. A wiec sytuacja dotyczy sytuacji w ktorej dany record nie jest unikalny, wiec dokladnie o co mi chodzi. Inne wyjatki nie powinny tu byc obslugiwane, tak mysle.
Czy nie jest tak, ze metoda validates_uniqueness_of wyrzuca i tak wlasnie taki blad podczas walidacji, jesli nie przebiega ona pomyslnie? Mam racje? A wiec moze wystarczy w kontrolerze tylko sprawdzic (np. tak jak wygooglowalem powyzej), czy taki wlasnie wyjatek wystapil.
Powiedzcie prosze, czy cos tu nie krece, ale czy validates_uniqueness_of nie generuje wlasnie tego konkretnego bledu RecordNotUnique?