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

时间:2012-04-18 17:44:58

标签: ruby-on-rails ruby ruby-on-rails-3 activerecord

我有一个带有Profit字段的用户模型。利润字段是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

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

6 个答案:

答案 0 :(得分:8)

试试这个:

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

答案 1 :(得分:6)

首先,这个:

def format_values
  self.profit.to_s.delete!('^0-9') unless self.profit.nil?
end

几乎与此相同:

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

因此,我们没有理由期望您的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

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

0

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

您可以通过覆盖模型中的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 方法来执行类似的操作,但这实际上不是模型的工作。

答案 2 :(得分:0)

  def format_values
    self.profit.to_d!
  end

答案 3 :(得分:0)

我建议你为这个特定的实例变量@profit编写自定义setter:

class User
  attr_accessor :profit

  def profit= value    
    @profit = value.gsub(/\D/,'')
  end
end

u = User.new
u.profit = "$1,000"
p u.profit # => "1000"

答案 4 :(得分:0)

我建议使用精确数字的rails helper。下面是一些代码。

通用示例:

number_with_precision(111.2345, :precision => 1, :significant => true)     # => 100

Rails代码示例:

def profit=(new_profit)
  number_with_precision(self[:profit], :precision => 1, :significant => true)
end

答案 5 :(得分:0)

class User < ActiveRecord::Base
  before_save :format_values

  private

  def format_values
    self.profit = profit.to_s.gsub(/\D/,'') if profit
  end
end