2012-04-18 9 views
5

Posiadam model użytkownika z polem Profit. Pole zysku jest typem DECIMAL (11,0). Mam maskowane wejście na formularzu, które pozwala użytkownikowi wprowadzić coś w rodzaju 1000 $. Chcę sformatować tę wartość i usunąć wszystko poza numerami, więc będę miał 1000 zapisanych. Oto, co mam do tej pory:Sposób formatowania wartości przed zapisaniem w bazie danych w szynach 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 

Ale zachowuje zapisanie 0 w bazie danych. Wygląda na to, że konwertuje go na format dziesiętny przed moją funkcją formatowania.

Odpowiedz

7

Spróbuj tego:

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

/[^ 0-9]/jest taki sam jak/\ D/ – makaroni4

+1

Po prostu naśladuje RegExp autora. Staram się go nie przerażać) – jdoe

+0

dzięki @jdoe użyłem twojej sugestii i działa tak, jakbym tego chciał. –

0
def format_values 
    self.profit.to_d! 
    end 
0

polecam Ci napisać niestandardowy setter dla tej konkretnej instancji zmiennej @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

Domyślam się, że 'u.profit' zwraca wartość zmiennej instancji. To pułapka, którą zrobiłeś! – jdoe

+0

Co masz na myśli? attr_accessor definiuje dwie metody - getter i setter, metoda profit zwraca wartość zmiennej instancji, po prawej) Gdzie jest pułapka?) – makaroni4

+1

Twój 'User' nie ma nic wspólnego z' ActiveRecord :: Base'. A gdyby tak było, zmienna '@ pofit' nie miałaby nic wspólnego z atrybutem' profit' DB. Po odziedziczeniu wersji 'User' z' ActiveRecord :: Base' powinieneś zastąpić '@profit =' 'self.profit ='. W przeciwnym razie maskowałbyś atrybut 'profit'. – jdoe

0

Proponuję za pomocą szyn pomocnika liczby z precyzją . Poniżej znajduje się kod.

Generic Przykład:

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

Rails kod Przykład:

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

Przede wszystkim, to:

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

jest prawie taki sam, jak ten:

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

Nie ma powodu, aby oczekiwać, że Twoja metoda format_values będzie miała jakikolwiek wpływ na self.profit.

Można oczywiście zmianie format_values przypisać przetworzony ciąg self.profit ale to nie pomoże, ponieważ logika czyszcząc jest w niewłaściwym miejscu i będzie on wykonywany po'$1,000' został przekształcony w zera.

Po przypisaniu wartości do właściwości, ActiveRecord zastosuje po drodze pewne konwersje typów. Co stanie się, gdy spróbujesz przekonwertować numer '$1,000'? Oczywiście otrzymasz zero. Można oglądać takiej sytuacji, jeśli bawić się w konsoli:

> 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 

Więc twój czyszczenia danych musi odbywać przed dane idzie do instancji modelu bo jak tylko AR dostaje jego ręki na wartości , Twój '$1,000' stanie się 0 i wszystko zniknie. Położyłbym logikę w kontrolerze, zadaniem kontrolera jest pośredniczenie między światem zewnętrznym a modelami i formatowaniem danych, a mangling z pewnością liczy się jako mediacja. Więc można mieć coś takiego w swoim kontrolerze:

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 

Wtedy wszystko będzie czyste przed ActiveRecord dostaje swoje brudne rączki na danych i robi bałaganu.

Można zrobić podobne rzeczy, przesuwając metodę profit= w modelu, ale to naprawdę nie jest praca modelu.

+0

Wiem, że mogę to zrobić w kontrolerze, ale miałem nadzieję zautomatyzować ten proces przed zapisaniem w samym modelu, ponieważ nazywam go z różnych miejsc. Jakieś pomysły? –

+0

dziękuję za odpowiedź informacyjną btw, a catch z metodą to_s w niewłaściwym miejscu. –

+0

@TamikSoziev: Możesz podać własną metodę 'profit ='. –

Powiązane problemy