如何在rails 3中保存到数据库之前格式化值

Tam*_*iev 5 ruby activerecord ruby-on-rails ruby-on-rails-3

我有一个带有利润字段的用户模型.利润字段是DECIMAL(11,0)类型.我在表单上有一个屏蔽输入,允许用户输入1000美元.我想格式化该值并删除除数字之外的所有内容,因此我将保存1000.这是我到目前为止:

class User < ActiveRecord::Base
  before_save :format_values

  private

  def format_values
    self.profit.to_s.delete!('^0-9') unless self.profit.nil?
  end
end
Run Code Online (Sandbox Code Playgroud)

但它一直在数据库中保存0.看起来它在我的格式化功能之前将其转换为十进制.

jdo*_*doe 8

试试这个:

def profit=(new_profit)
  self[:profit] = new_profit.gsub(/[^0-9]/, '')
end
Run Code Online (Sandbox Code Playgroud)


mu *_*ort 6

首先,这个:

def format_values
  self.profit.to_s.delete!('^0-9') unless self.profit.nil?
end
Run Code Online (Sandbox Code Playgroud)

与此基本相同:

def format_values
    return if(self.profit.nil?)
    p = self.profit
    s = p.to_s
    s.delete!('^0-9')
end
Run Code Online (Sandbox Code Playgroud)

所以没有理由期望你的format_values方法对任何效果有任何影响self.profit.

当然,变化的,你可以format_values到指定处理字符串self.profit,但不会帮助,因为你的清理逻辑是在错误的地方,它就会被执行后, '$1,000'已经变成了一个零.

为属性分配值时,ActiveRecord将沿途应用某些类型转换.当您尝试转换'$1,000'为数字时会发生什么?你当然得零.如果你在控制台中玩游戏,你可以看到这种情况:

> a = M.find(id)
> puts a.some_number
11
> a.some_number = 'pancakes'
 => "pancakes"
> puts a.some_number
0
> a.some_number = '$1,000'
 => "1,000"
> puts a.some_number
0
> a.some_number = '1000'
 => "1000"
> puts a.some_number
1000
Run Code Online (Sandbox Code Playgroud)

因此,您的数据清理必须在数据进入模型实例之前进行,因为一旦AR获得了价值,您的'$1,000'意志就会变得0全部丢失.我将逻辑放在控制器中,控制器的工作是在外部世界和模型之间进行调解,数据格式化和修改肯定算作调解.所以你可以在你的控制器中有这样的东西:

def some_controller
    fix_numbers_in(:profit)
    # assign from params as usual...
end

private

def fix_numbers_in(*which)
    which.select { |p| params.has_key?(p) }.each do |p|
        params[p] = params[p].gsub(/\D/, '') # Or whatever works for you
    end
end
Run Code Online (Sandbox Code Playgroud)

然后一切都会干净,然后ActiveRecord就会对你的数据进行肮脏的小动作并弄乱一些东西.

您可以通过覆盖profit=模型中的方法来执行类似的操作,但这实际上不是模型的工作.