进行DB约束的无效数据库操作_before_数据模型验证? (HABTM唯一性)

时间:2017-07-07 11:33:11

标签: ruby-on-rails validation activerecord associations rspec-rails

我有一个具有HABTM自我加入关系的模型(Company)(联接表调用关联公司supplierspurchasers)。

我想阻止公司拥有重复的供应商或购买者,因此我在供应商 - 购买者对中添加了唯一性约束。我在数据库级别添加了这个约束:

create_table :supply_link, id: false do |t|
  t.belongs_to :supplier,  null: false, index: true
  t.belongs_to :purchaser, null: false, index: true
end

add_index :supply_link, [:supplier_id, :purchaser_id], unique: true

和数据模型级别:

class Company < ApplicationRecord
  has_and_belongs_to_many :purchasers, -> { distinct },
                                       join_table: :supply_link,
                                       class_name: :Company,
                                       foreign_key: :supplier_id,
                                       association_foreign_key: :purchaser_id
  has_and_belongs_to_many :suppliers, -> { distinct },
                                      join_table: :supply_link,
                                      class_name: :Company,
                                      foreign_key: :purchaser_id,
                                      association_foreign_key: :supplier_id

end

但是在尝试为这种安排编写规范时,我注意到一些奇怪的事情:通常,数据模型验证优先于数据库约束 - 但不是在这里。

也就是说,如果同时设置数据模型验证(validates :email, presence: true)和数据库约束(t.string :email, null: false),则数据模型会捕获无效操作(如User.create(email: nil)) DB甚至都看到了它们。

但是在这种情况下,当我尝试多次将supplier添加到Company时,它首先会转到数据库,并引发错误。如果我完全删除了数据库约束,那么数据模型以正确的方式处理它,并且重复的条目永远不会被添加到suppliers属性。会发生两件事:1)重复的关联所有都显示在连接表中,但2)模型没有显示company.suppliers的任何重复项(感谢@Pavel Mihailyuk)。我在控制台中手动测试了这个,并使用RSpec / FactoryGirl。

这里发生了什么,编写规范的正确方法是什么?我应该同时保留两个验证并期望无效操作引发ActiveRecord错误吗?我应该删除数据库约束并仅依赖于数据模型的-> { distinct }范围吗?我应该将此报告为Rails中的错误吗?

0 个答案:

没有答案