ruby-on-rails - 升级到 Rails 5.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') }
在实际应用中,这是一个更复杂(也更有用)的术语,但这个简单且看似透明的术语同样会触发问题。
这里有很多类似的问题,但是,很多情况下关联确实是可选的,有些有非标准命名(我不认为我有,因为它以前工作过),我没有找到适合这种情况的归属模型是通过拥有一个完全处理的。
解决方案
在 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
推荐阅读
- arrays - 多维关联数组作为 Bash 脚本的配置文件?
- c++ - 通过函数挫折传递对象数组 c++
- php - 同一行上的多个 Update 语句
- angular - 角夹具 debugElement NULL
- unix - 未知的 ANSI 转义序列
- python-3.x - 如何在 tkinter 的顶层创建一个按钮
- python - 如何在不知道 colnames 的情况下从 pandas dfs 的特定列中删除前 8 个字符?
- ios - React Native ios不显示本地图像
- windows - OpenGL 窗口被其上的窗口擦除
- haskell - Aeson - 如何为 [String, Int] 创建新类型?