【问题标题】:Rails validation scope of serialized text array序列化文本数组的Rails验证范围
【发布时间】:2014-02-19 05:30:42
【问题描述】:

我有一个 Rails 模型,它有一个字段 array_field,它是一个序列化的文本数组。我希望这个数组值和another_field 的值的组合是唯一的。

应该直截了当,不是吗?

class Foo < ActiveRecord::Base
  validates_uniqueness_of :array_field, scope: [:another_field]

  serialize :filters, Array
end

这不起作用。但是,如果我在验证中切换它们,

validates_uniqueness_of :another_field, scope: [:array_field] 按预期工作。

有人可以解释为什么会这样吗?这是预期的行为吗?

array_field 的值为nil[] 时,前一种设置的Postgres 错误是这样的:

PG::SyntaxError: ERROR:  syntax error at or near ")"
   LINE 1: ...other_field" = 103 AND "foo"."array_field" = ) LIMIT 1

array_field[[1, 2], [3, 4, 5]](我使用的一个示例多数组)时,它是:

PG::UndefinedFunction: ERROR:  operator does not exist: text = integer
   LINE 1: ...other_field" = 103 AND "foo"."array_field" = 1, 2, 3, 4, 5) LIMIT 1

Rails 似乎不知道如何翻译这个查询的序列化对象。我错过了什么还是这是一个错误?

编辑:这发生在 Rails 4.0.2 中。

第二次编辑:

澄清:我理解为什么会发生这种情况(Rails 具有用于列表查询的自定义逻辑),并且我使用自定义验证器在验证之前手动执行序列化和自定义序列化器以避免 Yaml 字符串比较出现问题(如我的另一个问题here 中所述)。

在这一点上,我主要是想知道为什么 validates_uniqueness_of 将主要字段与 scope 字段区别对待,并希望有人能解释一下。

【问题讨论】:

  • 你能指定rails版本吗?

标签: ruby-on-rails postgresql


【解决方案1】:

我无法解释为什么验证以一种方式工作,而另一种则不行。

但我认为基本上你的问题是由于serialize 仅定义一个属性将在保存时使用 Yaml 序列化并在加载时反序列化。

换句话说:你通过serialize :filters, Array 说的唯一一件事就是

保存 Foo 时,首先使用 Yaml 序列化它的 filters 属性, 从数据库加载 Foo 时,请确保 filters 属性反序列化后为 Array,否则抛出异常

它不会影响查询的构造方式。相反,使用 Rails 的常规查询规则。因此,数组被转换为逗号分隔的数字列表。例如,在构造 LIKE 查询时,这是有意义的。这就是查询失败的原因。 DB 字段是一个字符串,但您正在尝试将其与列表进行比较。

我没有在 Rails 4 中使用原生 PostgreSQL 数组列,但我的猜测是,如果您使用它们而不是序列化类型的解决方案,这些问题将会解决。您可以获得额外的好处,即能够在数据库级别的数组内容中进行搜索。

【讨论】:

  • 不是一个选项:PG::InvalidTextRepresentation: ERROR: multidimensional arrays must have array expressions with matching dimensions
  • 请解释一下您的意思。当您收到此错误消息时,您究竟做了什么?
  • 抱歉不清楚。我不能使用本机 Postgres 数组,因为 Postgres 要求它的多维数组是“矩形的”,而我的不是(请参阅我原始问题中的示例数组)。
猜你喜欢
  • 2014-07-22
  • 2011-04-20
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多