升级到Rails 5.2:如何避免非可选关联的“optional:true”?

问题描述 投票:0回答:2

将我的应用程序从Rails 4.2.8移动到5.2.3后,插入失败了

Billings event must exist

应用程序接收一个带有一个事件和许多相关账单的级联哈希值,并且应该在一个事务中将其放入数据库中;这确实在以前工作过。

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

会避免这个错误,确实如此。但这对我来说似乎是非常错误的,因为在这个应用中,如果没有他们的活动,账单绝不可能存在,它不是可选的!但那么,什么是正确的解决方案?

进一步分析显示:所有验证都得到处理,但从未达到before_create()回调。在某些内部地方添加了“必须存在”错误,它不是来自我的代码。

此外,当创建一个只有上面显示的代码的模板时,我发现有问题的代码是范围-> { where('1 = 1') }

在实际应用中,这是一个更复杂(也更有用)的术语,但这个简单且看似透明的术语会引发问题。

这里有很多类似的问题,但是,很多人都有这种情况,其中关联确实是可选的,有些具有非标准的命名(我认为我没有,因为它之前有效),而且我没有找到这种情况所属模型通过一个完全处理。

ruby-on-rails ruby-on-rails-5
2个回答
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

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中提到的变化,现在导致验证错误。

© www.soinside.com 2019 - 2024. All rights reserved.