假设数据库中有用户记录。我们决定在模型中添加验证。型号:
class User < ActiveRecord::Base
validates_format_of :name, with: /\A[^\d]*\z/, allow_blank: true
before_validation :delete_digits_from_name
def delete_digits_from_name
self.name = name.gsub!(/\d/, '')
end
end
控制台中的场景1:
User.create(name: 'Username 15')
User.last
=> #<User id: 14154, name: "Username"
没关系。但是有旧记录(在添加验证之前创建)和..场景2:
user = User.first
=> #<User id: 1, name: "Username 15"
user.save
=> true
user
=> #<User id: 1, name: "Username"
user.reload
=> #<User id: 1, name: "Username 15"
但为什么?为什么改变没有保存?
答案 0 :(得分:1)
gsub!
中的delete_digits_from_name
更改了名称,因此Rails认为name
与从DB加载的内容相同。它是同一个对象,即使你已经改变了它的价值。 Rails执行此操作以在没有数据更改时优化远程数据库更新,并且就地编辑会使其混淆。
切换到self.name = self.name.gsub(/\d/, '')
(没有!
)会分配一个新的String
,Rails会认为它是脏的,需要保存。
您还可以在name_will_change!
之后添加gsub!
告诉Rails属性需要保存。