Requiring a would-be user to go through a sign-up process can often be too much to ask. Instead of jumping through your hoops, many people will just hit the 'back' button and continue browsing Reddit without ever discovering how cool your app is. In fact, I do it all the time.
Instead, why not treat your visitor as a valued customer with all the rights and privileges of a full-blown user from the get-go? With soft sign-ups, you can do just that.
Delayed registration, soft sign-up, lazy registration--whatever you like to call it, it has one simple purpose: to remove a barrier between your customer and your product.
But I want my users to register!
Even if you want your content to be as accessible as possible, there are still two basic reasons why you'd require registration:
- to prevent unauthorized access to private content
- to have something to silo user-created content with
The first is a users's concern; let's let them decide when to lock down their account with a password.
The second is our focus. Unless you're Wikipedia, you can't just let visitors start creating and editing content without any way to sort out who owns what. However, this is a technical constraint that can easily be overcome with soft sign-ups.
The omnipresent anonymous user
The most basic requirement for a soft sign-up is that there must be a
current_user at all times. You also want this user to be persistent (i.e., they're not someone new with every page load). The example below uses Devise, but could easily be adapted to the auth system of your choice.
[gist id=3821473 file=application_controller.rb]
There are three methods here:
anonymous_user_tokenreturns a unique identifier attached to the visitor's session. This will persist for the duration of the user's current session.
current_useroverrides the default Devise method. It first does what it normally does--returns the currently logged in user--but if one doesn't exist, it falls back to finding or creating a new AnonymousUser with the unique
authenticate_user!behaves like it normally does with Devise, except it's more lenient and allows an anonymous user.
You may choose to create another before filter method instead of overriding
authenticate_user! if you want to restrict an anonymous user in some way other than a registered user.
Another thing you may note is the AnonymousUser class, which inherits from User. This is not necessary, but just one way to differentiate anonymous and registered users. You may prefer to use a role-based system instead.
That's the meat of it. With those few lines of code, visitors should be able to start using your app like a normal, registered user.
Registering (and keeping all your work)
So now that your users have been able to start using your product right away, they've probably found out that it's really awesome and they want to become a member.
Will they get to keep all the stuff they've been working on? Of course!
From a technical perspective, this is more akin to updating their profile in order to change their email and password. But for an end user, it's magic: They get to transition into registered user-dom whenever they're ready, while keeping all the stuff there were already doing.
First, we need to tell Devise that we're going to be overriding the registration controller via routes.rb.
[gist id=3821473 file=routes.rb]
Then we need to override how Devise handles registrations with the RegistrationsController.
[gist id=3821473 file=registrations_controller.rb]
Like I said, it's basically just updating the current_user and re-signing them in. I have a little method on AnonymousUser called register to help do that:
[gist id=3821473 file=anonymous_user.rb]
You'll need to change a little view logic as well. For example, you'll want to check something like
current_user.anonymous? instead of
present? to conditionally show your "Sign in" and "Sign up" links.
That's pretty much all there is to it. With soft sign-ups, visitors can begin using your product right away. If they use your app and want to register, they can transition easily into a full user while retaining all their content.
Image credit: potential past