下記Modelを定義していて
ruby:
1class Maker < ApplicationRecord 2 has_many :notes, inverse_of: :maker 3 validates :name, presence: true, uniqueness: true 4end 5 6class Tag < ApplicationRecord 7 has_many :relations, class_name: 'TagRelation' 8 has_many :notes, through: :relations, source: :note 9 validates :name, presence: true, uniqueness: true 10end 11 12class TagRelation < ApplicationRecord 13 belongs_to :note 14 belongs_to :tag 15end 16 17class Note < ApplicationRecord 18 belongs_to :maker 19 accepts_nested_attributes_for :maker 20 21 has_many :relations, class_name: 'TagRelation' 22 has_many :tags, through: :relations, source: :tag 23 accepts_nested_attributes_for :tags 24 25 validates :name, presence: true, uniqueness: true 26end
下記データが登録されている時に
@Maker Table @Tag Table @Note Table id | name id | name id | name | maker_id ------------ ------------- ----------------------- 1 | maker1 1 | tag1 1 | note1 | 1 2 | maker2 2 | tag2 2 | note2 | 2 3 | tag3 @TagRelation Table id | note_id | tag_id ----------------------- 1 | 1 | 1 2 | 2 | 2 3 | 2 | 3
コントローラ上で(permit後の)下記パラメータでNoteにsaveしたい
ruby:
1params = { 2 name: 'note3', 3 maker_attributes: { 4 name: 'maker1', 5 }, 6 tags_attributes: [ 7 {name: 'tag1'}, 8 {name: 'tag4'}, 9 ], 10}
発生するバリデーションエラー
{ :"maker.name" => ["has already been taken"] :"tags[0].name" => ["has already been taken"] }
具体的に実行したいこと
Note.new(params).save
すると、上記のバリデーションエラーが発生します。
※ maker.name
も tags[x].name
も uniqueness: true
なので当然ですが。。。
実施したいのは、Maker
Tag
の両テーブルに登録済のデータ(name
カラム)があれば、
レコードを増やす事なく、勝手にNote
からリレーションを貼ってもらいたいのです。
動作イメージとしては、下記のようになります。
ruby
1note = Note.new(params) 2# バリデーションに成功する 3note.valid? # => true 4 5# Makerは登録済のレコードなので、対象のレコードを持ってくる 6note.maker # => Maker(id: 1, name: 'maker1') 7# tags[0]は登録済のレコードなので対象を持ってくるが、 tags[1]は新規 8note.tags # => [Tag(id: 1, name: 'tag1'), Tag(id: nil, name: 'tag4')] 9 10note.save # => true
現状、考えられるのは Note
の before_validation
で各モデルに find_or_initialize
するしかないかなと考えているのですが、
validates
や accepts_nested_attributes_for
に有効なオプションや、他に手法があれば教えていただきたいです!
よろしくおねがいします 🙇♂️
回答1件
あなたの回答
tips
プレビュー