代码之家  ›  专栏  ›  技术社区  ›  Bill

Rails/ActiveRecord:字段规范化

  •  3
  • Bill  · 技术社区  · 15 年前

    我正在尝试从模型中的字段中删除逗号。我希望用户键入一个数字,即10000,该数字应作为10000存储在数据库中。我希望我可以做一些模型端规范化来删除逗号。我不想依赖视图或控制器来正确地格式化我的数据。

    我试过:

    before_validation :normalize
    
    def normalize 
     self['thenumber'] = self['thenumber'].to_s.gsub(',','')
    end
    

    没有工作。

    5 回复  |  直到 7 年前
        1
  •  1
  •   Simon Russell    15 年前

    这样做的问题是,在一段时间内,对象中会存在非规范化的东西;如果您有代码在东西规范化之前处理属性,那么这将是一个问题。

    您可以定义一个setter:

    def thenumber=(value)
      # normalise stuff here, call write_attribute
    end
    

    不幸的是,我认为很多Rails表单的东西都直接编写属性,这也是我不喜欢使用它的原因之一。

    或者您可以在传递参数之前使控制器中的参数正常化。

        2
  •  8
  •   Tyler Rick    14 年前

    http://github.com/mdeering/attribute_normalizer 这似乎是解决这个常见问题的一个有希望的办法。以下是主页上的几个示例:

      # By default it will strip leading and trailing whitespace
      # and set to nil if blank.
      normalize_attributes :author, :publisher
    
      # Using one of our predefined normalizers.
      normalize_attribute  :price, :with => :currency
    
      # You can also define your normalization block inline.
      normalize_attribute :title do |value|
        value.is_a?(String) ? value.titleize.strip : value
      end
    

    因此,在您的案例中,您可能会这样做:

      normalize_attribute :title do |value|
        value.to_s.gsub(',', '')
      end
    
        3
  •  4
  •   Brian Hogan    15 年前

    我认为你做得对。此测试通过:

    test "should remove commas from thenumber" do
      f = Foo.new(:thenumber => "10,000")
      f.save
      f = Foo.find(f.id)
      assert f.thenumber == "10000"    
    end
    

    我用了你的密码。

     class Foo < ActiveRecord::Base
      before_validation :normalize
    
      def normalize 
        self['thenumber'] = self['thenumber'].to_s.gsub(',','')
      end
    
     end
    

    现在,我的模式是将数字设置为字符串,而不是整数。

    Started
    .
    Finished in 0.049666 seconds.
    
    1 tests, 1 assertions, 0 failures, 0 errors
    

    如果您想将它作为一个整数存储在数据库中,那么您肯定需要重写setter:

     def thenumber=(value)
       self['thenumber'] = value.to_s.gsub(',','').to_i
     end
    

    如果您按自己的方式进行,使用整数列,它会被ar…截断。

    >> f.thenumber = "10,000"
    => "10,000"
    >> f.thenumber
    => 10
    

    这是一个鲜为人知的关于红宝石和整数的东西…它通过截断不再是整数的任何内容来自动强制转换。

    irb(main):004:0> i = "155-brian-hogan".to_i
    => 155
    

    对这样的事情很酷

    /users/155-brian-hogan
    
    @user = User.find_by_id(params[:id])
    

    但对你所做的并不那么酷。

    因此,要么将col更改为字符串并使用过滤器,要么更改setter:。

    祝你好运!

        4
  •  0
  •   phillc    15 年前

    Ruby是否允许您在之间进行交换?和[’]? 我不知道,我稍后再试,但我想你应该用。

    self.thenumber = self.thenumber.to_s.gsub(',','')
    
        5
  •  0
  •   MikeJ    14 年前

    您应该从您的before-validation方法返回true,否则,如果分配给self[‘theNumber’]的表达式最终为nil或false,则不会根据rails文档保存数据:

    如果before_*callback返回false, 所有后来的回电和 已取消关联操作。

    表面上,您试图在这里规范化,然后使用Rails验证检查规范化的结果,这将决定nil/false/blank是否正常。

    before_validation :normalize
    
    def normalize 
      self['thenumber'] = self['thenumber'].to_s.gsub(',','')
      return true
    end