我有一个带有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。看起来它在我的格式化功能之前将它转换为十进制。
答案 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