Ruby on rails Rails 5在具有不同字段的多个模型中重复使用前验证代码
我有一个Rails 5应用程序,用户可以在不同的字段和不同的模型中输入货币值 因为我只提供一种语言环境,所以我希望用户能够同时使用这两种语言环境输入小数。和,十进制分隔符,忽略任何千位分隔符 例如,我的用户可能会输入:Ruby on rails Rails 5在具有不同字段的多个模型中重复使用前验证代码,ruby-on-rails,ruby-on-rails-5,Ruby On Rails,Ruby On Rails 5,我有一个Rails 5应用程序,用户可以在不同的字段和不同的模型中输入货币值 因为我只提供一种语言环境,所以我希望用户能够同时使用这两种语言环境输入小数。和,十进制分隔符,忽略任何千位分隔符 例如,我的用户可能会输入:1023.45或1023,45,但决不会输入1.023,45 适合我的用例的简单解决方案:在表示货币的特定十进制字段上,使用gsub(',',')将,替换为 放置此代码的最佳位置是什么?有多个具有不同名称字段的模型需要使用此代码 最好,我会使用像自定义验证器这样的东西,我创建了一次
1023.45
或1023,45
,但决不会输入1.023,45
适合我的用例的简单解决方案:在表示货币的特定十进制字段上,使用gsub(',',')
将,
替换为
放置此代码的最佳位置是什么?有多个具有不同名称字段的模型需要使用此代码
最好,我会使用像自定义验证器这样的东西,我创建了一次,并简单地引用了所有模型中带有适当字段的一行。非常类似于此示例中的自定义验证器,该验证器检查输入的值是否为正值:
class PositiveValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value and BigDecimal.new(value).negative?
record.errors[attribute] << 'is negative'
end
end
end
然而,这当然适用于验证,验证不应该修改数据。我试着关注这个问题,但从我看到的例子中,我应该已经知道哪些领域正在被改造
我真的需要在每个模型中写下如下内容:
before_validation lambda {self.total.gsub!(',', '.') if self.total}
还是有一个更优雅的类似Rails的解决方案
编辑:再次注意,每个型号的字段名“total”可能不同您可以从Rails 4.2开始使用自定义类型转换
class LocalFloat < ActiveRecord::Type::Float
def cast_value(value)
value = value.gsub(',', '.') if value.is_a? String
super(value)
end
end
class Order < ApplicationRecord
attribute :total, LocalFloat.new
end
o = Order.new total: '5,5'
o.total # => 5.5
class LocalFloat5.5
您可以从Rails 4.2开始使用自定义类型转换
class LocalFloat < ActiveRecord::Type::Float
def cast_value(value)
value = value.gsub(',', '.') if value.is_a? String
super(value)
end
end
class Order < ApplicationRecord
attribute :total, LocalFloat.new
end
o = Order.new total: '5,5'
o.total # => 5.5
class LocalFloat5.5
很好的建议。这也适用于MySQL支持的十进制类型?或者我应该使用与Float不同的类型?考虑到存储货币的准确性问题,我稍微改变了我的答案@ChrisDekker,因为当值可以从数据库中获取时,您是对的,所以值也可以是浮点。请参阅超类的实现,这是将Mysql decimal转换为ruby floatNice的驱动程序职责。这也适用于MySQL支持的十进制类型?或者我应该使用与Float不同的类型?考虑到存储货币的准确性问题,我稍微改变了我的答案@ChrisDekker,因为当值可以从数据库中获取时,您是对的,所以值也可以是浮点。请参阅超类的实现,这是将Mysql decimal转换为ruby float的驱动程序职责