1

A report_templatehas_manyreport_template_columns,其各自具有 nameindex屬性。如何防止使用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

+0

不要範圍適用於ASSOCATION。它的反模式與'defual_scope'相同。看起來似乎很方便,但如果您不想稍後應用範圍,會使事情變得非常困難。 http://weblog.jamisbuck.org/2015/9/19/default-scopes-anti-pattern.html – max

回答

2

我相信你需要將: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 the belongs_to as optional: false , but the cleanest way is to specify the inverse_of: on the has_many. That is why we write: has_many :tasks, inverse_of: :project

+0

它應該是'belongs_to:report_template,inverse_of :: report_template_columns'(複數)?與單數我得到'ActiveRecord :: InverseOfAssociationNotFoundError:無法找到report_template(:report_template_column in ReportTemplate)',反函數',用複數我得到同樣的錯誤在問題中。 – tommarshall

+0

糟糕,我想我錯誤地寫了我的答案。 'inverse_of'應該放在'has_many'這一邊。 – ardavis

+0

這是工作。儘管我不需要改變'create!'調用,以便'inverse_of'解決問題。如果您從答案中刪除該部分,我會將其作爲接受的答案。感謝您的幫助:) – tommarshall