Skip to content

Instantly share code, notes, and snippets.

@tbeauvais
Created March 6, 2011 17:21
Show Gist options
  • Save tbeauvais/857422 to your computer and use it in GitHub Desktop.
Save tbeauvais/857422 to your computer and use it in GitHub Desktop.
Rails Group/User relationship using join table - has_many :users, :through => :members
#############################################################################
# Migration file to create index so you don't get duplicate users for a group
#############################################################################
class AddMembersUniquenessIndex < ActiveRecord::Migration
def self.up
add_index :group_members, [:group_id,:user_id], :unique => true
end
def self.down
remove_index :group_members, [:group_id,:user_id]
end
end
# Users and Groups that were previously manually created.....
# Here's a dump of them:
ruby-1.9.2-p0 > Group.all
=> [#<Group id: 1, name: "Group 1", description: "Group One", created_at: "2011-02-27 18:55:01", updated_at: "2011-02-27 18:55:01">,
#<Group id: 2, name: "Group 2", description: "Group Two", created_at: "2011-02-27 18:55:39", updated_at: "2011-02-27 18:55:39">]
ruby-1.9.2-p0 > User.all
=> [#<User id: 1, name: "User 1", email: "user1@test.com", created_at: "2011-02-27 18:39:58", updated_at: "2011-02-27 18:39:58">,
#<User id: 2, name: "User 2", email: "user2@test.com", created_at: "2011-02-27 18:40:20", updated_at: "2011-02-27 18:40:20">]
# Get the first Group
ruby-1.9.2-p0 > g = Group.first
=> #<Group id: 1, name: "Group 1", description: "Group One", created_at: "2011-02-27 18:55:01", updated_at: "2011-02-27 18:55:01">
# List its current Users which is none
ruby-1.9.2-p0 > g.users
=> []
####################################################################################################################
# Add association of existing Group and User through the Group members join table
####################################################################################################################
ruby-1.9.2-p0 > u = g.members.build(:user_id => 1)
=> #<Member id: nil, user_id: 1, group_id: 1, created_at: nil, updated_at: nil>
# Save the Member
ruby-1.9.2-p0 > u.save
=> true
# Reload the Group
ruby-1.9.2-p0 > g = Group.first
=> #<Group id: 1, name: "Group 1", description: "Group One", created_at: "2011-02-27 18:55:01", updated_at: "2011-02-27 18:55:01">
# List its current Users which is one
ruby-1.9.2-p0 > g.users
=> [#<User id: 1, name: "User 1", email: "user1@test.com", created_at: "2011-02-27 18:39:58", updated_at: "2011-02-27 18:39:58">]
####################################################################################################################
# Here's a way to create a new User and add to Group through the members join table. Note save not called
####################################################################################################################
ruby-1.9.2-p0 > u = g.users.create(:name => "User 3", :email => "user3@test.com")
=> #<User id: 3, name: "User 3", email: "user3@test.com", created_at: "2011-02-27 20:35:37", updated_at: "2011-02-27 20:35:37">
ruby-1.9.2-p0 > g.users
=> [#<User id: 1, name: "User 1", email: "user1@test.com", created_at: "2011-02-27 18:39:58", updated_at: "2011-02-27 18:39:58">, #<User id: 3, name: "User 3", email: "user3@test.com", created_at: "2011-02-27 20:35:37", updated_at: "2011-02-27 20:35:37">]
ruby-1.9.2-p0 >
####################################################################################################################
# Create a new User and add to Group through the members join table. Note you must save the Group to update users and members tables
####################################################################################################################
ruby-1.9.2-p0 > u = g.users.build(:name => "User 4", :email => "user4@test.com")
=> #<User id: nil, name: "User 4", email: "user4@test.com", created_at: nil, updated_at: nil>
ruby-1.9.2-p0 > g.save
=> true
####################################################################################################################
# Destroy of User also removes Groups member relationship (User - has_many :group_members, :dependent => :destroy)
####################################################################################################################
# Current list of Users for specified Group
ruby-1.9.2-p0 > g = Group.first
ruby-1.9.2-p0 > g.users
=> [#<User id: 1, name: "User 1", email: "user1@test.com", created_at: "2011-02-27 18:39:58", updated_at: "2011-02-27 18:39:58">,
#<User id: 3, name: "User 3", email: "user3@test.com", created_at: "2011-02-27 20:35:37", updated_at: "2011-02-27 20:35:37">,
#<User id: 4, name: "User 4", email: "user4@test.com", created_at: "2011-02-27 20:39:08", updated_at: "2011-02-27 20:39:08">]
# Find and destroy user
ruby-1.9.2-p0 > u = User.find(4)
ruby-1.9.2-p0 > u.destroy
# View updated Group/User relationship
ruby-1.9.2-p0 > g = Group.first
=> #<Group id: 1, name: "Group 1", description: "Group One", created_at: "2011-02-27 18:55:01", updated_at: "2011-02-27 18:55:01">
ruby-1.9.2-p0 > g.users
=> [#<User id: 1, name: "User 1", email: "user1@test.com", created_at: "2011-02-27 18:39:58", updated_at: "2011-02-27 18:39:58">,
#<User id: 3, name: "User 3", email: "user3@test.com", created_at: "2011-02-27 20:35:37", updated_at: "2011-02-27 20:35:37">]
# == Schema Information
#
# Table name: groups
#
# id :integer not null, primary key
# name :string(255)
# description :string(255)
# created_at :datetime
# updated_at :datetime
#
class Group < ActiveRecord::Base
# destroy the relationship if group is deleted
has_many :members, :dependent => :destroy
# has many through members join table
has_many :users, :through => :members
end
# == Schema Information
#
# Table name: members
#
# id :integer not null, primary key
# user_id :integer
# group_id :integer
# created_at :datetime
# updated_at :datetime
#
class Member < ActiveRecord::Base
belongs_to :group
belongs_to :user
validates :user_id, :presence => true
validates :group_id, :presence => true
# avoid in memory duplicates. You will also need add unique index to db
validates :user_id, :uniqueness => {:scope => [:user_id, :group_id]}
end
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# name :string(255)
# email :string(255)
# created_at :datetime
# updated_at :datetime
#
class User < ActiveRecord::Base
# destroy the user in the members list if the user is deleted
has_many :members, :dependent => :destroy
# has many through members join table
has_many :groups, :through => :members
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment