7

I'm having trouble trying to understand/wrap my brain around this. I'm trying to create a relationship that allows this:

  • user can belong to many groups
  • group can have many users
  • a group has an owner which is a user
  • the group ownership can be transferable

I've got the many-to-many relationship set up, but I can't seem to understand how to set up the ownership functionality.

here is what i have so far in my models:

    class Group < ActiveRecord::Base
      has_and_belongs_to_many :users
      attr_accessible :name, :description, :isPublic, :tag_list, :owner
    end

    class User < ActiveRecord::Base
      has_and_belongs_to_many :groups
      attr_accessible :name, :description, :owner_id
    end

Any help would be greatly appreciated!!

meatherly
  • 1,741
  • 2
  • 13
  • 16

4 Answers4

14

You can set it up a couple of ways:

1) Use a join model and place a flag on the join model that specifies that the group member is an owner.

class Group < ActiveRecord::Base
  has_many :memberships
  has_many :users, through: :memberships
  attr_accessible :name, :description, :isPublic, :tag_list, :owner
end

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

  #this table has a flag called owner and thus a method called owner?
end

class User < ActiveRecord::Base
  has_many :memberships
  has_many :groups, through: :memberships
  attr_accessible :name, :description, :owner_id
end

2) Keep your existing HABTM and add another join model for tracking ownership.

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
  has_many :group_ownerships
  has_many :owners, through: :group_owernships, class_name: "User"
  attr_accessible :name, :description, :isPublic, :tag_list, :owner
end

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

class User < ActiveRecord::Base
  has_and_belongs_to_many :groups
  has_many :group_ownerships
  has_many :owned_groups, through: :group_owernships, class_name: "Group"
  attr_accessible :name, :description, :owner_id
end
Sean Hill
  • 14,978
  • 2
  • 50
  • 56
  • 1
    Dear Sean, I just wrote an advantage of what we can do(as an answer) if we have a JOIN model, i.e a LINK table. – beck03076 Mar 15 '13 at 21:51
  • 1
    The first half of this is the best answer. If you really want to only have one owner for a group, put a validation on the Membership model. This approach also lets you have multiple owners (or admins) without changing the schema. – Chris Aitchison Mar 16 '13 at 01:02
  • Thanks. Personally, I would do the first method, but I'm all about giving choices. – Sean Hill Mar 16 '13 at 01:03
  • Using the first method, I got an error 'Could not find table memberships'. How would I go about writing the db migration for membership? I could use rails generate model Membership but I'm not sure what parameters should go there. – Andy May 06 '14 at 23:26
  • 3
    You would do `rails g model Membership group:references user:references` – Sean Hill May 07 '14 at 21:38
3

I think that one solution could be to define a new belongs_to relationship from the group to the owner. So you would need to add a new user_id column in the groups table.

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
  belongs_to :owner, class_name: 'User', foreign_key: 'user_id'
  attr_accessible :name, :description, :isPublic, :tag_list, :owner
end

class User < ActiveRecord::Base
  has_and_belongs_to_many :groups
  has_many :owned_groups, class_name: 'Group', foreign_key: 'user_id'
  attr_accessible :name, :description, :owner_id
end

I think that's what you need. with a user, you can have all the groups he's a member of with user.groups, and you can have all the groups he owns user.owned_groups. With a group, you can have its owner : group.owner and all its members : group.users.

If you want to change the owner just do group.owner = new_user with new_user begin a User instance

Note that I quickly picked named for association and foreign keys, you could of course customize that.

pjam
  • 6,356
  • 5
  • 30
  • 40
0

What about the link table approach?

Because, if you have a link table to users and groups as users_groups, then you can actually store another new attribute into that table during the moment of an user and group belonging to each other.

Like when, John the user belongs to boys the group, he is naughty. When John the user belongs to engineers the group, he is smart. So in the users_groups table, I can store something like below.

Users

id | Name
1 | John
2 | Steve

Groups

id | Name
1| boys
2| doctors
3| beggars

Users_Groups

user_id | group_id | info
1       | 1        | "naughty"
1       | 2        | "wearing white coat"
1       | 3        | "broke"
2       | 1        | "liar"

Isn't this fun?. But yeah, we have to work on the Has and belongs to many relationships. But just a thought!

JUST MENTIONED THE ADVANTAGE OF HAVING A LINK TABLE. IMPLEMENTATION of that is taken care by Sean Hill in his answer.

beck03076
  • 3,268
  • 2
  • 27
  • 37
0

In your user model add a boolean field as owner, so while creating user u can assign if he is the owner or not.
So if you want to check against the group u can do it as below.

group.users.each do |u|
u.owner?
// logic goes here
end

nilay
  • 365
  • 1
  • 10