Ruby-on-rails Rails 验证数组中的值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19912694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:01:08  来源:igfitidea点击:

Rails validating values in array

ruby-on-railsrubypostgresqlvalidationactiverecord

提问by bsiddiqui

In my Schedule model I want to add some validation to the :wdays field, which is an int[]. I only want values 0..6 to be valid

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

Valid

有效的

Schedule.wdays = [0,1,6]

Invalid

无效的

Schedule.wdays = [0,1,10]

I tried using

我尝试使用

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

and

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

but neither works

但两者都不起作用

What is the proper way to validate the values in an array in your model?

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

回答by mechanicalfish

I don't think that default Rails validators will do the trick here, you can do this though:

我认为默认的 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

回答by Paul Richter

I'm not certain whether there are easier ways to handle this within the existing Rails validation structure. You've got an odd case that the validators weren't really built to handle. You might need to write a custom validator for something like this (assuming an existing validation extension gem isn't available). Something like this:

我不确定在现有的 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

and then in your model:

然后在您的模型中:

class Schedule < ActiveRecord::Base
    include ActiveModel::Validations

    validates :wdays, :presence => true, :array_in_range => true

    ... other model stuff
end

回答by Rafael Biriba

I created this gem: https://github.com/rafaelbiriba/active_model_validates_intersection_of

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

Basicaly, you can use like:

基本上,你可以使用像:

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

and if you try:

如果你尝试:

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

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

Enjoy! Comments, pull requests and feedbacks is always welcome.

享受!始终欢迎评论、请求请求和反馈。

回答by Arian Faurtosh

The accepted answer didn't really do this correctly in my opinion. If someone sets wdays = 'meow'it'll set it to empty array wdays == []without warning.

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

Type Casting is happening you ask for wdaysin that method. It's already converting the data into an array if it's invalid.

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

wdays_before_type_castshould be used instead of wdayswhen checking type.

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

See _before_type_cast

_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