【问题标题】:Uniqueness validation not working on has_many :though association on rails 5唯一性验证不适用于has_many:尽管rails 5上的关联
【发布时间】:2018-03-08 21:16:27
【问题描述】:

模型

class User < ApplicationRecord
    has_many :memberships
    has_many :pages, through: :memberships 
end

class Page < ApplicationRecord
    has_many :memberships
    has_many :users, through: :memberships 
end

class Membership < ApplicationRecord
    belongs_to :user
    belongs_to :page

    validates :page_id, uniqueness: { scope: :user_id}
end

能够在页面和用户页面上创建多个用户,就像没有调用验证一样。

【问题讨论】:

  • 你的意思是可以创建多条同一个page_iduser_id的会员记录?
  • 也许我们说的是同一件事,但很难判断您是否期望该验证的正确结果。您应该提供一个可重现的示例(例如来自 Rails 控制台),在其中显示例如 2.times { Membership.create!(user: User.first, page: Page.first) } 的结果。
  • 我可以多次调用 Page.users.create name: 'user name'。
  • 除非您对User#name 进行唯一性验证,否则会创建多个用户,这就是Membership 验证通过的原因。运行2.times { Membership.create!(user: User.first, page: Page.first) },您应该会看到它有效。 (因为引发了 RecordNotValid 错误)。
  • 谢谢@Max,也许我走错了路。我想要实现的是不要多次将同一用户作为成员添加到页面。

标签: ruby-on-rails ruby validation has-many-through validates-uniqueness-of


【解决方案1】:

要在关联模型中触发验证,您需要使用validates_associated

class User < ApplicationRecord
  has_many :memberships
  has_many :pages, through: :memberships
  validates_associated :memberships
end

class Page < ApplicationRecord
  has_many :memberships
  has_many :users, through: :memberships
  validates_associated :memberships
end

class Membership < ApplicationRecord
  belongs_to :user
  belongs_to :page
  validates :page_id, uniqueness: { scope: :user_id}
end

这可能是一个真正的问题,因为在隐式创建关联时不会调用关联验证。

此外,创建一个复合数据库索引是一个好主意,它可以防止possible race conditions

class AddCompoundIndexToMemberships < ActiveRecord::Migration[5.0]
  def change
    add_index :memberships, [:page_id, :user_id], unique: true
  end
end

这可确保在数据库级别上不能创建两个相同的行。

【讨论】:

    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多