質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

1回答

1650閲覧

【Rails】リレーションのあるマスターテーブルを同時に追加したい

aa37971

総合スコア24

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

0クリップ

投稿2019/04/04 00:34

編集2019/04/10 01:22

下記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.nametags[x].nameuniqueness: 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

現状、考えられるのは Notebefore_validation で各モデルに find_or_initialize するしかないかなと考えているのですが、
validatesaccepts_nested_attributes_for に有効なオプションや、他に手法があれば教えていただきたいです!
よろしくおねがいします 🙇‍♂️

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ykp_yk

2019/04/05 02:14

申し訳ありませんが何をしたいのかがわかりませんでした。 tag0-2やnote0-1はどのような条件で与えられるのでしょうか?配列ですか? Note.new(tag0,tag1)した後にNote.new(tag1,tag2)をしたいのであればそのように順番に処理を書けば良いんじゃないでしょうか(スマートな実装かどうかは置いておきます。)
aa37971

2019/04/05 02:31

`Note` の引数はコントローラ上でparamsから取得すると考えてください。 ※ そのため `maker_attributes `, `tags_attributes` を宣言しています。 事前にユーザー0の作ったNoteは ``` tag0, tag1 ``` を持っていて、 Tagには ``` id | name 1 | tag0 2 | tag1 ``` が登録されています。 ユーザー1のノートには ``` tag1, tag2 ``` を登録したいので `tags_attributes` で渡しているのですが、 `uniqueness` 制約に引っかかりますよね? これをどうにかしたいのです。
ykp_yk

2019/04/05 02:38

申し訳ないのですがやっぱり何をしたいのか理解できませんんでした。 validates :name, presence: true, uniqueness: true ユニーク制約というのはこのことですか?これを外せば良いんじゃないでしょうか。 Noteモデルのnameはユニークじゃなく、同じものが入る可能性があるということだと思いますが、ご質問全体に主語と詳しいエラーが無いのでよくわからないです。
aa37971

2019/04/05 02:44

> Noteモデルのnameはユニークじゃなく同じものが入る可能性があるということだと思いますが Note/Maker/Tag の name はすべてユニークにしたいです。 質問のparamsを改めて見ていただきたいです。 Noteに入れる name は別値です。 Tagに限って話をしますが、 初回のsaveでは tag0, tag1 をsaveします。 → これはtags_attributesなので当然できますよね? 次は tag1, tag2 の saveをしたいのですが、 tag1もsaveしようとするので、ユニーク制約にかかりますよね? もちろん、NoteとTagを別々にsaveすればいいのですが、それはaccepts_nested_attributes_forを使うメリットがないですし、コントローラも複雑化してしまうのでRailsに機能があるはずと思って質問しています。
ykp_yk

2019/04/05 03:37

> 質問のparamsを改めて見ていただきたいです。 このparamsとご質問を見ただけでエラーもやりたいことも書いていないあなたのやりたいことが分かる人ってそうそういないと思いますよ。 before_validationでユニークかどうかのチェックをやると良いです。 https://apidock.com/rails/ActiveRecord/Callbacks/before_validation
guest

回答1

0

ベストアンサー

accepts_nested_attributes_for を使って一気に作るのを諦めるという方法はいかがでしょう

note = Note.new(params) もしくは create のあと

note.maker= Maker.find_or_initialize_by
もしくは Maker.find_or_create_by

投稿2019/07/03 04:17

winterboum

総合スコア23329

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問