I'm experimenting in building a roles-based data structure in Rails using Concerns with role-specific methods. I've explored other solutions, like STI, polymorphic associations, but opted to try this method.
All attributes depicted are stored in one table, users.
module Client
extend ActiveSupport::Concern
def self.extended(target)
target.class_eval do
validates :emergency_contact, presence: true
end
end
end
module Doctor
def self.extended(target)
target.class_eval do
validates :credentials, presence: true
end
end
end
class User < ApplicationRecord
validates :role, allow_blank: true, inclusion: { in: roles }
validates :first_name, presence: true
validates :last_name, presence: true
validates :email, presence: true
after_initialize { extend_role }
# Extend self with role-appropriate Concern
def extend_role
extend role.camelize.constantize if role
end
def role=(role)
super(role)
extend_role
end
end
My challenge is during the changing of a role, specifically, what can be done (if anything) to negate the previous role's Concern having extended the User?
Each user will have 1 role, so having the Client and Doctor concerns both mixed into the User would not be appropriate (at this time, at least).
In an ideal solution, the User instance would morph with the role change and retain all changed attributes.
So, calling this:
user.update_attributes({ first_name: 'Wily', last_name: 'McDoc', role: 'doctor' })
...would first handle the role change and then update the attributes.