假设我们有以下模型:
class A < AR
has_many :bs
accepts_nested_attributes_for :bs
end
class B < AR
belongs_to :a
end
我们以这种方式创建具有嵌套表单的新A对象:
class AsController < AC
def create
a = A.create(a_params)
end
...
def a_params
params.require(:a).permit(bs_attributes: [...])
end
end
这会产生类似b.a must be exists
的错误。这意味着b.a_id
不能为nil或a
必须先创建。
所有人都说,belongs_to关联的解决方案是optional: true
。
但是当关联非常严格且b.a
永远不会为零时会发生什么?
一个好的解决方案是optional: true
并在B上添加验证规则吗?
答案 0 :(得分:0)
我们经常想验证具有belongs_to
关系的内容是否设置了该列。
例如,如果我们有属于讨论的帖子,那么可能希望确保每个帖子都属于讨论并且其discussion_id
已设置。验证这是rails 5中的默认行为。
在Rails 4中,我们不得不添加类似的东西......
class Post
belongs_to :discussion
validates :discussion_id, presence: true
end
但是,在Rails 5中设置belongs_to :discussion, optional: true
将取消该验证。如果我想允许存在与讨论无关的帖子,我只会这样做。
如果您希望示例中的A has_many :bs
关系严格,请不要添加optional: true
,Rails 5将为您验证。
参考:http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
如果您想同时创建A和新B,那么您将要遵循http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html中列出的模式
params = { a: {
name: 'A new A!', bs_attributes: [
{ title: 'Something new b' },
{ title: 'Something else new b' }
]
}}
class AsController < AC
def create
a = A.create(a_params)
end
...
def a_params
params.require(:a).permit(:name, bs_attributes: [...])
end
end
a.bs.length # => 2
a.bs.first.title # => 'Something new b'
a.bs.second.title # => 'Something else new b'