在has_many:through和has_and_belongs_to_many association

时间:2015-06-25 21:59:50

标签: ruby-on-rails ruby ruby-on-rails-4 database-design associations

我是编程新手,很难确定我需要的模型关联。我已经有两个表:组织和具有1:多关系的用户,因为组织有多个用户/成员。并非所有用户都是组织的成员,但这不是问题。

# In the organization model:
has_many :users

# In the user model:
belongs_to :organization, inverse_of: :users

# In the users migration file:
t.references :organization, index: true, foreign_key: true

我需要使用主持人功能对其进行扩展:用户可以是多个组织的主持人,组织可以有多个用户作为主持人。因此,用户和组织模型之间存在两种不同的原因(用户作为组织成员,用户作为组织的主持人;在成为主持人之前无需成员)。

我读了here关于创建关联的两种不同方法,即has_many :throughhas_and_belongs_to_many

  

最简单的经验法则是你应该设置一个has_many   :如果你需要使用关系模型,通过关系   作为一个独立的实体。如果你不需要做任何事情   关系模型,设置一个可能更简单   has_and_belongs_to_many关系(虽然你需要记住   在数据库中创建连接表)。   你应该使用has_many:through如果你需要验证,回调,   或连接模型上的额外属性。

我不确定“如果你需要将关系模型作为一个独立的实体”,那意味着什么。在我的用例中,主持人将拥有其他权利。我相信,该协会将以两种方式使用:1)显示组织的主持人,并显示用户是主持人的组织; 2)查看用户是否拥有版主权限以允许他获得这些权利。所以我不相信我需要验证(组织本身可以选择用户作为主持人)或额外的属性。我不确定回调(不确切知道它们是什么)。

简而言之,在我的用例中,两种关联形式中哪一种是最好的关联?

2 个答案:

答案 0 :(得分:2)

当人们问:

  • habtm - 只有一个联接表,例如两个ID
  • hm:t - 包含有关联接关系的元数据的联接表,例如,两个ID和其他数据,如时间,计数等。

答案 1 :(得分:2)

“如果您需要将关系模型作为独立实体使用”意味着您将能够像任何其他ActiveRecord模型一样操作关系模型,即您可以创建,保存,销毁等记录或分配各种类型关系的属性。

例如,假设用户可能与组织有不同类型的关系(例如主持人,员工,股东等)。使用:through关联,您将拥有:

class Relationship < ActiveRecord::Base
  belongs_to :user
  belongs_to :organization
end

class User < ActiveRecord::Base
  has_many :organizations, through: relationships
end

class Organization < ActiveRecord::Base
  has_many :users, through: relationships
end

# schema.rb
ActiveRecord::Schema.define(:version => 20150511223747) do
   # . . . . 
   create_table "relationships", :force => true do |t|
      t.string   "relationship_type"
      t.integer  "user_id"
      t.integer  "organization_id"
      t.datetime "created_at"
      t.datetime "updated_at"
   end
end

# things you can do: 
org = Organization.first
moderators_or_employees = org.users.where("relationship_type = 'moderator' OR relationship_type = 'employee'")

new_moderators = org.users.where("relationship_type = 'moderator' AND DATE(relationships.created_at) > '2015-01-01'")

这些是您无法使用has_and_belongs_to_many关联执行的操作,因为您无法查询关系类型或created_at。由于这些限制,我经常发现:通过关系,虽然有点复杂,但给你更多的灵活性。