4 votes

Autoriser les virgules dans un champ numérique

C'est une question tellement stupide que j'ai l'impression d'avoir raté quelque chose de simple. J'ai un formulaire avec un quantity champ. Les gens continuent à taper des virgules lorsqu'ils saisissent la quantité (par exemple, ils tapent 12,000 pour indiquer douze mille), je voudrais donc supprimer les virgules avant d'enregistrer la quantité ( 12000 dans l'exemple) dans une colonne de nombres entiers dans la base de données.

Jusqu'à présent, j'ai essayé deux méthodes. Remplacer la méthode setter comme suggéré dans cette question SO

  def quantity=(num)
    num.gsub!(',', '') if num.is_a?(String)
    self[:quantity] = num.to_i
  end

Cela fonctionne dans un sens. Si je tape 12,000 dans le champ quantité et soumettre le formulaire, j'obtiens 12000 dans la base de données. Le problème est que cela contourne également toutes les quantity validations. Je ne peux plus valider la présence d'une valeur pour la quantité par exemple. Ce n'est pas bon.

J'ai également essayé d'utiliser un rappel de validation avant (au lieu de remplacer le paramètre) :

  before_validation :sanitize_quantity

  def sanitize_quantity
    # Doesn't wok because quantity.to_i already called by this point.
  end

Cela ne fonctionne pas car le temps que la quantité atteigne la méthode de rappel, Rails a déjà appelé to_i sur elle. Cela signifie que 12,000 sera tronqué à 12 au moment où il atteint le callback. Encore une fois, ce n'est pas bon.

Que puis-je faire d'autre à part supprimer les virgules du côté client ?

Pour finir, je suis conscient que c'est essentiellement une chose stupide à faire parce que certains pays utilisent les points et les virgules de manière différente. Je dois quand même le faire.

10voto

CodeGnome Points 25402

Type d'utilisation Coercition

Si je comprends bien votre question, vous essayez de forcer les chaînes de caractères à devenir des nombres. Si c'est le cas, vous pouvez simplement utiliser un cast explicite comme ceci :

validates :quantity, presence: true, numericality: true

def quantity=(num)
  self[:quantity] = num.to_s.scan(/\b-?[\d.]+/).join.to_f
end

Tests et exemples

Pour voir comment cela fonctionne, vous pouvez essayer ce qui suit dans la console.

# String as input.
number = '12,956.05'
number.to_s.scan(/\b-?[\d.]+/).join.to_f
=> 12956.05

# Float as input.
number = 12956.05
number.to_s.scan(/\b-?[\d.]+/).join.to_f
=> 12956.05

# Using an ActiveRecord object.
q = Quantity.new quantity: '12,956.05'
=> #<Quantity id: nil, quantity: 12956.05, created_at: nil, updated_at: nil>
q.save
=> true

9voto

David Tuite Points 5342

En fait, j'ai compris ça au moment où je relisais ma question.

La clé est d'utiliser un attribut virtuel.

class Job < ActiveRecord::Base
  def flexible_quantity
    quantity
  end

  def flexible_quantity=(quantity)
    self.quantity = quantity.gsub(',', '') unless quantity.blank?
  end
 end

Ensuite, dans le formulaire, utilisez l'attribut virtuel.

<%= f.text_field :flexible_quantity %>

Validez maintenant la présence de la valeur flexible_quantity à la place.

class Job < ActiveRecord::Base
  validates :flexible_quantity, presence: true

  # The cool this is that we can leave the numericality validation on the quantity field.
  validates :quantity, presence: true, numericality: { only_integer: true }
end

0voto

MrDanA Points 6685

Vous obtiendrez la quantité en params[:quanity] . Vous pouvez simplement appeler une méthode d'aide (définie dans votre contrôleur, par exemple) pour réparer la chaîne, puis la transmettre à votre modèle.

# YourController.rb
def create # or whatever
    quantity = sanitize_quantity(params[:quantity])
    YourModel.create!(:quantity => quantity)
end

private

    def sanitize_quantity(num)
        num.gsub!(',', '') if num.is_a?(String)
        return num.to_i
    end

Donc vous le désinfectez avant il va dans votre modèle, donc il peut toujours avoir des validations faites sur lui.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X