我试图创建一个使用的Rails 5的属性API来接受本地化的用户输入自定义小数类型。它看起来象下面这样:
class Decimal < ActiveRecord::Type::Decimal
def cast(value)
return unless value
cast_value(value.is_a?(String) ? parse_from_string(value) : value)
end
def changed_in_place?(raw_old_value, new_value)
raw_old_value != serialize(new_value)
end
def parse_from_string(value)
delimiter = I18n.t('number.format.delimiter')
separator = I18n.t('number.format.separator')
value.gsub(delimiter, '_').gsub(separator, '.')
end
end
我也有一个自定义表单生成器显示一个格式化的值给用户。当提交表单创建资源(模型实体),它工作正常。然而,提交表单更新资源时,在validates_numericality_of
验证,标志着我的自定义属性为无效(not_a_number)。在主动模式的源代码经过一番研究,我达到了这段代码在NumericalityValidator
。
但我不明白我可以改变,使这个作品。有任何想法吗?!
验证程序使用一个名为raw_value
变量。它试图从你的对象,它的原始值,检查线路35至38。
我想你可以使用你的属性的名称以“_before_type_cast”返回一个数值,验证可以使用你的模型中定义的方法。
如果你的属性被调用,可以说,amount
,你可以这样做:
def amount_before_type_cast
amount.to_number
end
然后,你必须确定你的自定义类型的方法把它变成一个数字,也许是这样的:
def to_number
value.gsub(/\D/,'').to_i #remove all non-digit and turn it into an integer
end
我做了改变我的自定义小数类型的工作。
class Decimal < ActiveRecord::Type::Decimal
def cast(value)
return unless value
if value.is_a?(String)
if numeric_string?(value)
value = value.to_s.to_numeric
else
return value
end
end
cast_value(value)
end
def value_constructed_by_mass_assignment?(value)
if value.is_a?(String)
numeric_string?(value)
else
super
end
end
def numeric_string?(value)
number = value.to_s.gsub(/[.,]/, '.' => '', ',' => '.')
/\A[-+]?\d+/.match?(number)
end
end