2016-03-07 9 views
0

Я пытаюсь установить полиморфное отношение has-many-through с ActiveRecord. Вот конечная цель:Полиморфные отношения has-many-through в Rails

  • Пользователи может принадлежать многие организациям и многим командам
  • организация много пользователей и много команд
  • команда много пользователей и принадлежат к организации

Я пытаюсь использовать has-many-through вместо has-and-belongs-to-many, так как мне нужно связать некоторую информацию alon g с отношениями (например, роль пользователя в организации или команде), поэтому я сделал таблицу соединений Членство.

Как бы это реализовать?

ответ

2

Я хотел бы разработать схему так: enter image description here

  • Organization имеет много Team
  • Team имеет много TeamMember
  • User имеет много TeamMember
  • TeamMember принадлежит User и Team

модели будут:

organization.rb

class Organization < ActiveRecord::Base 
    has_many :teams 
    has_many :team_members, through: :teams 
    has_many :users, through: :team_members 
end 

team.rb

class Team < ActiveRecord::Base 
    belongs_to :organization # fk: organization_id 
    has_many :team_members 
    has_many :users, through: :team_members 
end 

user.rb

class User < ActiveRecord::Base 
    has_many :team_members 
    has_many :teams, through: :team_members 
    has_many :organizations, though: :teams 
end 

team_member.гь

class TeamMember < ActiveRecord::Base 
    belongs_to :team  # fk: team_id 
    belongs_to :user  # fk: user_id 
    attr_accessible :role # role in team 
end 

Итак, сравните с вашими требованиями:

Пользователи могут принадлежать многим организациям и многие команды

=> Окей

организации имеют много пользователей и многие другие команды

=> Окей

Команда имеет много пользователей и принадлежит организации

=> Хорошо

Btw, мы не используем любые полиморфные здесь, и TeamMember обозначает Membership в вашей ранней идее!

1

Для полиморфной ассоциации,

class User 
    has_many :memberships 
end 

class Team 
    belongs_to :organization 
    has_many :memberships, :as => :membershipable #you decide the name 
end 

class Organization 
    has_many :memberships, :as => :membershipable 
    has_many :teams 
end 

class Membership 
    belongs_to :user 
    belongs_to :membershipable, polymorphic: true 
end 

Обратите внимание, что User косвенно связан с Team и Organization, и что каждый вызов должен пройти через Membership.

0

В моих проектах я использую класс Relationship (в драгоценности, которую я назвал ActsAsRelatingTo) в качестве модели объединения. Это выглядит примерно так:

# == Schema Information 
# 
# Table name: acts_as_relating_to_relationships 
# 
# id     :integer   not null, primary key 
# owner_id   :integer 
# owner_type   :string 
# in_relation_to_id :integer 
# in_relation_to_type :string 
# created_at   :datetime   not null 
# updated_at   :datetime   not null 
# 

module ActsAsRelatingTo 
    class Relationship < ActiveRecord::Base 

     validates :owner_id,     presence: true 
     validates :owner_type,    presence: true 
     validates :in_relation_to_id,   presence: true 
     validates :in_relation_to_type,  presence: true 

     belongs_to :owner,     polymorphic: true 
     belongs_to :in_relation_to,   polymorphic: true 

    end 
end 

Таким образом, в вашей User модели, вы могли бы сказать что-то вроде:

class User < ActiveRecord::Base 

    has_many :owned_relationships, 
     as: :owner, 
     class_name: "ActsAsRelatingTo::Relationship", 
     dependent: :destroy 

    has_many :organizations_i_relate_to, 
     through: :owned_relationships, 
     source: :in_relation_to, 
     source_type: "Organization" 

    ... 

    end 

Я считаю, что вы можете быть в состоянии оставить source_type аргумент от момента вступил класса (Organization) можно сделать из :organizations. Часто я присоединяюсь к моделям, где имя класса не может быть выведено из имени отношения, и в этом случае я включаю аргумент source_type.

С этим можно сказать user.organizations_i_relate_to. Вы можете сделать то же самое для отношений между любым набором классов.

Вы также мог бы сказать в своем классе Organization:

class Organization < ActiveRecord::Base 

    has_many :referencing_relationships, 
     as: :in_relation_to, 
     class_name: "ActsAsRelatingTo::Relationship", 
     dependent: :destroy 

    has_many :users_that_relate_to_me, 
     through: :referencing_relationships, 
     source: :owner, 
     source_type: "User" 

Так что можно сказать, что organization.users_that_relate_to_me.

Я устал от того, чтобы сделать все настройки, так что в моей жемчужине я создал acts_as_relating_to метод, так что я могу сделать что-то вроде:

class User < ActiveRecord::Base 
    acts_as_relating_to :organizations, :teams 
    ... 
end 

и

class Organization < ActiveRecord::Base 
    acts_as_relating_to :users, :organizations 
    ... 
end 

и

class Team < ActiveRecord::Base 
    acts_as_relating_to :organizations, :users 
    ... 
end 

и все полиморфные ассоциации и методы устанавливаются для меня «автоматически».

Извините за длинный ответ. Надеюсь, вы найдете в нем что-то полезное.

Смежные вопросы