What sort of business logic should go in a model?

Suppose I have a classic blog application augmented with something like restful authentication so that users must log in to create blog posts and to issue comments on other blog posts.

I would like to give a user the option of deleting blog posts, but only those that (s)he has created.

Do I put that logic in my Post model or in the controller? Or does it go in the User model? Or should it go (somehow) in the session controller? In principal, the Post model only knows about users to the extent that it belongs_to :user. It doesn’t have any notion of who is currently logged in – that’s the business of the session controller. But the user views all of the posts through the #index view of the session controller – it seems very logical to add a “Delete” link/icon next to the current user’s posts in the list.

I am curious to learn what other folks have done, and what your opinions are on this issue.

Thanks for giving me the opportunity to ask :slight_smile:

–wpd

Suppose I have a classic blog application augmented with something
like restful authentication so that users must log in to create blog
posts and to issue comments on other blog posts.

I would like to give a user the option of deleting blog posts, but
only those that (s)he has created.

Do I put that logic in my Post model or in the controller? Or does
it go in the User model? Or should it go (somehow) in the session
controller? In principal, the Post model only knows about users to
the extent that it belongs_to :user. It doesn't have any notion of
who is currently logged in -- that's the business of the session
controller. But the user views all of the posts through the #index
view of the session controller -- it seems very logical to add a
"Delete" link/icon next to the current user's posts in the list.

Post could easily have a can_delete? method that might look something
like

def can_delete?(current_user)
   user == current_user || current_user.admin?
end

Fred

Blatantly answering only the subject line:

Anything a user can do to your back-end (database, flat-files, wire APIs, etc.)...

...a unit test can do to a Model object, in generally the same way.

If, for example, your users can see a list of items, and can pick one item to operate on, then your unit tests should force your Item class to find a list of appropriate items, and should force your Item model to expose a method that operates on that item.

This rule should limit your controllers to mere patch-boards. Their only purpose is to glue this or that Model method to this or that View.

How does this answer apply to the details of your question?

Post could easily have a can_delete? method that might look something

like

def can_delete?(current_user)

user == current_user || current_user.admin?

end

Ok, that works for me. But when you do that, do you also add a parameter to the destroy method
for the model (can I do that?) that takes a current_user parameter as
well?

Fred

Blatantly answering only the subject line:

Anything a user can do to your back-end (database, flat-files, wire APIs, etc.)…

…a unit test can do to a Model object, in generally the same way.

If, for example, your users can see a list of items, and can pick one item to

operate on, then your unit tests should force your Item class to find a list of

appropriate items, and should force your Item model to expose a method that

operates on that item.

This rule should limit your controllers to mere patch-boards. Their only purpose

is to glue this or that Model method to this or that View.

How does this answer apply to the details of your question?

I’m not sure – in my case I would like users to be able to delete records from the back-end (database), but only certain users should be able to delete certain records. Are you suggesting that a good practice would be for me to define a #destroy_if_allowed method? Then my patch-board controller would call that instead of the traditional #destroy method.

Is this the common practice?

–wpd

I would define can_delete? on the user model, not the post model.

User.rb

def can_delete?(post)
   # code here
end

user.can_delete? makes more sense to me than post.can_delete?...

You could rename the method to can_be_deleted_by? for clarity though.