【问题标题】:Rails validating values in arrayRails 验证数组中的值
【发布时间】:2013-11-23 15:05:47
【问题描述】:

在我的 Schedule 模型中,我想向 :wdays 字段添加一些验证,该字段是一个 int[]。我只希望值 0..6 有效

有效

Schedule.wdays = [0,1,6]

无效

Schedule.wdays = [0,1,10]

我尝试过使用

validates :wdays, inclusion: { in: [0, 1, 2, 3, 4, 5, 6] }

validates :wdays, inclusion: { in: 0..6 }

但两者都不起作用

在模型中验证数组中的值的正确方法是什么?

【问题讨论】:

    标签: ruby-on-rails ruby postgresql validation activerecord


    【解决方案1】:

    我不认为默认的 Rails 验证器可以解决问题,但您可以这样做:

    validate :validate_wdays
    
    def validate_wdays
      if !wdays.is_a?(Array) || wdays.detect{|d| !(0..6).include?(d)}
        errors.add(:wdays, :invalid)
      end
    end
    

    【讨论】:

    • 这不能完全工作...如果有人设置wdays = 'meow',它会在没有警告的情况下将它设置为空数组[]。堆栈上方的某些事情正在发生,如果数据无效,它已经将数据转换为数组
    【解决方案2】:

    我不确定在现有的 Rails 验证结构中是否有更简单的方法来处理这个问题。您遇到了一个奇怪的情况,即验证器并不是真正为处理而构建的。您可能需要为此编写自定义验证器(假设现有的验证扩展 gem 不可用)。像这样的:

    class ArrayInRangeValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, valueArray)
        valueArray.each do |value|
          record.errors.add "#{attribute} - #{value}", (options[:message] || "is not in the acceptable range") unless (1..6).include?(value)
        end
      end
    end
    

    然后在你的模型中:

    class Schedule < ActiveRecord::Base
        include ActiveModel::Validations
    
        validates :wdays, :presence => true, :array_in_range => true
    
        ... other model stuff
    end
    

    【讨论】:

    • @tirdadc 我从您的编辑中添加了一些更新,但是您能否验证验证器的名称必须是下划线版本(它应该是 array_in_range 而不是 arrayInRange?做您知道有关该公约的任何文档吗?
    • 验证者的名字应该加下划线
    【解决方案3】:

    我创建了这个宝石: https://github.com/rafaelbiriba/active_model_validates_intersection_of

    基本上,你可以像这样使用:

    class User < ActiveRecord::Base
       DEFAULT_PERMISSION = ["read", "write", "share"]
       validates_intersection_of :permission, in: DEFAULT_PERMISSION
    end
    

    如果你尝试:

    user = User.new(permission: ["read", "share"])
    user.valid? #true
    
    user = User.new(permission: ["read", "admin"])
    user.valid? #false
    

    享受吧!随时欢迎评论、拉取请求和反馈。

    【讨论】:

      【解决方案4】:

      在我看来,接受的答案并没有真正正确地做到这一点。如果有人设置wdays = 'meow',它会将其设置为空数组wdays == [],而不会发出警告。

      类型转换正在发生,您在该方法中要求wdays。如果数据无效,它已经将数据转换为数组。

      检查类型时应使用wdays_before_type_cast 而不是wdays

      _before_type_cast

      validate :validate_wdays
      
      def validate_wdays
        errors.add(:wdays, :invalid) if wdays_changed? && !wdays_before_type_cast.is_a?(Array)
        errors.add(:wdays, :invalid) if wdays.any? { |d| (0..6).exclude?(d) }
      end
      

      【讨论】:

        猜你喜欢
        • 2018-01-25
        • 2011-02-01
        • 2012-08-17
        • 2018-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-24
        相关资源
        最近更新 更多