【问题标题】:activerecord column type / before_validationactiverecord 列类型 / before_validation
【发布时间】:2023-03-26 09:09:01
【问题描述】:

如何在活动记录将属性转换为关联的列类型之前在模型级别处理属性?

我的具体问题是...用户以十进制形式(即 15.32 美元)为一个名为“cents”的整数类型列输入金额...在我的模型中,我尝试使用 before_validation 挂钩来抓取该金额并将其转换为美分(应为 1532),但是活动记录已将其四舍五入为整数,现在我的转换仅为 1500。

我可以在控制器级别转换参数中的数量,但为了保持 DRY,我更愿意在模型中控制它。

有什么建议吗?

【问题讨论】:

    标签: ruby-on-rails activerecord callback


    【解决方案1】:

    我建议您根本不要公开您的cents 属性。使用名为 dollars 的属性 getter/setter 对并从中计算您的 cents

    class Model < ActiveRecord::Base
       …
       def dollars
         cents / 100.0
       end
    
       def dollars=(value)
         cents = dollars * 100
       end
       …
    end
    

    【讨论】:

    • 这是正确的方法。如果您使用#attr_accessible,则需要添加#dollars 并删除#cents。
    • 太棒了。效果很好。我从来不知道 get & set 用 rails 这么简单。谢谢!
    【解决方案2】:

    您可以将 before_validation 钩子与 before_type_cast 值一起使用。你可以这样做:

    class Model < ActiveRecord::Base
       before_validation :convert_dollars_to_cents
    
       def convert_dollars_to_cents
           cents = cents_before_type_cast * 100
       end
       …
    end
    

    我认为值得一提的是,因为很多人不知道 before_type_cast 值,但从对象建模的角度来看,这里还有很多其他建议可以提供。

    【讨论】:

      【解决方案3】:

      我不知道人们用什么来管理资金,但我使用了 rails_money 插件,它负责大部分转换,所以我会先检查一下。

      http://www.railslodge.com/plugins/461-rails-money

      但要解决您的问题,您希望在列类型上将货币属性存储为 floatdecimal

      我见过大多数人都这样做。

      t.decimal :amount, :precisions => 8, :scale => 2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-27
        • 1970-01-01
        • 2016-10-16
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        • 2017-10-23
        相关资源
        最近更新 更多