Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails 5在具有不同字段的多个模型中重复使用前验证代码_Ruby On Rails_Ruby On Rails 5 - Fatal编程技术网

Ruby on rails 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(',',')将,替换为 放置此代码的最佳位置是什么?有多个具有不同名称字段的模型需要使用此代码 最好,我会使用像自定义验证器这样的东西,我创建了一次

我有一个Rails 5应用程序,用户可以在不同的字段和不同的模型中输入货币值

因为我只提供一种语言环境,所以我希望用户能够同时使用这两种语言环境输入小数。和,十进制分隔符,忽略任何千位分隔符

例如,我的用户可能会输入:
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的驱动程序职责