2012-04-18 17 views
5

Profitフィールドを持つUserモデルがあります。 ProfitフィールドはDECIMAL(11,0)型です。私は$ 1000のようなものを入力するためのフォーム上にマスクされた入力を持っています。私はその値を書式化し、そこから数値を除いてすべてを削除したいので、1000を保存します。ここに私がこれまでに持っているものがあります:レールにデータベースに保存する前に値をフォーマットする方法3

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を保存し続けます。私の書式設定関数の前に10進数に変換しているように見えます。

答えて

7

これを試してみてください:

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

/[^ 0-9] /は、\​​ D/ – makaroni4

+1

と同じです。著者のRegExpを模倣するだけです。彼を怖がらせようとしないで) – jdoe

+0

ありがとう@jdoe私はあなたの提案を使用して、それが私が望むように動作します。 –

0
def format_values 
    self.profit.to_d! 
    end 
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" 
+1

'u.profit'はインスタンス変数の値を返します。あなたが作った落とし穴です! – jdoe

+0

どういう意味ですか? attr_accessorは、getterとsetterの2つのメソッドを定義しています。利益メソッドはインスタンス変数の値を返します。その通りです)落ち葉はどこですか? – makaroni4

+1

あなたの 'User'は' ActiveRecord :: Base'とは​​何の関係もありません。もしそれがあったとしても、 '@ pofit'変数は' profit'DB属性とは関係ありません。 'ActiveRecord :: Base'からあなたのバージョンの' User'を継承した後、 '@profit ='を 'self.profit ='に置き換えてください。それ以外の場合は、 'profit'属性をマスクします。 – jdoe

0

私は正確に数のレールのヘルパーを使用することをお勧めし。以下はいくつかのコードです。

一般的な例:

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 
0
class User < ActiveRecord::Base 
    before_save :format_values 

    private 

    def format_values 
    self.profit = profit.to_s.gsub(/\D/,'') if profit 
    end 
end 
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_valuesself.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=メソッドをオーバーライドすることで同様のことができますが、それは実際にモデルの仕事ではありません。

+0

私はコントローラでそれを行うことができますが、私はそれを呼び出すので、モデル自体を保存する前にそのプロセスを自動化することを望んでいました異なる場所から。何か案は? –

+0

有益な回答btwのおかげで、間違った場所にto_sメソッドを持つキャッチがあります。 –

+0

@TamikSoziev:独自の 'profit ='メソッドを提供することができます。 –