Rails内置的验证方法可以验证PostgreSQL的Array[String]字段至少包含一个元素吗?

huangapple go评论90阅读模式
英文:

Built-in Rails way of validating that a PostgreSQL Array[String] field has at least one item in it?

问题

我们有一个基本上是 PostgreSQL 数组字符串字段的字段,如下所示:

add_column :books, :tags, :string, array: true, default: []

我该如何添加验证以验证 tags 数组中至少有一个字符串,并且该字符串来自字符串枚举集合?

我在这里看到我们可以对字符串值使用 accept,像这样:

class Person < ApplicationRecord
  validates :terms_of_service, acceptance: { accept: 'yes' }
  validates :eula, acceptance: { accept: ['TRUE', 'accepted'] }
end

但是对于数组[string]字段呢?像这样是最好的选择吗?

class Book < ApplicationRecord
  # tags :string is an Array
  validate :tags_has_one_from_set

  enum tag: {
    foo: 'foo',
    bar: 'bar'
  }

  def tags_has_one_from_set
    allowed_tags = Book.tags.values

    if tags.length == 0
      errors.add(:tags, "Must select at least one tag")
    elsif !tags.all? { |t| allowed_tags.include?(t) }
      errors.add(:tags, "Must select from approved tag list")
    end
  end
end

在Rails中是否有任何更多的“内置”或最佳实践方式来实现这一点?

英文:

We have a PostgreSQL array string field basically like:

add_column :books, :tags, :string, array: true, default: []

How can I add a validation to verify that that tags array has at least 1 string in it, and that the string is from an enum set of strings?

I see we have accept on string values, like this:

class Person &lt; ApplicationRecord
  validates :terms_of_service, acceptance: { accept: &#39;yes&#39; }
  validates :eula, acceptance: { accept: [&#39;TRUE&#39;, &#39;accepted&#39;] }
end

But what about on array[string] fields? Is something like this my best option?

class Book &lt; ApplicationRecord
  # tags :string is an Array
  validate :tags_has_one_from_set

  enum tag: {
    foo: &#39;foo&#39;,
    bar: &#39;bar&#39;
  }

  def tags_has_one_from_set
    allowed_tags = Book.tags.values

    if tags.length == 0
      errors.add(:tags, &quot;Must select at least one tag&quot;)
    elsif !tags.all? { |t| allowed_tags.include?(t) }
      errors.add(:tags, &quot;Must select from approved tag list&quot;)
    end
  end
end

Is there any more "built-in" or best-practice sort of way of doing this in Rails?

答案1

得分: 1

你应该能够使用内置的 lengthinclusion 验证器:

validates :tags,
  length: { minimum: 1, message: "必须至少有一个标签" },
  inclusion: { in: tags.values, message: "必须从以下选项中选择: #{tags.values.join(", ")}" }
英文:

You should be able to use the built in length and inclusion validators:

validates :tags,
  length: { minimum: 1, message: &quot;must have at least one tag&quot; },
  inclusion: { in: tags.values, message: &quot;must be selected from: #{tags.values.join &quot;, &quot;}&quot; }

huangapple
  • 本文由 发表于 2023年8月9日 02:10:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862178.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定