我正在尝试从模型中的字段中删除逗号。我希望用户键入一个数字,即 10,000,该数字应作为 10000 存储在数据库中。我希望我可以进行一些模型端规范化以删除逗号。我不想依赖视图或控制器来正确格式化我的数据。
我试过:
before_validation :normalize
def normalize
self['thenumber'] = self['thenumber'].to_s.gsub(',','')
end
没有工作。
http://github.com/mdeering/attribute_normalizer 看起来是解决这个常见问题的有希望的解决方案。以下是主页上的一些示例:
# By default it will strip leading and trailing whitespace
# and set to nil if blank.
normalize_attributes :author, :publisher
# Using one of our predefined normalizers.
normalize_attribute :price, :with => :currency
# You can also define your normalization block inline.
normalize_attribute :title do |value|
value.is_a?(String) ? value.titleize.strip : value
end
所以在你的情况下你可以这样做:
normalize_attribute :title do |value|
value.to_s.gsub(',', '')
end
我认为你做得对。这个测试通过:
test "should remove commas from thenumber" do
f = Foo.new(:thenumber => "10,000")
f.save
f = Foo.find(f.id)
assert f.thenumber == "10000"
end
我用了你的代码。
class Foo < ActiveRecord::Base
before_validation :normalize
def normalize
self['thenumber'] = self['thenumber'].to_s.gsub(',','')
end
end
现在,我的模式被设置为数字是一个字符串,而不是一个整数。
Started
.
Finished in 0.049666 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
如果您想将其作为整数存储在数据库中,那么您肯定需要覆盖设置器:
def thenumber=(value)
self['thenumber'] = value.to_s.gsub(',','').to_i
end
如果你按照自己的方式使用整数列,它会被 AR 截断....
>> f.thenumber = "10,000"
=> "10,000"
>> f.thenumber
=> 10
对于 Ruby 和整数这是一个鲜为人知的事情......它通过截断任何不再是整数的东西来自动转换。
irb(main):004:0> i = "155-brian-hogan".to_i
=> 155
对于像这样的东西可以很酷
/users/155-brian-hogan
@user = User.find_by_id(params[:id])
但是对于你正在做的事情来说并不是那么酷。
所以要么将 col 更改为字符串并使用过滤器,要么更改 setter :)
祝你好运!
这样做的问题是,有一段时间,非规范化的东西会存在于对象中;如果你有在东西被规范化之前处理属性的代码,那将是一个问题。
你可以定义一个setter:
def thenumber=(value)
# normalise stuff here, call write_attribute
end
不幸的是,我认为很多 Rails 表单的东西直接写了属性,这是我不倾向于使用它的原因之一。
或者您可以在传递之前在控制器中规范化参数。
ruby 是否允许您在 .和 [''] ? 我不知道,我稍后再试,但我认为你应该使用 .
self.thenumber = self.thenumber.to_s.gsub(',','')
您应该从 before_validation 方法返回 true,否则如果分配给 self['thenumber'] 的表达式最终为 nil 或 false,根据 Rails 文档,数据将不会被保存:
如果 before_* 回调返回 false, 所有后来的回调和 相关动作被取消。
表面上,您正在尝试在此处进行规范化,然后使用 Rails 验证检查规范化的结果,这将决定 nil/false/blank 是否可以。
before_validation :normalize
def normalize
self['thenumber'] = self['thenumber'].to_s.gsub(',','')
return true
end
ActiveRecord::Base::normalizes
class User < ApplicationRecord
normalizes :email, with: ->(email) { email.strip.downcase }
end
它在验证之前调用
这是安全的,因为没有(但可以选择)适用于
nil
它适用于持久性和查找器方法
User.create(email: " [email protected] \n")
# => #<User email: "[email protected]">
User.find_by(email: "\[email protected] \t")
# => #<User email: "[email protected]">
如果您也需要对
nil
值应用归一化,请使用 apply_to_nil: true
选项
class User < ApplicationRecord
normalizes :email, with: ->(email) { email&.strip&.downcase || "[email protected]" },
end
(
"[email protected]"
电子邮件将在nil
情况下分配)
如果您有遗留的非规范化记录,您可以使用
ActiveRecord::Base#normalize_attribute
对其进行规范化
user.email # => "[email protected] "
user.normalize_attribute(:email)
user.email # => "[email protected]"
user.save