сохранить массив активных записей - PullRequest
17 голосов
/ 19 февраля 2010

У меня есть такой массив

a = []

a << B.new(:name => "c")
a << B.new(:name => "s")
a << B.new(:name => "e")
a << B.new(:name => "t")

Как я могу сохранить его сразу?

Ответы [ 6 ]

45 голосов
/ 19 февраля 2010
B.transaction do
  a.each(&:save!)
end

Это создаст транзакцию, которая перебирает каждый элемент массива и вызывает на нем element.save.

Вы можете прочитать о транзакциях ActiveRecord и о каждом методе в Rails и Ruby API.

26 голосов
/ 19 февраля 2010
a.each(&:save)

Это вызовет B#save для каждого элемента в массиве.

11 голосов
/ 05 апреля 2014

Так что я думаю, что нам нужно золотую середину к тому, чтобы Алексей поднял исключения и прервал транзакцию, а решение Джордана - на одну строчку. Могу ли я предложить:

B.transaction do
  success = a.map(&:save)
  unless success.all?
    errored = a.select{|b| !b.errors.blank?}
    # do something with the errored values
    raise ActiveRecord::Rollback
  end
end

Это даст вам немного обоих миров: транзакцию с откатом, знание о том, какие записи не удалось, и даже доступ к ошибкам проверки в них.

2 голосов
/ 31 марта 2015

Я знаю, что это старый вопрос, но я удивлен, что никто не подумал об этом:

B.transaction do
  broken = a.reject { |o| o.save }
  raise ActiveRecord::Rollback if broken.present?
end

if broken.present?
  # error message
end
0 голосов
/ 31 декабря 2017

Если вы ищете более эффективное решение, чем сохранение каждой строки в цикле, посмотрите мой ответ здесь Ruby on Rails - Импорт данных из CSV-файла

Япредлагая использовать камень activerecord-import там.

0 голосов
/ 14 мая 2013

Свертывание save в транзакции будет недостаточно: если проверка не пройдена, исключение не будет возникать и откат не будет инициирован.

Я могу предложить это:

B.transaction do
  a.each do |o|
    raise ActiveRecord::Rollback unless o.save
  end
end

Простое выполнение B.transaction do a.each(&:save!) end также не вариант, потому что блок транзакции не спасет никакое исключение, кроме ActiveRecord::Rollback, и приложение завершится сбоем при неудачной проверке.

Я не знаю, как потом проверить, сохранены ли записи.


Обновление . Поскольку кто-то понизил мой ответ, я предполагаю, что этот человек искал решение «вырезать и вставить» :), так что вот какой-то (уродливый :)) способ обработки значения сбой / успех:

save_failed = nil
B.transaction do
  a.each do |o|
    unless o.save
      save_failed = true
      raise ActiveRecord::Rollback
    end
  end
end
if save_failed
  # ...
else
  # ...
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...