【问题标题】:Ruby on Rails ActiveRecord "has_many :through" uniqueness validationRuby on Rails ActiveRecord "has_many :through" 唯一性验证
【发布时间】:2011-02-26 20:57:59
【问题描述】:

目前我通过每次检查插入一个新关系,如果它不存在:

unless Relationship.exists?(:entry_id => entry.id, :tag_id => tag.id)

我怎样才能在关系模型中实现这样的验证,这样它就不允许在同一个条目和标签之间有多个关系?

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:
    class Relationship < ActiveRecord::Base
      belongs_to :entry
      belongs_to :tag
      validates :tag_id, :uniqueness => { :scope => :entry_id }
    end
    

    【讨论】:

      【解决方案2】:

      假设您的模型如下所示:

      class Entry < ActiveRecord::Base
        has_many :relationships
        has_many :tags, :through => :relationships
      end
      
      class Tag < ActiveRecord::Base
        has_many :relationships
        has_many :entries, :through => :relationships
      end
      
      class Relationship < ActiveRecord::Base
        belongs_to :entry
        belongs_to :tag
      end
      

      您可以为您的 Relationship 加入模型添加唯一验证:

      validates_uniqueness_of :tag_id, :scope => :entry_id
      

      validates_uniqueness_of 方法将确保关系不存在,:scope 选项将匹配范围限定为给定列。 rails 通过此验证生成的 SQL 如下所示:

      SELECT `relationships`.id
      FROM `relationships`
      WHERE (`relationships`.`tag_id` = <tag id> AND `relationships`.`entry_id` = <entry id>)
      LIMIT 1
      

      (您会注意到这与您显式使用 Relationship.exists?(:entry_id =&gt; entry.id, :tag_id =&gt; tag.id) 生成的 SQL 基本相同),如果找到记录,验证将失败。

      此外,与任何要验证唯一性的情况一样,请确保在 relationships 表中的 tag_id, entry_id 上具有唯一键。有关详细信息,请参阅this article 和我上面链接的 API 页面的“并发性和完整性”。

      【讨论】:

      • 谢谢,但是如何添加唯一键,我仍然可以为其他条目使用相同的 tag_id,并为同一条目使用许多不同的标签? add_index "relationships", ["tag_id"], :unique => true - 我想会阻止我多次使用相同的 tag_id。
      • 您必须为 both 列创建索引。在迁移中,它看起来像add_index :relationships, [:tag_id, :entry_id], :unique =&gt; true。然后,做你的 DBMS,只有当两列的值都与现有行匹配时,新行才会发生冲突。
      • (应该是你的DBMS)
      猜你喜欢
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-04
      • 1970-01-01
      相关资源
      最近更新 更多