Ruby on rails 处理混合数—;在模型中?
我有一个包含大量字段的表单,这些字段以小数形式存储在数据库中 但是,我希望用户能够输入分数,特别是混合数(例如38 1/2) 为将混合数转换为分数提供了一个很好的解决方案,我对其进行了修改,并将其放入模型中的函数中:Ruby on rails 处理混合数—;在模型中?,ruby-on-rails,ruby,Ruby On Rails,Ruby,我有一个包含大量字段的表单,这些字段以小数形式存储在数据库中 但是,我希望用户能够输入分数,特别是混合数(例如38 1/2) 为将混合数转换为分数提供了一个很好的解决方案,我对其进行了修改,并将其放入模型中的函数中: def to_dec self.chest = self.chest.split.map { |r| Rational(r) }.inject(:+).to_f end 我已经尝试过在保存之前用validate:to_dec和调用它。然而,这两种方法都不起作用 我知道为什么,
def to_dec
self.chest = self.chest.split.map { |r| Rational(r) }.inject(:+).to_f
end
我已经尝试过在保存之前用validate:to_dec
和调用它。然而,这两种方法都不起作用
我知道为什么,但不知道如何修复它
通过使用put self.chest
我能够在我有机会调整之前判断出该值正在转换为一个数字。在我的表单中输入'10 1/2'并保存,放入self.cost
将为我提供10.0,即使该函数只是:
def to_dec
puts self.chest
end
另外,将'38 1/2'。split.map{r | Rational(r)}.inject(:+).to|d
给我38.5,所以我知道问题不在转换中
我已经将视图输入类型从数字改为字符串,但我的模型中似乎仍然有一个数字
我卡住了
另外,其他一些字段也需要支持混合数——我想以某种方式将其抽象出来,这样就不需要为每个值编写不同的函数 原因是ActiveRecord在定义模型属性时会查看数据库模式。这就是所有属性在模型类上的显示方式,而无需像在普通的旧Ruby对象上一样,使用attr\u访问器:cost
(或def-cost
和def-cost=
)手动定义它们
执行此操作时,ActiveRecord还会查看列类型,并在分配属性时应用类型转换。因此,因为您的cost
列是十进制的,所以它将您提供给它的任何字符串转换为浮点。在这样做时,它将获取可以转换的字符串的第一位,并丢弃其余的,这就是为什么会得到38.0
您可以通过两种方式来解决这个问题—您可以将数字作为字符串存储在数据库中,这可能会节省一些转换(但如果需要在查询中使用数字表示,则不会太有用),也可以使用字符串
基本上,您需要定义一个getter和setter,如下所示:
def rational_chest
# I assume this would create a rational from a float
# and respond to `to_s` in a sane manner...
Rational(chest) if chest
end
def rational_chest=(value)
self.chest = parse_rational(value)
end
private
def parse_rational(value)
return nil if value.blank?
value.split.map{|r| Rational(r)}.inject(:+).to_f
end
然后在你的表单中使用rational\u-cost
,而不仅仅是cost
由于您需要在多个字段上执行此操作,因此可以求助于一些漂亮的元编程:
def self.rational_attribute(attribute)
define_method("rational_#{attribute}") do
Rational(send(attribute))
end
define_method("rational_#{attribute}=") do |value|
send "#{attribute}=", value.split.map{|r| Rational(r)}.inject(:+).to_f
end
end
def self.rational_attributes(*attributes)
attributes.each {|attribute| rational_attribute attribute}
end
rational_attributes :chest, :waist, :etc
如果你在多个模型中使用它,把它放在一个模块中(没有self.
s和extend
it!我用If-cost
编辑了你的答案,因为如果留空它会抛出一个错误。这非常有用而且解释得很好!一个缺点是它允许不正确的分数(77/2,等等)但这很容易通过删除Rational()来解决
。它给出了一个小数。最终我可以使用它将其转换回一个混合数。感谢您的帮助!嗯…我能够解决第一个示例中留下空白值的问题,但我正在努力解决第二个示例。我希望允许空白输入。有什么想法吗?我将此错误未定义方法
发送给您l:NilClass`Ah yep good call,我没有考虑过这种情况。我可能会将解析拆分为一个单独的方法,如我最近的编辑所示。总体而言,听起来您的需求比您拥有的基本Rational
类稍微复杂一些,也许值得考虑开发一个自定义度量
class。另外,cost\u was
应该在rails将其转换为数据库中为该属性定义的类型之前为您提供值。当我创建新记录时,我再次收到一些关于nil的错误,但是如果我从send(attribute)
中删除Rational()
,它就会消失。不过,对于我的用例来说,这不是问题。。。