I have a model that looks something like this:
class Comment < ActiveRecord::Base
...
#allow editing comment if it is moderated and the user passed-in
#is the one that owns the comment
def can_edit?(user)
moderated? and user.Type == User and user.id == self.user_id
end
...
end
And a call in a view:
<%= link_to 'Show Comment', @comment if @comment.can_show?(current_user) %>
I need to write many such methods in many different models – sort of validation checks to see if current_user is allowed to
do something on a model.
But it feels cumbersome – especially the need to check that the passed-in user is indeed a object of type User.
What’s a clean, best-practice way to do this sort of thing? Am I on the right track? (i.e. should I be adding such methods to a model or somewhere else)
Note
I am using scoped queries to get the comments and other models, but in some cases I cannot scope the query so I have to use the
can_xxxx?methods
Ps. Is what I’m doing considered a "fat model"?
Create a
modulecontaining all the authorization methods andincludethe module to all the classes requiring authorization.Add a file called
authorization.rbtoapp/modelsdirectory.Add a file called
authorization.rbtoconfig/initializersdirectory.Now
CommentandPostmodels will have all the authorization methods.Other approach is to use your current named_scope.
Postcontroller actionsI like this approach as it uses the same logic for accessing an array of objects or a single object.
You can add the named_scope to the module to avoid repeated definitions:
Make sure to include the module in required classes as suggested earlier.