ruby-on-rails - 当我们在 ActiveRecord 中有一个字段的新范围时,我们可以立即更改验证代码吗?
问题描述
说,如果我们有
class SomeData < ActiveRecord::Base
validates :foo, inclusion: 33..99
现在,我们说,我们将范围缩小到66..99
,但是数据库中有很多值仍然在 33 和 65 之间,我们可以将上面的代码更改为
class SomeData < ActiveRecord::Base
validates :foo, inclusion: 66..99
立即地?如果数据只是读入系统有问题吗?(即使在早期版本的 Rails 中,例如 3.2?)
解决方案
更改验证实际上不会以任何方式直接影响数据库中的现有数据。验证仅#valid?
在模型上调用时运行。
当您调用时,这会隐式发生:
.create
和.create!
#save
和#save!
#update
和#update!
并且它会导致这些方法保释,以便首先发生回滚或不触发任何数据库查询。
我们可以立即更改验证吗?
是的。只有当您尝试更新现有记录时,验证才会真正生效。在这种情况下,以前有效的记录现在可能无效。除非将值更新到新的允许范围内,否则这将不允许更新。
处理遗留数据
如果您想让用户仍然根据新规则使用无效数据更新现有记录,则有一些技巧。
if:
和unless:
选项_
class SomeData < ActiveRecord::Base
validates :foo, inclusion: 33..99, if: :legacy_record?
validates :foo, inclusion: 66..99, unless: :legacy_record?
end
有几种方法可以:legacy_record?
像数据库中的布尔标志一样实现。请注意,这些不应与 ruby 关键字混淆。它们只是哈希选项。
自定义验证方法:
class SomeData < ActiveRecord::Base
validate :my_validation_method
def my_validation_method
rng = legacy_record? ? 33..99 : 66..99
errors.add(:foo, "out of range") unless rng.cover?(foo)
end
end
单表继承
class Thing < ActiveRecord::Base
validates :foo, inclusion: 66..99
end
class LegacyThing < ActiveRecord::Base
self.table_name = "things"
validates :foo, inclusion: 33..99
end
在此示例中,您将添加一个things.type
varchar 列并使用things.type = "LegacyThing"
. 这不是真正的 STI - 它只是使用 ActiveRecord 中内置的机制。
推荐阅读
- python - 字典键是数据框中的列,值是列的特征类型
- java - 如何仅使用 if else 语句按字母顺序排列任意三个变量值?
- angular - 如何在不取消原始流的情况下将值传递给另一个可观察的创建者?
- algorithm - 对于已经排序的数据,哪种排序方法最快?
- c# - 发生异常后如何修复httplistener
- javascript - Javascript 事件/序列问题:为什么这个事件会触发?
- javascript - Javascript:从 x-www-form-urlencoded 请求中获取参数值
- swift - SKPhysicsContactDelegate,碰撞无法正常工作
- python - 如何从某个日期获取某个单词的TF-IDF?
- java - java内部类中静态成员的使用