如何防止使用ActiveRecord中的作用域has_many嵌套创建失败?
A report_template
has_many
report_template_columns
,其各自具有 name
和index
属性。如何防止使用ActiveRecord中的作用域has_many嵌套创建失败?
class ReportTemplateColumn < ApplicationRecord
belongs_to :report_template
validates :name, presence: true
end
class ReportTemplate < ApplicationRecord
has_many :report_template_columns, -> { order(index: :asc) }, dependent: :destroy
accepts_nested_attributes_for :report_template_columns, allow_destroy: true
end
report_template_columns
需要按索引列排序。我申请这与在has_many
相关联的范围,但这样做会导致以下错误:
> ReportTemplate.create!(report_template_columns: [ReportTemplateColumn.new(name: 'id', index: '1')])
ActiveRecord::RecordInvalid: Validation failed: Report template columns report template must exist
from /usr/local/bundle/gems/activerecord-5.1.4/lib/active_record/validations.rb:78:in `raise_validation_error'
如果我删除同一命令成功的范围。
如果我将order
范围替换为where
范围,该命令以相同的方式失败,所以它似乎是存在范围而不是使用order
具体。
如何在不破坏嵌套创建的情况下将范围应用于has_many
?
我相信你需要将:inverse_of
选项添加到has_many
关联中。
class ReportTemplate < ApplicationRecord
has_many :report_template_columns, -> { order(index: :asc) },
dependent: :destroy, inverse_of: :report_template
end
的API指出:inverse_of
:
Specifies the name of the belongs_to association on the associated object that is the inverse of this
has_many
association. Does not work in combination with:through
or:as
options. See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
我也喜欢怎么cocoon gem话他们之所以使用它:
Rails 5 Note: since rails 5 a
belongs_to
relation is by default required. While this absolutely makes sense, this also means associations have to be declared more explicitly. When saving nested items, theoretically the parent is not yet saved on validation, so rails needs help to know the link between relations. There are two ways: either declare thebelongs_to
asoptional: false
, but the cleanest way is to specify theinverse_of:
on the has_many. That is why we write:has_many :tasks, inverse_of: :project
它应该是'belongs_to:report_template,inverse_of :: report_template_columns'(复数)?与单数我得到'ActiveRecord :: InverseOfAssociationNotFoundError:无法找到report_template(:report_template_column in ReportTemplate)',反函数',用复数我得到同样的错误在问题中。 – tommarshall
糟糕,我想我错误地写了我的答案。 'inverse_of'应该放在'has_many'这一边。 – ardavis
这是工作。尽管我不需要改变'create!'调用,以便'inverse_of'解决问题。如果您从答案中删除该部分,我会将其作为接受的答案。感谢您的帮助:) – tommarshall
不要范围适用于ASSOCATION。它的反模式与'defual_scope'相同。看起来似乎很方便,但如果您不想稍后应用范围,会使事情变得非常困难。 http://weblog.jamisbuck.org/2015/9/19/default-scopes-anti-pattern.html – max