0

私は、ユーザーが学校のレビューを書くことができるこのアプリを持っています。レビューを保存するには、ユーザーはFacebookでサインインする必要があります。問題は、ユーザーが署名されておらず、レビューを書き込んだ後、Facebookでサインインした場合、同じレビューを再度書き込む必要があることです。

レビューデータフォームをセッションに保存してこれを修正しようとしていますが、うまく機能させることができません。

これを行うための適切なレールの方法は何ですか?

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
4

2 に答える 2

3

私の理解では、ユーザートークンなどの非常に小さなもの以外に、セッションに物を保存するのは「The Rails Way」ではありません。そのアイデアの詳細については、ObieFernandezによるTheRails3Wayを参照してください。

レビューを最初からデータベースに保存し、レビューがFacebook認証ユーザーに接続された後にのみレビューを「表示」することをお勧めします。それを達成する方法について何か興味があれば、私は詳しく説明させていただきます。

編集:ここに小さなサンプルコードがあります。まず、「永続的な」ストレージのために、ユーザーとレビューの関連付けを行います。user_idテーブルにaを追加することもできreviewますが、それはおそらくnullほとんどの場合であり、それは私にはだらしのないようです。

$ rails g model UserReview review_id:references, user_id:references

次に、とを使用してテーブルを作成しuser_session_reviewます。これは「一時的な」ストレージ用です。review_iduser_session_token

$ rails g model UserSessionReview review_id:integer, user_session_token:string

次に、ユーザーがサインアップしたら、「一時的な」レビューをそのユーザーに関連付けます。

class User
  has_many :user_reviews
  has_many :reviews, through: :user_reviews
  has_many :user_session_reviews

  def associate_reviews_from_token(user_session_token)
    temp_reviews = UserSessionReview.find_all_by_user_session_token(user_session_token)
    temp_reviews.each do |temp_review|
      user_reviews.create!(review_id: temp_review.review_id)
      temp_review.destroy
    end
  end
end

だからあなたのコントローラーでは、あなたはするかもしれません

class UsersController < ApplicationController
  def create
    # some stuff
    @user.associate_reviews_from_token(cookies[:user_session_token])
  end
end

もちろん、行間を少し読む必要がありますが、それでうまくいくはずです。

編集2:古い放棄されたレビューを削除するには、次のようにします。

class UserSessionReview
  scope :old, -> { where('created_at < ?', Time.zone.now - 1.month) }
end

次に、cronジョブで:

UserSessionReview.old.destroy_all
于 2013-02-27T20:06:16.930 に答える
2

レビューはセッションの作成アクション(質問には含まれていません)に保存する必要があります。omn​​iauthを使用していると仮定すると、コールバックを処理するアクションに何かを追加できます

# review controller
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"   
  end
end

# callback to login the user
def handle_callback
  # do your thing here to login the user
  # once you have the user logged in
  if signed_in?
    if session[:school] && session[:review] && session[:rating] # or just 1 check
      Review.create(
        content: session.delete(:review),
        school_id: session.delete(:school), 
        user_id: current_user.id,
        rating: session.delete(:rating)
      )
      #redirect_to somewhere
    end
  end
end

削除を使用したので、セッションからこれらの値がクリアされます。

更新:セッションコントローラーを使用しているため

class SessionsController < ApplicationController
  def create
    if user = User.from_omniauth(env["omniauth.auth"])
      session[:user_id] = user.id 

      if session[:school] && session[:review] && session[:rating] # or just 1 check
        review = Review.new
        review.content = session.delete(:review)
        review.school_id = session.delete(:school)
        review.user_id = user.id
        review.rating = session.delete(:rating)
        review.save
      end
    end

    redirect_to :back
  end
于 2013-02-28T09:09:17.170 に答える