Во-первых, если вы хотите, чтобы дети сохранялись без родительского идентификатора, тогда нет смысла делать это
p = Parent.new(params[:data])
for type in %w[bookmark_id history_id window_id]
if !params[type].blank?
p.children << Child.find(params[type])
end
end
вся цель
p.children << some_child
- прикрепить родительский идентификатор к дочернему объекту, который вы здесь не делаете, потому что родительский объект еще не существует.
Другое дело, если вы просто хотите убедиться, что у родительского объекта есть дочерний объект, и если вы создаете дочерний и родительский объект вместе, вы можете использовать блок транзакции вокруг создания родительского и дочернего объектов, который будет гарантировать, что родитель имеет ребенок, как
transaction do
p = create_parent
p.children << child1
p.children << child2
end
Таким образом, в рамках транзакции, если на каком-либо этапе код завершится неудачей, он откатит всю транзакцию БД, т. Е. У вас будет один родитель с двумя дочерними элементами или ничего, если вы ищете конечное состояние.
РЕДАКТИРОВАТЬ: Поскольку вы не можете создать родителя, если у него нет 2 детей, в этом случае, вместо
p = Parent.new(params[:data])
for type in %w[bookmark_id history_id window_id]
if !params[type].blank?
p.children << Child.find(params[type])
end
end
сделать
children = []
for type in %w[bookmark_id history_id window_id]
if !params[type].blank?
children << Child.find(params[type])
end
end
if children.size >= 2
p = Parent.create!(params[:data])
children.each {|child| p.children << child}
end
Имеет ли это смысл