article

article

Some sites allow guest users to still interact with it. Kandid.ly allows you to like a photo, for example. CodePen and JSFiddle allow you to create pieces of code without having an account. Devise by default doesn’t have anything in it for having guest users on your site. Adding this functionality is not a difficult thing to do.

In fact, the Devise wiki has an article on how to do this exact thing! However, that article talks about how to persist that user only for the current session. This session goes away when the user closes their browser. What if we want to persist those sessions for longer than the current session? We use a cookie!

The Code

moduleAuthorizationHelper# if user is logged in, return current_user, else return guest_userdefcurrent_or_guest_userifcurrent_userifcookies.signed[:guest_user_email]logging_inguest_user.deletecookies.delete:guest_user_emailendcurrent_userelseguest_userendend# find guest_user object associated with the current session,# creating one as neededdefguest_user# Cache the value the first time it's gotten.@cached_guest_user||=User.find_by!(email:(cookies.permanent.signed[:guest_user_email]||=create_guest_user.email))# if cookies.signed[:guest_user_email] invalidrescueActiveRecord::RecordNotFound#cookies.delete:guest_user_emailguest_userendprivate# called (once) when the user logs in, insert any code your application needs# to hand off from guest_user to current_user.deflogging_in# put all your processing for transferring# from a guest user to a registered user# i.e. update votes, update comments, etc.end# creates guest user by adding a record to the DB# with a guest name and emaildefcreate_guest_useru=User.create(:first_name=>"guest",:email=>"guest_#{Time.now.to_i}#{rand(99)}@example.com")u.skip_confirmation!u.save!(:validate=>false)uendend

If you put this in the app/helpers, the method current_or_guest_user will be available in your views. If you want to use it in your controller, you need to include the module in your application controller like the code below.

I tried to comment the code to explain it a bit. Here’s a quick explanation of whats going on. current_or_guest_user will check if current_user exists. If not, it fires the guest_user method. This method checks if the user has been cached on the controller yet. If so, it returns that. If not, it gets the user email from a signed cookie. If the cookie doesn’t exist, then we create a new user using the create_guest_user and save their email in the cookie. Then we cache that user in case we try to get the guest user again in this request.

If the user is signed in, then we check if the cookie exists. If not, we just return the current user. If the cookie does exist, it fires the logging_in method, deletes the guest user entry in the database, deletes the cookie, and then returns the current user. The logging_in method is an important one. This is where you write your logic to transfer all of the guest user values over to the currently logged in user. For example, if the guest user had liked a bunch of photos on your site, you would want to move all those likes to the current user. It’s just that easy!

Wrapping Up

Adding guest users can be very simple using the Devise gem for Rails. The code Devise gives on its wiki is good, but their implementation only allows for same session persistence. Sometimes we need a bit more! Let me know what you think in the comments!