5

我有一个带有利润字段的用户模型。利润字段是 DECIMAL (11,0) 类型。我在表单上有一个屏蔽输入,允许用户输入 1,000 美元之类的东西。我想格式化该值并从中删除除数字之外的所有内容,这样我将保存 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。看起来它在我的格式化功能之前将其转换为十进制。

4

6 回答 6

8

试试这个:

def profit=(new_profit)
  self[:profit] = new_profit.gsub(/[^0-9]/, '')
end
于 2012-04-18T17:54:23.863 回答
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'变成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

然后,在 ActiveRecord 弄脏你的数据并把事情弄得一团糟之前,一切都会变得干净。

您可以通过覆盖profit=模型中的方法来做类似的事情,但这实际上不是模型的工作。

于 2012-04-18T20:02:45.973 回答
0
  def format_values
    self.profit.to_d!
  end
于 2012-04-18T17:48:05.837 回答
0

我建议您为这个特定的实例变量@profit 编写自定义设置器:

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"
于 2012-04-18T17:56:14.697 回答
0

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

通用示例:

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
于 2012-04-18T18:48:56.707 回答
0
class User < ActiveRecord::Base
  before_save :format_values

  private

  def format_values
    self.profit = profit.to_s.gsub(/\D/,'') if profit
  end
end
于 2012-04-18T19:29:11.340 回答