# How to render partials dynamically in Rails 3

Here's a simple one for you guys. 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 provide why the proper way is best, as I want to learn from this. Thanks.

-

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.

-
Thanks Flambino. I'm wondering though, what benefits would this have over the method I'm using currently? It's a bit more verbose and, to me at least, the other method seems more readable. Also, I'm guessing from the code that I'd call this with something like render user and to_partial_path would select the correct partial, right? –  GorrillaMcD Nov 14 '12 at 21:59
@GorrillaMcD it's (negligibly) more verbose, but arguably more correct, since it's "the Rails Way" to have a model define its partial path. Besides, role is defined on the model, so why shouldn't the partial path be when it's dependent on the role? But really, there aren't many alternatives: The partial path is an expression; it's either inline in the view, or in a method. Your code uses the former, this uses the latter (which can be anywhere, but this is in keeping with conventions). Not much else you can do. –  Flambino Nov 14 '12 at 22:19
Thanks for the explanation. I was just curious as to why it's better that's all. Thanks again. –  GorrillaMcD Nov 14 '12 at 22:28