Convert User input to integer

后端 未结 3 1340
难免孤独
难免孤独 2021-02-14 05:10

So I have a form where users can input a price. I\'m trying to make a before_validation that normalizes the data, clipping the $ if the user puts it.

before_val         


        
相关标签:
3条回答
  • 2021-02-14 05:51

    My soluction colum price type decimal

    t.decimal :price, precision: 12, scale: 6
    
    # app/concern/sanitize_fields.rb
        module SanitizeFields
          extend ActiveSupport::Concern
    
          def clear_decimal(field)
            return (field.to_s.gsub(/[^\d]/, '').to_d / 100.to_d) unless field.blank?
    
          end
    
          def clear_integer(field)
            field.to_s.strip.gsub(/[^\d]/, '') unless field.blank?
          end
    
          # module ClassMethods
          #   def filter(filtering_params)
          #     results = self.where(nil)
          #     filtering_params.each do |key, value|
          #       results = results.public_send(key, value) if value.present?
          #     end
          #     results
          #   end
          #
          #   #use
          #   #def index
          #   #  @products = Product.filter(params.slice(:status, :location, :starts_with))
          #   #end
          #
          # end
    
        end
    
    #app/controllers/products_controller.rb
    
    include SanitizeFields
    
    params[:product][:price] = clear_decimal(params[:product][:price])
    
    0 讨论(0)
  • 2021-02-14 06:01

    I would define a virtual attribute and do my manipulation there allowing you to format and modify both the getter and setter at will:

    class Model < ActiveRecord::Base
    
      def foo_price=(price)
        self.price = price... #=> Mods to string here
      end
    
      def foo_price
        "$#{price}"
      end
    

    You also might want to note that:

    "$50.00".gsub(/\D/, '').to_i #=> 5000
    
    0 讨论(0)
  • 2021-02-14 06:10

    One way is to override the mechanism on the model that sets the price, like this:

    def price=(val)
        write_attribute :price, val.to_s.gsub(/\D/, '').to_i
    end
    

    So when you do @model.price = whatever, it will go to this method instead of the rails default attribute writer. Then you can convert the number and use write_attribute to do the actual writing (you have to do it this way because the standard price= is now this method!).

    I like this method best, but for reference another way to do it is in your controller before assigning it to the model. The parameter comes in as a string, but the model is converting that string to a number, so work with the parameter directly. Something like this (just adapt it to your controller code):

    def create
        @model = Model.new(params[:model])
        @model.price = params[:model][:price].gsub(/\D/, '').to_i
        @model.save
    end
    

    For either solution, remove that before_validation.

    0 讨论(0)
提交回复
热议问题