W aktywnym rekordzie znajduje się przydatny atrybut dynamiczny o nazwie find_or_create_by:
Model.find_or_create_by_<attribute>(:<attribute> => "")
Ale co jeśli będę musiał znaleźć_lub_tworzyć za pomocą więcej niż jednego atrybutu?
Powiedzmy, że mam model do obsługi relacji M: M między grupą a członkiem o nazwie GroupMember. Mógłbym mieć wiele instancji, w których member_id = 4, ale nigdy nie chcę więcej niż jednej instancji, gdzie member_id = 4 i group_id = 7. Próbuję dowiedzieć się, czy można zrobić coś takiego:
GroupMember.find_or_create(:member_id => 4, :group_id => 7)
Zdaję sobie sprawę, że mogą istnieć lepsze sposoby na poradzenie sobie z tym, ale podoba mi się wygoda pomysłu find_or_create.
Dla każdego, kto natknie się na ten wątek, ale musi znaleźć lub utworzyć obiekt z atrybutami, które mogą ulec zmianie w zależności od okoliczności, dodaj następującą metodę do swojego modelu:
Wskazówka dotycząca optymalizacji: bez względu na to, które rozwiązanie wybierzesz, rozważ dodanie indeksów najczęściej zadawanych atrybutów.
źródło
find_or_create_by
będzie.Model.where(attributes).instance_eval{|q| q.first || q.create}
.find_or_create
ma również tę zaletę, że wykorzystuje transakcję, w którejwhere….first || create
wprowadza warunek wyścigudef self.find_or_create(attributes) self.where(attributes).first || self.create(attributes) end
, żebyście nie musieli powtarzaćModel
self
w treści metody (ponieważ chcesz usunąć słowa!).W Rails 4 możesz:
I użycie
where
jest inne:Wywoła to
create
naGroupMember.where(member_id: 4, group_id: 7)
:Na Przeciwnie,
find_or_create_by(member_id: 4, group_id: 7)
będzie zadzwonićcreate
naGroupMember
:Proszę zobaczyć to odpowiednie zatwierdzenie na szynach / szynach.
źródło
Przekazywanie bloku do
find_or_create
, możesz przekazać dodatkowe parametry, które zostaną dodane do obiektu, jeśli zostanie on utworzony jako nowy. Jest to przydatne, jeśli sprawdzasz obecność pola, którego nie szukasz.Zarozumiały:
następnie
utworzy nowego członka grupy o nazwie „John Doe”, jeśli go nie znajdzie
member_id 4
and group_id 7
źródło
Możesz to zrobić:
Lub po prostu zainicjować:
źródło