如何实现 has_many :through 关联两种方式?

Posted

技术标签:

【中文标题】如何实现 has_many :through 关联两种方式?【英文标题】:How can I implement a has_many :through association two ways? 【发布时间】:2018-08-21 00:36:54 【问题描述】:

我有一个属性模型和一个用户模型。

具有“admin”角色的用户(由 users 表中的一列表示)可以具有许多属性。

具有“guest”角色的用户也可以属于某个属性,这使他们可以访问该属性。

我应该如何在 Rails 中做到这一点?

【问题讨论】:

【参考方案1】:

授权表 -> user_id, property_id

class Authorization < ActiveRecord::Base
    belongs_to :user
    belongs_to :property
end 

class User < ActiveRecord::Base
    has_many :authorizations
    has_many :properties, through: :authorizations
end

class Property < ActiveRecord::Base
    has_many :authorizations
    has_many :users, through: :authorizations
end

那你就可以User.find(id).properties

【讨论】:

【参考方案2】:

首先,您的模型UserProperty 之间需要has_many :through 关联。因此,创建一个新表 properties_users,其中包含列 user_idpropety_id。并对模型进行以下更改:

class PropertiesUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :property
end 

class User < ActiveRecord::Base
  has_many :properties_users
  has_many :properties, through: :properties_users
end

class Property < ActiveRecord::Base
  has_many :properties_users
  has_many :users, through: :properties_users
end

现在,我们需要确保来宾用户没有多个属性。为此,我们可以向模型 PropertiesUser 添加验证,如下所示:

class PropertiesUser < ActiveRecord::Base
  validate :validate_property_count_for_guest

  private

  def validate_property_count_for_guest
    return unless user && user.guest?

    if user.properties.not(id: self.id).count >= 1
      self.errors.add(:base, 'guest user cannot have more than one properties')
    end
  end
end 

class User < ActiveRecord::Base
  def guest?
    # return `true` if user is guest
  end
end

最后,要访问访客用户的属性,在模型User 中定义一个专用方法:

class User < ActiveRecord::Base
  def property
    # Raise error if `property` is called on non-guest users
    raise 'user has multiple properties' unless guest?

    properties.first
  end
end

现在,您可以通过运行获取来宾用户的属性:

user = User.first

user.guest?
 => true

user.property
 => <#Property 1>    # A record of Property

【讨论】:

以上是关于如何实现 has_many :through 关联两种方式?的主要内容,如果未能解决你的问题,请参考以下文章

使用 `:has_many :through` 记录关联处理复选框表单

ActiveRecord、has_many :through 和多态关联

has_and_belongs_to_many 或多态 has_many :through?

使用 has_many 时如何创建关联模型的实例:通过关联

如何通过 has_many 关联在 FactoryBot 中设置工厂

如何实现has_many:通过与Mongoid和mongodb的关系?