Reputation: 221
We have two classes - User and Group
class User < ActiveRecord::Base
# Group Memberships
has_many :memberships, dependent: :destroy
has_many :groups, through: :memberships
end
class Group < ActiveRecord::Base
# Group has a property called 'name'
# Group members
has_many :memberships, dependent: :destroy
has_many :members, through: :memberships, source: :user
end
This is working just fine and we can create Groups and add Users to those groups.
What's the cleanest way to detect user's group membership? Something like: user.reviewer? where reviewer is the name of a group, without explicitly defining those methods. How can this be done using delegation?
We already have it working, albeit in an ugly way. Would appreciate the most elegant (and shortest) solution.
PS: We're on Rails 4.2.7
Upvotes: 2
Views: 856
Reputation: 36860
this is a way you can get my_user.reviewer?
to work... add the following to your User class:
def method_missing(name, *args, &block)
if name.to_s.end_with?('?')
group_name = name.to_s.chomp('?')
if Group.find_by(name: group_name)
return groups.pluck(:name).include?(group_name) ? true : false
end
end
super
end
Upvotes: 0
Reputation: 36860
Last time I looked delegate
wasn't supported for has_many
relationships.
The simplest way is to define a member_of?
method. I'm doing it here with a private method and using a memoized list of group names.
class User < ActiveRecord::Base
# Group Memberships
has_many :memberships, dependent: :destroy
has_many :groups, through: :memberships
delegate :name to :groups
def member_of?(group_name)
group_names.include? group_name.to_s
end
private
def group_names
@group_names ||= groups.pluck(:name)
end
end
Use it like...
my_user.member_of?(:reviewers)
If you keep group names in the singular, you can still do the more readable pluralize call...
my_user.member_of?(:reviewers)
And just reference the argument as group_name.to_s.singularize
in the method.
Note that you can support my_user.reviewer?
by adding a def method_missing
call, but you'd have to
check that the method is a valid group name and then check whether the user is a member of the group, otherwise raise the missing method error (i.e. super
to the inherited method_missing
). See here for a simple explanation of how method_missing
can be used. https://rosettacode.org/wiki/Respond_to_an_unknown_method_call#Ruby
Upvotes: 1