ruby-on-rails - Rails 4 HABTM 自定义关联验证

标签 ruby-on-rails validation activerecord ruby-on-rails-4 has-and-belongs-to-many

我有一个简单的场景,但我似乎找不到任何适用于 Rails 4 的建议解决方案。我只想添加一个自定义验证器来检查我的 HABTM 关联之间存储的关联数量。说起来容易做,令我惊讶的是?

我已经寻找了一个解决方案,但似乎只得到了旧版本 Rails 的答案。我有以下几点:

class User < ActiveRecord::Base

  has_and_belongs_to_many :roles
  after_save :check_maximum_number_of_roles

  .
  .
  .

  private

  def check_maximum_number_of_roles
    if self.roles.length > 3
      errors.add(:roles, 'Users can only have three roles assigned.')
      return false
    end
  end

end

class Role < ActiveRecord::Base

  has_and_belongs_to_many :users

end

我使用的原因 after_save是因为据我所知,存储的关联在添加后首先可用。我也尝试编写自定义验证器(例如 validate: :can_only_have_one_role ),但这也不起作用。

我按以下方式添加关联,并在 rails 控制台中完成此操作(应该可以正常工作?):
user.roles << role

尽管如此,它为用户添加了多个角色,并且不关心任何类型的验证。

非常感谢帮助,谢谢!

最佳答案

user.roles << role不对 user 执行验证.用户基本上不参与。所有这些都是在您的连接表中插入一条新记录。

如果你想强制一个用户只有一个角色,你有两种选择,都涉及扔掉 has_and_belongs_to_many ,你真的不应该再使用它了。 Rails 提供 has_many :through ,这一直是处理多对多关系的首选方式。

因此,第一种(我认为最好的)方法是使用 has_many/belongs_to .这就是在 Rails 中建模一对多关系的方式。应该是这么简单:

class Role
  has_many :users
end

class User
  belongs_to :role
end

第二种方法对于强制执行单个关联记录过于复杂,是创建您的连接模型,将其命名为 UserRole ,使用 has_many :through ,并在 UserRole 中执行验证.
class User
  has_many :user_roles
  has_many :roles, through: :user_roles
end

class UserRole
  belongs_to :user
  belongs_to :role

  # Validate that only one role exists for each user
  validates :user_id, uniqueness: { scope: :role_id }

  # OR, to validate at most X roles are assigned to a user
  validate :at_most_3_roles, on: :create

  def at_most_3_roles
    duplicates = UserRole.where(user_id: user_id, role_id: role_id).where('id != ?', id)
    if duplicates.count > 3
      errors.add(:base, 'A user may have at most three roles')
    end
  end
end

class Role
  has_many :user_roles
  has_many :users, through: :user_roles
end

关于ruby-on-rails - Rails 4 HABTM 自定义关联验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24559489/

相关文章:

ruby-on-rails - 在 Rails 中实现订阅 Redis pub sub 的最佳方式是什么?

php - Silex ActiveRecord 模型加载

ruby-on-rails - 在 Ruby/Rails 中处理大型数据集导入

ruby-on-rails - Gmaps4Rails 中的标记样式

mysql - has_and_belongs_to_many 权限过滤

ruby-on-rails - 如何限制 "Add new"在事件管理 ruby​​ on Rails 中仅接受 X 个嵌套对象

php - 如何解决 Laravel-5.4 多列的输入值唯一验证

javascript - 正则表达式窗口路径验证器

ruby-on-rails - Rails - 不能以字符开头或结尾的用户名

ruby-on-rails - Rails 如何获取一个对象的所有孙子