我正在实施一个以模型为特色的Rails应用程序:
class Document < ActiveRecord::Base
has_many :categorisations
has_many :categories, through: :categorisations
accepts_nested_attributes_for :categorisations
end
class Category < ActiveRecord::Base
has_many :categorisations
has_many :documents, through: :categorisations
end
class Categorisation < ActiveRecord::Base
belongs_to :document
belongs_to :category
validates_presence_of :document
validates_presence_of :category
validates_uniqueness_of :category, scope: :document
end
accepts_nested_attributes_for
中Document
的存在允许在文档创建时将类别附加到文档。这通常可以正常工作,除了通过嵌套属性传入无效的category-id(不存在类别的类别)的情况。在这种情况下:
document = Document.new({
# .. attributes ..,
categorisations_attributes: {
'0' => {
# .. more attributes ..,
category_id: some_invalid_id
}
}
})
# Ouch, this results in 'NoMethodError: undefined method `attributes' for nil:NilClass'
document.valid?
不出所料,我在尝试document.save
时遇到了同样的错误。此时,看起来我可以通过检查document.categorisations.first.category.nil?
之类的内容来检测并抢占这一点。然而,这似乎不太理想,因为它不符合通常的Rails验证实践,我不能遵循document.save
检测无效性的共同模式(通过false
返回值)。
我是否缺少一些Rails最佳实践/更好的方法来布置我的模型以减轻这种情况?
[修改:这里是document.valid?
]
activerecord-4.0.2/lib/active_record/validations/uniqueness.rb:56:in `build_relation'
activerecord-4.0.2/lib/active_record/validations/uniqueness.rb:22:in `validate_each'
activemodel-4.0.2/lib/active_model/validator.rb:153:in `block in validate'
activemodel-4.0.2/lib/active_model/validator.rb:150:in `each'
activemodel-4.0.2/lib/active_model/validator.rb:150:in `validate'
activesupport-4.0.2/lib/active_support/callbacks.rb:283:in `_callback_before_29'
activesupport-4.0.2/lib/active_support/callbacks.rb:407:in `_run__1039810079386051889__validate__callbacks'
activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
activemodel-4.0.2/lib/active_model/validations.rb:373:in `run_validations!'
activemodel-4.0.2/lib/active_model/validations/callbacks.rb:106:in `block in run_validations!'
activesupport-4.0.2/lib/active_support/callbacks.rb:373:in `_run__1039810079386051889__validation__callbacks'
activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
activemodel-4.0.2/lib/active_model/validations/callbacks.rb:106:in `run_validations!'
activemodel-4.0.2/lib/active_model/validations.rb:314:in `valid?'
activerecord-4.0.2/lib/active_record/validations.rb:70:in `valid?'
activerecord-4.0.2/lib/active_record/autosave_association.rb:304:in `association_valid?'
activerecord-4.0.2/lib/active_record/autosave_association.rb:293:in `block in validate_collection_association'
activerecord-4.0.2/lib/active_record/autosave_association.rb:293:in `each'
activerecord-4.0.2/lib/active_record/autosave_association.rb:293:in `validate_collection_association'
activerecord-4.0.2/lib/active_record/autosave_association.rb:207:in `block in add_autosave_association_callbacks'
activerecord-4.0.2/lib/active_record/autosave_association.rb:153:in `instance_eval'
activerecord-4.0.2/lib/active_record/autosave_association.rb:153:in `block in define_non_cyclic_method'
activesupport-4.0.2/lib/active_support/callbacks.rb:397:in `_run__779968926416857275__validate__callbacks'
activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
activemodel-4.0.2/lib/active_model/validations.rb:373:in `run_validations!'
activemodel-4.0.2/lib/active_model/validations/callbacks.rb:106:in `block in run_validations!'
activesupport-4.0.2/lib/active_support/callbacks.rb:383:in `_run__779968926416857275__validation__callbacks'
activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
activemodel-4.0.2/lib/active_model/validations/callbacks.rb:106:in `run_validations!'
activemodel-4.0.2/lib/active_model/validations.rb:314:in `valid?'
activerecord-4.0.2/lib/active_record/validations.rb:70:in `valid?'
[编辑2 :]
我更新了问题,以在validates_uniqueness_of :category, scope: :document
模型中包含Categorisation
约束。 删除它可以消除Nil错误,从而导致更加理智,验证错误和分类类别不能为空白&#39;代替。但是,验证到位后问题仍然存在。
答案 0 :(得分:0)
我不确定,如果您尝试使用association
而不仅仅是association_id
,验证的工作原理如何,但您可以尝试使用validates_each
代替validates_presence_of
Categorisation
模型中的验证:
validates_each :category_id do |record, attr, value|
unless Category.exists?(id: value)
record.errors.add(attr, "does not exist")
end
end