Ответ 1
Из Guides
first_or_create
Метод first_or_create
проверяет, первым ли возвращает nil или нет. Если он возвращает nil, тогда вызывается create. Это очень эффективно при сочетании метода. Давайте посмотрим пример.
Предположим, вы хотите найти клиента с именем "Энди", а если нет, создайте его и добавьте его заблокированный атрибут в значение false. Вы можете сделать это, выполнив:
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">
SQL, сгенерированный этим методом, выглядит следующим образом:
SELECT * FROM clients WHERE (clients.first_name = 'Andy') LIMIT 1
BEGIN
INSERT INTO clients (created_at, first_name, locked, orders_count, updated_at) VALUES ('2011-08-30 05:22:57', 'Andy', 0, NULL, '2011-08-30 05:22:57')
COMMIT
first_or_create
возвращает либо уже существующую запись, либо новую запись. В нашем случае у нас уже не было клиента с именем Andy, поэтому запись была создана и возвращена.
first_or_create!
Вы также можете использовать first_or_create!
для создания исключения, если новая запись недействительна. Проверки не рассматриваются в этом руководстве, но давайте предположим, что вы временно добавили
validates :orders_count, :presence => true
для вашей модели клиента. Если вы попытаетесь создать нового Клиента без передачи order_count, запись будет недействительной и будет вызвано исключение:
Client.where(:first_name => 'Andy').first_or_create!(:locked => false)
# => ActiveRecord::RecordInvalid: Validation failed: Orders count can't be blank