Rails / ActiveRecord: normalização campo

votos
3

Eu estou tentando remover as vírgulas de um campo em um modelo. Eu quero que o usuário digite um número, ou seja, 10.000 e esse número deve ser armazenado no banco de dados como 10000. Eu estava esperando que eu poderia fazer alguma normalização do lado do modelo para remover a vírgula. Eu não quero depender da vista ou controlador para formatar corretamente meus dados.

Eu tentei:

before_validation :normalize

def normalize 
 self['thenumber'] = self['thenumber'].to_s.gsub(',','')
end

não worky.

Publicado 19/05/2009 em 17:44
fonte usuário
Em outras línguas...                            


5 respostas

votos
7

http://github.com/mdeering/attribute_normalizer parece uma solução promissora para este problema comum. Aqui estão alguns exemplos da home page:

  # By default it will strip leading and trailing whitespace
  # and set to nil if blank.
  normalize_attributes :author, :publisher

  # Using one of our predefined normalizers.
  normalize_attribute  :price, :with => :currency

  # You can also define your normalization block inline.
  normalize_attribute :title do |value|
    value.is_a?(String) ? value.titleize.strip : value
  end

Assim, no seu caso, você pode fazer algo como isto:

  normalize_attribute :title do |value|
    value.to_s.gsub(',', '')
  end
Respondeu 18/08/2010 em 19:46
fonte usuário

votos
4

Eu acho que você está fazendo certo. Este teste passa:

test "should remove commas from thenumber" do
  f = Foo.new(:thenumber => "10,000")
  f.save
  f = Foo.find(f.id)
  assert f.thenumber == "10000"    
end

E eu usei o seu código.

 class Foo < ActiveRecord::Base
  before_validation :normalize

  def normalize 
    self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  end

 end

Agora, meu esquema é configurado para thenumber para ser uma seqüência, porém, não um inteiro.

Started
.
Finished in 0.049666 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

Se você quiser armazenar esta no db como um inteiro, então você definitivamente precisa para substituir o setter:

 def thenumber=(value)
   self['thenumber'] = value.to_s.gsub(',','').to_i
 end

Se você fazer do seu jeito, com uma coluna de número inteiro, ele é truncado por AR ....

>> f.thenumber = "10,000"
=> "10,000"
>> f.thenumber
=> 10

Isso é uma coisa pouco conhecida com Ruby e inteiros ... É auto-casts truncando qualquer coisa que não é mais um inteiro.

irb(main):004:0> i = "155-brian-hogan".to_i
=> 155

Pode ser legal para coisas como

/users/155-brian-hogan

@user = User.find_by_id(params[:id])

Mas não tão legal para o que você está fazendo.

Assim, ou mudar o col em uma string e usar o filtro, ou alterar o setter :)

Boa sorte!

Respondeu 19/05/2009 em 20:38
fonte usuário

votos
1

O problema em fazer isso dessa maneira é que por um tempo, as coisas não normalizada vai existir no objeto; se você tiver código que funciona com os atributos antes de o material se normalizaram, então isso será um problema.

Você poderia definir um setter:

def thenumber=(value)
  # normalise stuff here, call write_attribute
end

Infelizmente eu acho que um monte de coisas forma Rails escreve os atributos diretamente, o que é uma das razões que eu não tendem a usá-lo.

Ou você poderia normalizar os parâmetros no controlador antes de passá-los completamente.

Respondeu 19/05/2009 em 19:20
fonte usuário

votos
0

Você deve retornar verdadeiro do seu método before_validation, caso contrário, se a expressão a ser atribuída a auto [ 'thenumber'] acaba sendo nulo ou falso, os dados não serão salvos, pelo documention Rails:

Se um before_ * callback retorna false, todos os retornos de chamada mais tarde e a ação associada são cancelados.

Aparentemente, você está tentando normalizar aqui, em seguida, verificar o resultado da normalização com os seus validações do Rails, que decidirá se nil / false / em branco estão bem ou não.

before_validation :normalize

def normalize 
  self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  return true
end
Respondeu 11/05/2010 em 21:01
fonte usuário

votos
0

O rubi deixar você trocar entre um. e [ '']? Eu não sei, vou tentar mais tarde, mas eu acho que você deveria usar.

self.thenumber = self.thenumber.to_s.gsub(',','')
Respondeu 19/05/2009 em 17:58
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more