Created
March 11, 2012 21:48
-
-
Save jerhinesmith/2018326 to your computer and use it in GitHub Desktop.
Simple has_many :through
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
########### | |
# Classes # | |
########### | |
class Group < ActiveRecord::Base | |
has_many :memberships, | |
:class_name => 'GroupUser' | |
has_many :users, | |
:through => :memberships, | |
:source => :user | |
has_many :owners, | |
:through => :memberships, | |
:source => :user, | |
:conditions => {'groups_users.role' => GroupUser::OWNER_ROLE} | |
has_many :newbies, | |
:through => :memberships, | |
:source => :user, | |
:conditions => {'groups_users.role' => GroupUser::NEWBIE_ROLE} | |
end | |
class User < ActiveRecord::Base | |
has_many :group_memberships, | |
:class_name => 'GroupUser', | |
:dependent => :destroy | |
has_many :groups, | |
:through => :group_memberships | |
end | |
class GroupUser < ActiveRecord::Base | |
OWNER_ROLE = 'owner' | |
NEWBIE_ROLE = 'newbie' | |
belongs_to :group | |
belongs_to :user | |
end | |
######## | |
# So, I want a "group" to always have an owner, here's how I'm doing it now, | |
# I'm not enamored of this approach | |
######## | |
# Add an attr_accessor and a callback to the Group class | |
class Group < ActiveRecord::Base | |
# Same shit as above | |
# New stuff | |
attr_accessor :created_by | |
after_create :set_owner | |
private | |
def after_create | |
memberships.create(:user => created_by) do |m| | |
m.role = GroupUser::OWNER_ROLE | |
end | |
end | |
end | |
# For Newbies, the shit is a little trickier, because I want to do | |
# things like validate roles for adding newbies, send invitation | |
# emails, etc. So, instead of trying to do all of that shit in | |
# the join model, I created a new class | |
class GroupNewbie | |
extend ActiveModel::Callbacks | |
include ActiveModel::Validations | |
# Attributes | |
attr_accessor :group_id, :created_by, :email, :user, :group | |
# Bunch of validations | |
# Bunch of callbacks | |
def save | |
_run_create_callbacks do | |
GroupUser.create(:user => user, :group => group) do |gu| | |
gu.role = GroupUser::NEWBIE_ROLE | |
end | |
end if valid? | |
end | |
end | |
# Then, in the controller, I can just do: | |
newb = GroupNewbie.new(:group_id => 1, :created_by => current_user, :email => '[email protected]') | |
if newb.save | |
# blah | |
else | |
# worse blah | |
end | |
# So, that's where I'm at now. What I'd like to do... what feels most "Rails-ish" | |
# is this: | |
# Adding a newbie | |
# This does create the GroupUser record, but it doesn't populate the 'role' attribute | |
group = Group.find(params[:id]) | |
group.newbies << User.find_by_email('[email protected]') | |
# Adding a new group | |
# This creates the Group record, but does NOT create the GroupUser record. Leading to | |
# the code mentioned above | |
group = current_user.groups.build(params[:group]) | |
group.save | |
# What do you think? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment