Rails создает связанные модели без сохранения?

Скажем, у нас есть модели Patient и PatientRawData (с ассоциацией author_to с Patient).

Можно ли создавать новые записи (без сохранения их в базе данных), связывать их и, наконец, сохранять в базе данных?

Что-то вроде этого:

patient = Patient.new(:name => 'John', :age => 34)
rawtext = PatientRawText.new(:rawtext => 'My name is..')
patient.rawtext = rawtext
patient.save!

Причина, по которой я хочу это сделать, заключается в том, что в моем реальном сценарии могут быть более сложные модели/ассоциации, и я бы предпочел не иметь частичных вещей в базе данных в случае исключения.

По этой причине я предпочитаю создавать любую сложную вещь, которую захочу, и в качестве последнего шага хранить все это в базе данных.


person Pithikos    schedule 20.04.2016    source источник


Ответы (4)


В Rails есть встроенная поддержка этого типа проблем с использованием вложенных атрибутов. http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

class Patient < ActiveRecord::Base
  has_one :patient_raw_text
  accepts_nested_attributes_for :patient_raw_text
end

params = { patient: { name: 'Jack', patient_raw_text_attributes: { rawtext: '...' } }}
member = Patient .create(params[:patient])
person dk87    schedule 20.04.2016

Вы можете использовать transaction, чтобы предотвратить создание множества записей. Он откатит все сохранения ActiveRecord, если где-либо в блоке возникнет исключение.

ActiveRecord::Base.transaction do
  patient = Patient.new(:name => 'John', :age => 34)
  rawtext = PatientRawText.create!(:rawtext => 'My name is..')
  patient.rawtext = rawtext
  patient.save! # <- if this fails
  raise "I don't want to be here"  # <- or if you manually raise an exeption 
end

Если возникнет исключение, даже после того, как объект PatientRawText был успешно создан (скажем, в случае сбоя patient.save!), создание PatientRawText будет отменено.

person SteveTurczyn    schedule 20.04.2016

Да, Rails позволяет нам это сделать:

patient = Patient.new(:name => 'John', :age => 34)
patient.build_patient_raw_text(:rawtext => 'My name is..')
patient.save!
person Hieu Pham    schedule 20.04.2016
comment
Этого метода не существует. - person YWCA Hello; 20.12.2018

Использование new для ссылки на экземпляр создаст несохраненную связанную модель, внешний ключ которой будет автоматически назначен при сохранении родителя. Другими словами...

patient = Patient.new(:name => 'John', :age => 34)
patient.patient_raw_text.new(:rawtext => 'My name is..')
patient.save!

Это то же самое, что вы предложили... просто сохраняет строку и назначение локальной переменной

person Hari Honor    schedule 21.01.2020