В active-record есть полезный динамический атрибут с именем find_or_create_by:
Model.find_or_create_by_<attribute>(:<attribute> => "")
Но что, если мне нужно найти find_or_create более чем одним атрибутом?
Скажем, у меня есть модель для обработки отношений M: M между Группой и Участником, которая называется GroupMember. У меня может быть много случаев, когда member_id = 4, но я никогда не хочу более одного раза, когда member_id = 4 и group_id = 7. Я пытаюсь выяснить, возможно ли сделать что-то подобное:
GroupMember.find_or_create(:member_id => 4, :group_id => 7)
Я понимаю, что могут быть лучшие способы справиться с этим, но мне нравится удобство идеи find_or_create.
Для тех, кто сталкивается с этим потоком, но ему нужно найти или создать объект с атрибутами, которые могут меняться в зависимости от обстоятельств, добавьте в вашу модель следующий метод:
Совет по оптимизации: независимо от того, какое решение вы выберете, рассмотрите возможность добавления индексов для атрибутов, которые вы запрашиваете чаще всего.
источник
find_or_create_by
будет.Model.where(attributes).instance_eval{|q| q.first || q.create}
.find_or_create
также имеет преимущество использования транзакции, гдеwhere….first || create
вводится условие гонкиdef self.find_or_create(attributes) self.where(attributes).first || self.create(attributes) end
что вам не нужно повторятьModel
self
внутри тела метода (так как вы хотите удалить слова!).В Rails 4 вы можете сделать:
И использование
where
отличается:Это будет призывать
create
кGroupMember.where(member_id: 4, group_id: 7)
:Наоборот, то
find_or_create_by(member_id: 4, group_id: 7)
призоветcreate
наGroupMember
:Пожалуйста, смотрите этот соответствующий коммит на рельсах / рельсах.
источник
Передав блок в
find_or_create
, вы можете передать дополнительные параметры, которые будут добавлены к объекту, если он создан новым. Это полезно, если вы проверяете наличие поля, по которому вы не ищете.Предполагая, что:
затем
создаст новый член группы с именем «Джон Доу», если не найдет его с
member_id 4
and group_id 7
источник
Ты можешь сделать:
Или просто инициализировать:
источник