Problem
My User model has multiple roles (utilizing CanCan). Each role’s dashboard view is different enough to warrant a partial for each role (admins get big-picture reports of users and app activity, students get big-picture overviews of grades, current courses, and lessons to be taken).
At first I had a case statement to iterate through the views based on current_user.role
(of course, that was just temporary, even I know that!). Now, I have this:
<%= render "#{current_user.role}" %>
This doesn’t feel right. What’s the proper way to dynamically render partials (or maybe this method is perfectly fine)? Also, please mention why the proper way is best, as I want to learn from this.
Solution
You can override ActiveModel#to_partial_path
if you want – same as how you might override to_param
. See the documentation (and be sure to check the source too – they’re doing some caching that’s elided in the docs, but might be worth looking in to).
Anyway, in your case, you could likely just redefine the method on the User model like so:
# in app/models/user.rb
class User < ActiveRecord::Base
# ...
def to_partial_path
collection = ActiveSupport::Inflector.tableize(self)
"#{collection}/#{self.role}"
end
end
This way, you can use render
as you would normally. You’ll only be doing what Rails is already doing – just a little differently.