【问题标题】:SELECT request for uniqueness validation has no WHERE conditionsSELECT 唯一性验证请求没有 WHERE 条件
【发布时间】:2016-07-03 16:56:27
【问题描述】:

我正在搜索 4 天来解决这个问题,我在 ActiveRecord 和使用唯一性验证方面遇到了一些问题。 我无法在控制台或测试中创建包含至少一个唯一性验证的模型。但是,我可以使用 rails 服务器 (API) 创建对象。

这让我发疯了!当我将 Rails3 项目更新到 Rails4 时,它就开始了。

实际上,我使用以下宝石:

  • Rails 4.0.15
  • Ruby 2.2.0
  • FactoryGirl Rails 4.6.0
  • Rspec 3.4.1
  • PG 0.18.4

相关型号:

class ContainerType < BaseModel

  has_many :containers, :inverse_of => :container_type, :dependent => :restrict_with_exception

  validates :name, :length => { :minimum => 1, :maximum => 25 },
                   :presence => true,
                   :uniqueness => true
end

BaseModel 是一个抽象,包含一些所有模型共有的include

class BaseModel < ActiveRecord::Base
  self.abstract_class = true

  include [...]
end

在控制台中测试:

test = ContainerType.last.dup

ContainerType Load (0.7ms) SELECT "container_types".* FROM "container_types" ORDER BY "container_types"."id" DESC LIMIT 1

&lt;ContainerType id: nil, name: "Type #1-6f896a99-fb63-4b3", created_at: nil, updated_at: nil&gt;

test.save!

(0.3ms) 开始
ContainerType Exists (0.4ms) SELECT 1 AS one FROM "container_types" LIMIT 1
(0.3ms) 回滚
ActiveRecord::RecordInvalid:验证失败:名称已被占用
来自 /home/dev/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.1.15/lib/active_record/validations.rb:57:in `save!'

对于有效的 ContainerType:

ContainerType.delete_all
ContainerType.create!(name: 'my container type 1 !')

(0.3ms) 开始
ContainerType Exists (0.4ms) SELECT 1 AS one FROM "container_types" LIMIT 1
(0.3ms) 回滚
ActiveRecord::RecordInvalid:验证失败:名称已被占用
来自 /home/dev/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activerecord-4.1.15/lib/active_record/validations.rb:57:in `save!'

您可能注意到 SELECT 验证请求没有条件。 我确定它与 ActiveRecord 或不兼容的 gem 有关,但我找不到原因....

其他测试:

container_type = ContainerType.where(name: 'my container type 1 !').first_or_create  

ContainerType Load (0.6ms) SELECT "container_types".* FROM "container_types" WHERE "container_types"."name" = '我的容器类型 1 !' ORDER BY "container_types"."id" ASC LIMIT 1
(0.1ms) 开始
ContainerType Exists (0.3ms) SELECT 1 AS one FROM "container_types" LIMIT 1
(0.2ms) 回滚

p container_type.inspect  

"#&lt;ContainerType id: nil, name: \"my container type 1 !\", created_at: nil, updated_at: nil&gt;"

测试

所以问题是:

  • 什么可以使唯一性验证无条件创建 SQL 请求?
  • 你已经看到了吗?

编辑:

经过一番调查,我尝试了: - 在所有 before_* 回调中添加 return true - 创建用于唯一性验证的自定义验证器 - 我生成了一个脚手架模型来检查它是否与我的通用包含相关。

我认为:

这似乎与模型属性有关,通过 rails 更新,我将 StrongParameter 添加到我的控制器中。但模型可能仍在使用一种 protected_attribute 遗物。

【问题讨论】:

  • 您可以尝试在唯一性验证器上将区分大小写的属性设置为 false,如下所示:validates :name, uniqueness: { case_sensitive: false }
  • @D.Visser :我试过了,没有任何变化......
  • 在我看来,它完全按照它应该的方式工作。当您运行 ContainerType.last.dup 时,您正在从最后创建的 ContainerType 中复制属性。您对 name 进行了唯一性验证...当您调用 save 时,该对象无法保存,因为它与另一个对象具有相同的名称。
  • @toddmetheny 哎呀,我忘记了有效的案例......我更新了问题。
  • delete_all之后你能保证对象已经被销毁了吗?你能发布你从运行delete_all获得的相关堆栈跟踪吗?改用destroy 时会得到同样的结果吗?也许有相关的回调应该运行但不是?如果你在运行delete_all 之后但在调用create! 之前reload! 控制台呢?

标签: ruby-on-rails validation activerecord


【解决方案1】:

好的,我的实习生发现了它为什么不起作用,它来自项目中的一个 monkey_patch。从初始化程序加载的库正在覆盖 ActiveRecord::Relation 类...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 2018-06-11
    • 2016-01-19
    相关资源
    最近更新 更多