I have this app where a user can write a review for a school. A user must sign in with Facebook to save a review. The problem is if a user is unsigned and writes a review, then signs in with Facebook they have to write the same review again.
I am trying to fix this by storing the review data form in sessions, but I cant quite make it work.
What is the proper rails way to do this?
ReviewForm:
<%= form_for [@school, Review.new] do |f| %>
<%= f.text_area :content %>
<% if current_user %>
<%= f.submit 'Save my review', :class => "btn" %>
<% else %>
<%= f.submit 'Save my review and sign me into facebook', :class => "btn" %>
<% end %>
<%end %>
ReviewController
class ReviewsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def create
@school = School.find(params[:school_id])
@review = @school.reviews.new(params[:review])
@review.user_id = current_user.id
if @review.save
redirect_to @review.school, notice: "Review has been created."
else
render :new
end
end
def new
@school = School.find_by_id(params[:school_id])
@review = Review.new
end
def save_review(school, review, rating)
Review.create(:content => review, :school_id => school,
:user_id => current_user, :rating => rating)
end
private
def signed_in?
!current_user.nil?
end
def signed_in_user
unless signed_in?
# Save review data into sessions
session[:school] = School.find(params[:school_id])
session[:review] = params[:review]
session[:rating] = params[:rating]
# Login the user to facebook
redirect_to "/auth/facebook"
# After login save review data for user
save_review(session[:school], session[:review], session[:rating])
end
end
end
My understanding is that it's not "The Rails Way" to store things in the session besides really tiny stuff like a user token, etc. You can read more about that idea in The Rails 3 Way by Obie Fernandez.
I would recommend that you store reviews in the database right from the start and only "surface" the review after the review has been connected to a Facebook-authenticated user. If you have any curiosities regarding how to accomplish that, I'm happy to elaborate.
Edit: here's a little sample code. First I'd take care of associating users with reviews, for "permanent" storage. You could just add a
user_id
to thereview
table, but it would probably benull
most of the time, and that seems sloppy to me:Then I'd create a
user_session_review
table with areview_id
and auser_session_token
. This is for "temporary" storage:Then when a user signs up, associate any "temporary" reviews with that user:
So in your controller, you might do
You'll of course have to read between the lines a little bit, but I think that should get you going.
Edit 2: To delete old abandoned reviews, I'd do something like this:
Then, in a cron job:
You should save the review in the create sessions action (which is not included in your question). Assuming you are using omniauth, you can add something on the action that handles the callback
I used delete so the session will be cleared of these values.
UPDATE: since you're using a session controller