views:

45

answers:

1

This seems to keep coming up for me on various projects and I'm wondering if anyone out there has a great solution:

We have a Rails app with Authlogic authentication. Initially, there's a nice, clean, RESTful ListingsController that requires a user to be logged in before they can post/create:

before_filter :require_user, :only => [ :new, :create]

However, after seeing this in action we decide we need to try out a different flow where unregistered users can fill out the form for the Listing first and then be prompted to register/login. If they abandon registration, we don't need to create the Listing. If they authenticate, we want to wire up the Listing with the current_user as we would normally.

A couple possible snags:

  1. The new Listing form allows users to upload files that we store with Paperclip.
  2. Authentication may happen through a series of redirects for facebook or twitter.

I feel like this authenticate post-creation scenario is a common enough that there would be some resources on standard methods for attacking it, but I haven't really found much. Anyone have a good solution or resource for this?

Thanks!

+3  A: 

One solution is to generate a unique token and store it in your model (say Listing.pending_id), then write the same token to a cookie. Later, when the client is first authenticated, you check for a 'pending_id' cookie and link it to the relevant listing if found.

You'd have to schedule a task to remove any unfinished listings older than (x), and make sure that any pending Listings were excluded from normal operations (searching, listing, etc). Depending on your application you might be better off creating a separate PendingListing model and database table.

One downside with this approach is that the listing would not be recovered if added on one computer/browser, but authenticated on another.

Daniel Mendel
Thanks for the answer. So I'll need to do this for several models and I'd like to avoid duplicating all those tables in the DB. I'd like a solution I can streamline for all models/controllers that need it. I was pondering something like the pending_id solution...I suppose the user_id would need to be made nullable or there could be an 'anonymous' user that the pending records would reference. Then, it's mostly a matter of filtering out pending listings. I'd use default_scope to filter them out, but it's really given me headaches in the past...
njorden
Well, if the #create procedure on your models tends to stick with the Model.create(params[:model]) approach, then you could create a PendingAsset model with pending_params, pending_id and all the possible paperclip attachments / other abstracted behaviors, stash your params[:model] hash as JSON in PendingAsset.pending_params and when the user is later authenticated, pull the params out and build the real instance. In this case you wouldn't need to bother with default_scope. For bonus DRYing, you could add helpers to deal with stashing and retrieving pending models.
Daniel Mendel
I like it...maybe it could even be abstracted to the point of being a useful plugin/gem for future projects. I'll give it a shot and see how it looks. Thanks!
njorden
That sounds great, happy coding! Be sure to post any future information (or github links!) back here if you do.
Daniel Mendel