Skip to content

Instantly share code, notes, and snippets.

@sj26
Created April 5, 2012 11:55
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save sj26/2310315 to your computer and use it in GitHub Desktop.
Save sj26/2310315 to your computer and use it in GitHub Desktop.
class User < ActiveRecord::Base
attr_accessible :name
has_many :admin_memberships, class_name: "Membership", conditions: {role: 'admin'}
has_many :editor_memberships, class_name: "Membership", conditions: {role: 'editor'}
def admin?
admin_memberships.exists?
end
def editor?
editor_memberships.exists?
end
end
class Group < ActiveRecord::Base
attr_accessible :name
has_many :admin_memberships, class_name: "Membership", conditions: {role: "admin"}
has_many :editor_memberships, class_name: "Membership", conditions: {role: "editor"}
has_many :admins, through: :admin_memberships, source: :user
has_many :editors, through: :editor_memberships, source: :user
end
class Membership < ActiveRecord::Base
attr_accessible :role
belongs_to :user
belongs_to :group
end
sam = User.new name: "Sam"
# => #<User id: 1, name: "Sam", created_at: "2012-04-05 11:45:54", updated_at: "2012-04-05 11:45:54">
rainbows = Group.new name: "Rainbows"
# => #<Group id: 1, name: "Rainbows", created_at: "2012-04-05 11:46:06", updated_at: "2012-04-05 11:46:06">
rainbows.admins << sam
# => [#<User id: 1, name: "Sam", created_at: "2012-04-05 11:45:54", updated_at: "2012-04-05 11:45:54">]
rainbows.admin_memberships
# => [#<Membership id: 2, user_id: 1, group_id: 1, role: "admin", created_at: "2012-04-05 11:48:58", updated_at: "2012-04-05 11:48:58">]
user.admin?
# Membership Exists (0.3ms) SELECT 1 FROM "memberships" WHERE "memberships"."user_id" = 1 AND "memberships"."role" = 'admin' LIMIT 1
# => true
@LukasSkywalker
Copy link

You just helped me a great deal to simplify my code (from ~10 lines of very cluttered and ununderstandable has_many definitions to 2 very clean lines).
But I have a question where you can maybe help: would it be possible to set the role attribute also when calling build on the has_many relation?
I would like to be able to do this:

rainbows = Group.new name: "Rainbows"
rainbows.admins.build(name: "Sam")

@ccmcbeck
Copy link

ccmcbeck commented Feb 4, 2014

Very nice. Note that the conditions syntax is very different in Rails 4

http://guides.rubyonrails.org/association_basics.html#the-has-many-association

And if you (like me) are tempted to use Rails 4.1 enums, the syntax is a bit more interesting pending the outcome of these:

rails/rails#13918
rails/rails#13433

In my case, I have the role in the Membership table (so Users can have a different role per Group) and here is what I'm using in gem 'rails', '4.1.0.beta1'

class Group
  has_many :admins, -> { where role: Membership::ROLE[:admin] }, class_name: 'Membership'

Here is the enum declaration

  enum role: {
    reader:   10,
    editor:   20,
    admin:    30
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment