将我的应用程序从Rails 4.2.8移动到5.2.3后,插入失败并
Billings event must exist
应用程序接收到一个具有一个事件和许多相关账单的级联哈希,应将其以 one single transaction 的形式放入数据库中;以前确实如此。
class Event < ActiveRecord::Base
has_many :billings, -> { where('1 = 1') }, dependent: :destroy
accepts_nested_attributes_for :billings
validates_associated :billings
end
class Billing < ActiveRecord::Base
belongs_to :event
validates_presence_of :event_id, on: :update
end
class EventsController < ApplicationController
def kC
@event = Event.new(event_params)
if @event.save
[doesn't get here anymore]
end
end
end
没有计费控制器,它们仅通过关联的事件存在。
快速分析发现文档中提到
belongs_to :event, optional: true
将避免此错误,的确如此。但这对我来说似乎很不对劲,因为在此应用程序中,账单必须从不不存在,它是 NOT 可选! 但是,正确的解决方案是什么?
进一步的分析表明:所有验证都得到处理,但是从未达到过before_create()回调。 “必须存在”错误是在内部某个地方添加的,它不是来自我的代码。
此外,当仅使用上述代码创建模板时,我发现问题代码为范围-> { where('1 = 1') }
在实际应用中,这是一个更复杂(也更有用)的术语,但这个简单且看似透明的术语会同样触发问题。
这里有很多类似的问题,但是很多情况下,这种关联确实是可选的,有些具有非标准的命名(我不认为我有像以前那样的名称),但是我没有找到一个在这种情况下,所属模型通过拥有模型得到了完全处理。
答案 0 :(得分:1)
在Rails 5中,每当我们定义一个belongs_to
关联时,默认情况下都需要显示关联的记录。如果相关记录不存在,则会触发验证错误。要删除此默认行为,我们可以使用Rails 5随附的 new_framework_defaults.rb 初始化程序。
(有关更多信息,您可以检查此https://github.com/rails/rails/pull/18937)
从较旧版本的Rails升级到Rails 5时,我们可以通过运行bin/rails app:update
任务来添加此初始化程序。
此新添加的初始化程序具有以下配置标志,用于处理默认行为
Rails.application.config.active_record.belongs_to_required_by_default = true
我们可以通过将其值设置为 false
来关闭此行为Rails.application.config.active_record.belongs_to_required_by_default = false
答案 1 :(得分:0)
我找到了正确的解决方案:
class Event < ActiveRecord::Base
has_many :billings, -> { where('1 = 1') }, dependent: :destroy, inverse_of: :event
accepts_nested_attributes_for :billings
validates_associated :billings
end
以这种方式添加此inverse_of:
选项可以解决该问题。
初步的根本原因分析:
inverse_of
选项的(稀疏)文档的确建议将其添加到belongs_to
功能中;它并没有提及将其添加到has_many
中(这也不妨碍)。在这种情况下,将其添加到belongs_to
不会有所改善,文档中的用例也不适用于此。
尽管如此,文档中提到了关联的“自动猜测”,并且在AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS
中声明的某些情况下,这种自动猜测将被省略。
在源中搜索该术语会导致使用私有方法can_find_inverse_of_automatically?()
,很明显,作用域也会导致自动猜测被忽略。
看来,以某种方式对累积插入进行解散需要查明“ inverse_of”(是自动还是已编码),否则,由于提到的更改,它会认为拥有关系不存在-与后者的所有权关系不存在在Rails 5中,现在会导致验证错误。