###前提・実現したいこと
以下のような構成のmodelがあるとしたときに、これらを一度のsaveで同時作成したいです。
user.rb
ruby
1# id 2has_many :user_jobs, inverse_of: :user 3has_many :contacts 4accepts_nested_attributes_for :user_jobs 5accepts_nested_attributes_for :contacts
user_job.rb
ruby
1# id, user_id 2belongs_to :user 3has_one :contact 4accepts_nested_attributes_for :user 5accepts_nested_attributes_for :contact 6validates :user, presence: true # inverse_ofを利用しているのでpresenceは:user_idではなく:user
contact.rb
ruby
1# id, user_id, user_job_id, 2belongs_to :user 3belongs_to :user_job 4accepts_nested_attributes_for :user 5accepts_nested_attributes_for :user_job 6validates :user_id, :user_job_id, presence: true
###発生している問題・エラーメッセージ
最後のアソシエーションの外部キーがセットされないようで、バリデートに引っかかってしまいます。
ruby
1# 試行1 2u = User.create(contacts_attributes: [{ user_job_attributes: {} }]) 3# u.errors => contacts.user_jobs.user_id を入力してください 4 5# 試行2 6c = Contact.create(user_attributes: { user_jobs_attributes: [{}] }) 7# c.errors => user.user_jobs.user_id を入力してください
いろいろ試したのですが、paramsを整形、もしくは*_attributesやbuildなどを使用して(ApplicationRecord.transactionを書かずにRailsっぽく)、
トランザクション内でsaveする方法はないのでしょうか?
###2016-12-12追記
-
inverse_ofが必要そうなので、modelを若干修正しました。
-
目的としましては以下のようなコードで実現できますが、こちらを「Railsの機能でもっとイイカンジに書けるのではないか」、と考えています。
ruby
1 def create 2 # user_params => { user_jobs_attributes: [{}] } 3 # viewでは@user.errorsをeachで回したいので@userのスコープをtransactionの外に 4 @user = User.new(user_params) 5 ApplicationRecord.transaction do 6 @user = User.save 7 @user.user_jobs.each do |user_job| 8 @user.update(user_jobs_attributes: [id: user_job.id, contact_attributes: { user_id: @user.id }]) 9 end 10 raise if @user.errors.present? # validationエラーがあれば例外を発生させ、rescueで拾う 11 redirect_to @user, notice: '更新に成功しました' 12 rescue 13 render :new 14 end 15 end
###補足情報(言語/FW/ツール等のバージョンなど)
Rails 5.0.0.1
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/12/12 06:44 編集
2016/12/12 08:31
2016/12/12 08:34
2016/12/12 08:43
2016/12/12 09:22
2016/12/12 11:31
2016/12/14 04:01