Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails / Devise: Determining in model if user is logged in

I have made an application recently which has articles, etc, with a commenting/moderation system on top. There are one of three things that happen when a user leaves a comment.

The first is if they are a registered user and logged in via Devise, their comment is flagged with a status of '2' and gets published right away. If they are an anonymous user with a previously approved comment with a matching email address, comment gets status of '1' and gets put into a moderation queue for approval. And if the user is completely brand new and their email isn't in the system, that comment gets a status of '0' and an email is sent to their inbox to click on a link to approve their email. After any of this, an appropriate notice/flash message is displayed.

I have all this working fine, but did nearly all the logic and variable definition in the controller, making the create action very fat. In the interest of learning best practices and the convention of 'fat model, skinny controller,' I am trying to move what logic I can into the Comment model, particularly the portion that figures out if they're logged in or what. So hypothetically, something like this in the model...

attr_accessor :message
before_create :poster_type

def poster_type
  if current_user
    self.status = 2
    self.message = 'Your comment has been posted.'
  elsif Comment.find_by_mail(self.mail, :conditions => { :status => [1,2]}).present?
    self.status = 1
    self.message = 'Your comment has been sent for moderation.'
  else
    self.status = 0
    self.message = 'This is a new email, please confirm...'
  end
end

Problem is, you can't use Devise's current_user method (or others like user_signed_in?, etc) in the model, apparently. Every answer I have researched on this says unhelpfully that it isn't the business of the model to access current_user values, etc.

However, I don't exactly need to give the model a user's information (as I've seen all other threads trying to do), all I need the method in the model to figure out is simply whether they're logged in or not.

In addition, if you can't use current_user (or other user detecting methods) in the model, then you would have no other choice than to define all the logic in the controller, and isn't that bad practice as well? So if it's possible, how can I do this logic in the model? Or should I simply just leave the controller fat?

like image 279
Shannon Avatar asked Jul 19 '11 13:07

Shannon


1 Answers

You cannot access the devise user or session from any model due to separation of layers. What you can do is send the the object to the model.

I've done something like your solution before and It was just a headache.

So in your create action.

def create
    if current_user
        @user.current_user(true)
    end
end

Then just send true/false to a method on the user:

def current_user(current_user)
    current_user
end

Then you can have a before_create that checks if that is true.

like image 136
thenengah Avatar answered Nov 19 '22 00:11

thenengah