Rails/ActiveRecord:字段规范化

Bil*_*ill 3 activerecord model ruby-on-rails

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

我试过了:

before_validation :normalize

def normalize 
 self['thenumber'] = self['thenumber'].to_s.gsub(',','')
end
Run Code Online (Sandbox Code Playgroud)

没有工作.

Tyl*_*ick 8

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
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下你可能会这样做:

  normalize_attribute :title do |value|
    value.to_s.gsub(',', '')
  end
Run Code Online (Sandbox Code Playgroud)


Bri*_*gan 5

我认为您做对了。该测试通过:

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
Run Code Online (Sandbox Code Playgroud)

我用了你的代码。

 class Foo < ActiveRecord::Base
  before_validation :normalize

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

 end
Run Code Online (Sandbox Code Playgroud)

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

Started
.
Finished in 0.049666 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
Run Code Online (Sandbox Code Playgroud)

如果要将其作为整数存储在db中,那么您肯定需要覆盖setter:

 def thenumber=(value)
   self['thenumber'] = value.to_s.gsub(',','').to_i
 end
Run Code Online (Sandbox Code Playgroud)

如果按照自己的方式进行操作,则使用整数列时,它将被AR截断。

>> f.thenumber = "10,000"
=> "10,000"
>> f.thenumber
=> 10
Run Code Online (Sandbox Code Playgroud)

这在Ruby和整数中鲜为人知……它会通过截断不再是整数的任何东西来自动广播。

irb(main):004:0> i = "155-brian-hogan".to_i
=> 155
Run Code Online (Sandbox Code Playgroud)

对于诸如此类的东西可能很酷

/users/155-brian-hogan

@user = User.find_by_id(params[:id])
Run Code Online (Sandbox Code Playgroud)

但是对于您正在做的事情却不是那么酷。

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

祝好运!


小智 1

这样做的问题是,在一段时间内,非标准化的东西会存在于对象中;如果您有在标准化之前对属性起作用的代码,那么这将是一个问题。

您可以定义一个设置器:

def thenumber=(value)
  # normalise stuff here, call write_attribute
end
Run Code Online (Sandbox Code Playgroud)

不幸的是,我认为很多 Rails 表单内容直接写入属性,这是我不倾向于使用它的原因之一。

或者,您可以在传递控制器中的参数之前对其进行标准化。