代码之家  ›  专栏  ›  技术社区  ›  catinahat

如何验证Rails模型中的坐标?

  •  0
  • catinahat  · 技术社区  · 6 年前

    我已经构建了一个Rails应用程序,它使用HTML5地理定位API来获取用户的当前位置。我使用坐标填充表单中的字段。我想知道如何在我的模型中验证这一点。以下是我的表单输入:

    <%= f.input :start_point, label: false,  input_html: { id: 'coordinatesStart' } %>
    

    坐标应该是我的形式 54.678, 45.789 可以取小数点后的任意数量的数字。

    0 回复  |  直到 6 年前
        1
  •  0
  •   Mark    6 年前

      validates :points, format: { with: /\d{1,}\.\d{1,},\s\d{1,}\.\d{1,}/, message: "please enter co-ordinates in correct format"}
    

    逻辑是:

    至少匹配一个数字,后跟一个小数点,后跟一个或多个数字,后跟逗号,后跟空格,后跟一个或多个数字,后跟一个小数点,后跟一个或多个数字

        2
  •  0
  •   mechnicov    6 年前

    纬度必须介于-90和90之间,经度必须介于-180和180之间。

    GEOCOORDINATES_REGEX = /\A-?(?:90(?:(?:\.0*)?)|(?:[0-9]|[1-8][0-9])(?:(?:\.\d*)?)),\s-?(?:180(?:(?:\.0*)?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.\d*)?))\z/.freeze
    
    validates :start_point, format: { with: GEOCOORDINATES_REGEX }
    
        3
  •  0
  •   rewritten    6 年前

    第一件事应该是将输入验证和模型内容分开。使用一些单独的层,即使它只是一个实现ActiveModel::Validations的裸类。

    然后,添加一个独立的验证器类,如:

    class GeoPairValidator < ActiveModel::EachValidator
      RE = /\A\d+\.\d+, ?\d+\.\d+\z/
    
      def validate_each(record, attribute, value)
        # value should be "nn.nnnnnnn, nn.nnnnnnn"
        record.errors.add(attribute, :invalid, value: value) if value.to_s !~ RE
    
        # split by comma, convert to float
        v1, v2 = value.to_s.split(', ').map(&:to_f)
    
        # check logical bounds
        record.errors.add(attribute, :invalid, value: value) if v1.abs > 90
        record.errors.add(attribute, :invalid, value: value) if v2.abs > 180
      end
    end
    

    最后,在输入类中使用它:

    class YourInput
      include ActiveModel::Validations
    
      attr_accessor :start_point
    
      validates :start_point, geo_point: true
    end
    

    同时检查 https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates 更多详细信息。