Rails - Как использовать Find or Create
У меня есть следующее:
@permission = @group.permissions.create(
:user_id => @user.id,
:role_id => 2,
:creator_id => current_user.id)
Как я могу обновить это как find_or_create
, так что если эта запись уже существует, она назначается @permission
, а если она не существует, запись создается?
Ответы
Ответ 1
Связанная тема:
find_or_create_by в Rails 3 и обновление для создания записей
Вы можете расширить ActiveRecord с помощью собственного метода update_or_create
(см. соответствующую тему), а затем вы можете использовать этот
@permission = Permission.update_or_create_by_user_id_and_role_id_and_creator_id(@user.id, 2, current_user.id) do |p|
p.group_id = @group.id
end
Или вы можете использовать метод find_or_create_by...
:
@permission = Permission.find_or_create_by_user_id_and_role_id_and_creator_id(@user.id, 2, current_user.id)
@permission.group = @group
@permission.save
Ответ 2
Несмотря на то, что принятый ответ правильный, важно отметить, что в Rails 4 этот синтаксис будет меняться (и хэш-синтаксис). Вы должны написать следующее:
@permission = Permission.where(
user_id: @user.id,
role_id: 2,
creator_id: current_user.id).first_or_create
Что на самом деле выглядит намного ближе к вашему оригинальному методу! Подробнее см. Подраздел Устаревшие искатели.
Ответ 3
Я обновляю вопросы с версиями ответов. Потому что его важно.
Rails 4 (docs)
Существует несколько способов "найти или создать" объект, один из которых - find_or_create_by(args)
Client.find_or_create_by(email: "[email protected]", phone: "4255551212")
Но предпочтительный способ сообщества использует where
client = Client.where(email: "[email protected]", phone: "4255551212").first_or_create
а затем вы можете сделать что-то вроде:
client = Client.where(client_params.slice(:email, :phone)).first_or_create
client.update(client_params)
Rails 3 (docs)
Предположим, вы хотите найти клиента с именем "Andy", и если theres нет, создайте его и добавьте его заблокированный атрибут в значение false. Ты можешь сделайте это, выполнив:
client = Client.where(:first_name => 'Andy').first_or_create(:locked => false)
# => #<Client id: 1, first_name: "Andy", orders_count: 0, locked: false, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
Ответ 4
Или вы хотите попробовать это, если у вас есть много полей для заполнения:
conditions = { :user_id => @user.id,
:role_id => 2,
:creator_id => current_user.id }
@permission = group.permissions.find(:first, :conditions => conditions) || group.permissions.create(conditions)
посмотреть это сообщение:
Как передать несколько атрибутов find_or_create_by в Rails 3?