4
3

More than 3 years have passed since last update.

Rails6 のちょい足しな新機能を試す111(uniqueness validation with belongs_to編)

Last updated at Posted at 2019-12-12

はじめに

Rails 6 に追加された新機能を試す第111段。 今回は、uniqueness validation with belongs_to 編です。
Rails 6 では、 belongs_to, has_many の関係があるModel で、 uniqueness 制約がある場合に save! メソッドで例外が発生しないバグが修正されました。
(なお、 後述しますが、 accepts_nested_attributes_for を組み合わせた場合のバグは修正されていません。)

Ruby 2.6.5, Rails 6.0.1 で確認しました。 (Rails 6.0.0 で修正されています。)

$ rails --version
Rails 6.0.1

今回は、Author モデルと Book モデルを作って、スクリプトで動作確認してみます。

Rails プロジェクトを作成する

$ rails new rails_sandbox
$ cd rails_sandbox

Author モデルを作る

$ bin/rails g model Author name

Book モデルを作る

Book モデルを作ります。 Book は、 titleisbnAuthor モデルへの参照を持つようにします。

$ bin/rails g model Book title isbn author:references

Author モデルを修正する

Author モデルに has_many を追加します。

app/models/author.rb
class Author < ApplicationRecord
  has_many :books, dependent: :destroy
end

Book モデルに validation を追加する

Book モデルに uniqueness の Validation を追加します。 uniqueness であることが重要です。

app/models/book.rb
class Book < ApplicationRecord
  belongs_to :author

  validates :isbn, uniqueness: true
end

スクリプトを作成する

Author と Book のデータをDBに保存するスクリプトを作成します。uniqueness 制約にひっかかるように、Book は2件作成します。

scripts/save.rb
author = Author.new(name: 'Dave Thomas')
author.books.build(title: 'Pragmatic Programmer', isbn: '123')
author.books.build(title: 'Agile Web Development with Rails 6', isbn: '123')
author.save!
p author.persisted?

DB マイグレーションを実行する

$ bin/rails db:create db:migrate

スクリプトを実行する

スクリプトを実行します。 ActiveRecord::RecordInvalid が発生します。

bin/rails runner scripts/save.rb
...
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/autosave_association.rb:419:in
`block in save_collection_association': Validation failed: Books is invalid (ActiveRecord::RecordInvalid)`

Rails 5では

エラーにならず、保存されてしまいます。

補足1

uniqueness 以外の validation では、Rails 5 でも Rails 6 でも例外が発生します。

補足2

Author モデルに、 accepts_nested_attributes_for :books を追加すると、例外が発生しなくなってしまいます。
(uniqueness 以外の validation では、例外が発生します。)

この事象については、既存の issue が見つかりました

app/models/author.rb
class Author < ApplicationRecord
  has_many :books, dependent: :destroy
  accepts_nested_attributes_for :books # https://github.com/rails/rails/issues/20676
end

試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try111_save_with_associated

参考情報

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3