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.
1 Answer 1
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.
-
\$\begingroup\$ 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
andto_partial_path
would select the correct partial, right? \$\endgroup\$GorrillaMcD– GorrillaMcD2012年11月14日 21:59:44 +00:00Commented Nov 14, 2012 at 21:59 -
\$\begingroup\$ @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. \$\endgroup\$Flambino– Flambino2012年11月14日 22:19:11 +00:00Commented Nov 14, 2012 at 22:19
-
\$\begingroup\$ Thanks for the explanation. I was just curious as to why it's better that's all. Thanks again. \$\endgroup\$GorrillaMcD– GorrillaMcD2012年11月14日 22:28:47 +00:00Commented Nov 14, 2012 at 22:28