T. Cole
T. Cole

Reputation: 191

Rails - having difficulty with group, user, owner, member associations

I've looked everywhere and have been unable to find exactly what I'm looking for. I have an idea of what I need, but am unable to put 2 and 2 together.

This code isn't proper, but this is the idea:

class Group < ActiveRecord::Base
 has_one :owner, :class_name => "user"
 has_many :members, :class_name => "user"
end

class User < ActiveRecord::Base
 belongs_to :groups
 has_one :group, :class_name "user"
end

I believe I need a has_many :through association, but am unsure about how to implement it. How do I build my models/controllers/migrations in order to represent the association within the parameters above?

Upvotes: 2

Views: 1016

Answers (3)

sebsonic2o
sebsonic2o

Reputation: 356

I would suggest as well using a join table as follows:

class Membership < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

class Group < ActiveRecord::Base
  belongs_to :owner, class_name: "User"
  has_many :members, through: :memberships, source: :user
  has_many :memberships
end

class User < ActiveRecord::Base
  has_one :owned_group, foreign_key: "owner_id", class_name: "Group"
  has_many :groups, through: :memberships
  has_many :memberships
end

Migrations are as follows:

class CreateMemberships < ActiveRecord::Migration
  def change
    create_table :memberships do |t|
      t.references :user
      t.references :group

      t.timestamps null: false
    end
  end
end

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.timestamps null: false
    end
  end
end

class CreateGroups < ActiveRecord::Migration
  def change
    create_table :groups do |t|
      t.references :owner

      t.timestamps null: false
    end
  end
end

schema design

Upvotes: 2

SacWebDeveloper
SacWebDeveloper

Reputation: 2812

Modern Rails applications use has_many through: instead of HABTM.

class User < ActiveRecord::Base

  has_many :groups, through: :user_groups

end

class Group < ActiveRecord::Base

  has_one  :owner, through: :user_groups, source: :user
  has_many :members, through: :user_groups, source: :user

end

class UserGroups < ActiveRecord::Base
  validates :owner, uniqueness: true
  belongs_to :member, class_name: 'User'
  belongs_to :group
  belongs_to :owner, class_name: 'User'
end

Adding source on has_many and has_one allows you to write Group.find(id).members and Group.find(id).owner. Validate the uniqueness of a group owner on the join.

Upvotes: 2

bf34
bf34

Reputation: 294

http://guides.rubyonrails.org/association_basics.html#the-types-of-associations

The main types you could use in this case and depend on your requirements are

has_many :groups, through: join_table

where the join table would reference both the user and the group by having user_id and group_id. This allows you to have additional information related to the group membership, maybe you want a join date or a membership id or something like that.

has_and_belongs_to_many :groups

which is implemented in a similar fashion but bypassess the join model and would simply give you a list of groups/users on either side of the relationship

Polymorphic relationships wouldn't really come into play unless you were planning on having maybe different types of memberships, maybe groups, or organizations or something that would require similar, but separate database tables.

Upvotes: 1

Related Questions