rails中belongs_to中model验证问题
问题描述:
在使用rails5开发时,追加了一个table并配置好belongs_to关系,随后在创建页面,提示table_id 不能为空。检查之后并没有验证,排查之后发现原来是rails5中,默认设置了这一验证,可同过optional属性设置掉。
参考链接:https://www.bigbinary.com/blog/rails-5-makes-belong-to-association-required-by-default
只为自己做笔记,方便查阅复习。
In Rails 5, whenever we define a belongs_to association, it is required to have the associated record present by default after this change.
It triggers validation error if associated record is not present.
class User < ApplicationRecord end class Post < ApplicationRecord belongs_to :user end post = Post.create(title: 'Hi') => <Post id: nil, title: "Hi", user_id: nil, created_at: nil, updated_at: nil> post.errors.full_messages.to_sentence => "User must exist"
As we can see, we can't create any post record without having an associated user record.
How to achieve this behavior before Rails 5
In Rails 4.x world To add validation on belongs_to association, we need to add option required: true .
class User < ApplicationRecord end class Post < ApplicationRecord belongs_to :user, required: true end post = Post.create(title: 'Hi') => <Post id: nil, title: "Hi", user_id: nil, created_at: nil, updated_at: nil> post.errors.full_messages.to_sentence => "User must exist"
By default, required option is set to false.
Opting out of this default behavior in Rails 5
We can pass optional: true to the belongs_to association which would remove this validation check.
class Post < ApplicationRecord belongs_to :user, optional: true end post = Post.create(title: 'Hi') => <Post id: 2, title: "Hi", user_id: nil>
But, what if we do not need this behavior anywhere in our entire application and not just a single model?
Opting out of this default behavior for the entire application
New Rails 5 application comes with an initializer named new_framework_defaults.rb.
When upgrading from older version of Rails to Rails 5, we can add this initializer by running bin/rails app:update task.
This initializer has config named Rails.application.config.active_record.belongs_to_required_by_default = true
For new Rails 5 application the value is set to true but for old applications, this is set to false by default.
We can turn off this behavior by keeping the value to false.
Rails.application.config.active_record.belongs_to_required_by_default = false class Post < ApplicationRecord belongs_to :user end post = Post.create(title: 'Hi') => <Post id: 3, title: "Hi", user_id: nil, created_at: "2016-02-11 12:36:05", updated_at: "2016-02-11 12:36:05">