2012-04-18 9 views
5

Ho un modello Utente con campo Profitto. Il campo profitto è di tipo DECIMAL (11,0). Ho un input mascherato sul modulo che consente all'utente di inserire qualcosa come $ 1.000. Voglio formattare quel valore e rimuovere tutto tranne i numeri da esso così avrò 1000 salvato. Ecco cosa ho finora:Come formattare i valori prima di salvare nel database nelle guide 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 

Ma continua a salvare 0 nel database. Sembra che lo converta in decimale prima della mia funzione di formattazione.

risposta

7

Prova questo:

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

/[^ 0-9]/è uguale a/\ D/ – makaroni4

+1

Imita solo il RegExp dell'autore. Cercando di non spaventarlo) – jdoe

+0

grazie @jdoe ho usato il tuo suggerimento e funziona come lo voglio io. –

0
def format_values 
    self.profit.to_d! 
    end 
0

vi consiglio di scrivere setter personalizzato per questo caso particolare @profit variabile:

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

Immagino che 'u.profit' restituisca il valore della variabile di istanza. È un trabocchetto quello che hai fatto! – jdoe

+0

Cosa intendi? attr_accessor definisce due metodi: getter e setter, il metodo di profitto restituisce il valore della variabile di istanza, a destra) Dov'è un trabocchetto?) – makaroni4

+1

L'utente non ha nulla a che fare con 'ActiveRecord :: Base'. Ed event se avesse, la variabile '@ pofit' non avrebbe nulla a che fare con l'attributo DB' profit'. Dopo aver ereditato la tua versione di 'User' da' ActiveRecord :: Base' avresti dovuto sostituire '@profit =' con 'self.profit ='. Altrimenti maschera l'attributo 'profit'. – jdoe

0

Io suggerirei di usare il rotaie aiutante di numero con precisione . Di seguito è riportato un codice.

Generico Esempio:

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

Rails codice Esempio:

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

Prima di tutto, questo:

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

è praticamente lo stesso di questo:

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

Quindi non c'è motivo di aspettarsi che il tuo metodo format_values abbia alcun effetto su self.profit.

Potreste di cambio di rotta format_values per assegnare la stringa esaminata a self.profit ma che non aiuterà perché la logica di pulizia è nel posto sbagliato e verrà eseguito dopo'$1,000' è stata trasformata in uno zero.

Quando si assegna un valore a una proprietà, ActiveRecord applicherà alcune conversioni di tipo lungo la strada. Cosa succede quando provi a convertire '$1,000' in un numero? Ovviamente ottieni zero. Puoi guardare questo accada se si gioca in giro per la console:

> 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 

Così, il vostro pulizia dei dati deve avvenire prima il dato va nell'istanza modello perché non appena AR ottiene le mani sul valore , il tuo '$1,000' diventerà 0 e tutto è perduto. Metterei la logica nel controller, il lavoro del controller è di mediare tra il mondo esterno e i modelli e la formattazione dei dati e il mangling conta sicuramente come mediazione. Così si potrebbe avere qualcosa di simile nel controller:

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 

allora tutto sarebbe essere puliti prima di ActiveRecord ottiene le sue piccole mani sporche sui dati e fa un casino di cose.

È possibile eseguire operazioni simili sovrascrivendo il metodo profit= nel modello, ma questo non è in realtà il lavoro del modello.

+0

so che posso farlo in controller, ma speravo di automatizzare quel processo prima di salvare nel modello stesso, dato che lo sto chiamando da diversi posti. Qualche idea? –

+0

grazie per la risposta informativa btw e una presa con il metodo to_s in un posto sbagliato. –

+0

@TamikSoziev: potresti fornire il tuo metodo 'profit ='. –

Problemi correlati