2

ユーザーがログインする前に投稿を作成できるコントローラー PostsController があります。しかし、それを保存するには、ユーザーは Omniauth を使用してログインする必要があります。

PostsController には、次のものがあります。

class PostsController < ApplicationController
  before_filter :authenticate_user_by_service, :only => :create
  def create
    ...
  end

private
  def authenticate_user_by_service
    redirect_to user_omniauth_authorize_path(:facebook)
  end

今、私は Facebook からのコールバックを処理する別のコントローラーを持っています。これは ServicesController と呼ばれます。

class ServicesController < ApplicationController
  def create
    auth = request.env["omniauth.auth"]
    ... authentication logic here ...
    sign_in(:user, service.user)
  end
  method_alias: :facebook, :create

通常、認証のために、サインインした後、:back にリダイレクトします。

ただし、services#createここでは before_filter として使用されます。この場合、 Posts#create に戻すにはどうすればよいですか?

更新:別のメソッドを参照しているときにフィルターチェーンが中断されているという警告が表示されました

Started POST "/posts" for 127.0.0.1 at 2013-02-26 23:47:41 -0500
Processing by PostsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"H0as8=", "post"=>{"post"=>"bla bla"}, "commit"=>"Create Post"}
Redirected to http://localhost:3000/users/auth/facebook
Filter chain halted as :authenticate_user_by_service rendered or redirected
4

1 に答える 1

1

あなたはこれに間違って近づいています。あなたはログインを処理しており、同じステップで誰かがログインしているかどうかを確認しています。

すべてのサインアップ/ログイン/ログアウト ロジックを処理するために sessions_controller を使用することを検討してください。次に例を示します。

class SessionsController < ApplicationController
  def new # this will be /login
    session[:return_to] = params[:returnto] unless params[:returnto].nil?
    redirect_to "/auth/facebook"
  end

  def create # this will be the callback after the user is authenticated
    auth_token = request.env["omniauth.auth"]["credentials"]["token"]
    # you'll need to write this based on your app's requirement. 
    # Find a user or create one if he doesn't exist yet.
    user = User.find_or_create_authenticated_user(auth_token) 

    if user.present?
      session[:user_id] = user.id # this stores the current user's id in your session and lets Rails remember him for you.
      redirect_to return_or(products_url) # see below for the usage of return_or
      return
    end

    redirect_to root_url, alert: 'User not found or invalid'
  end

  def destroy # /logout
    session[:user_id] = nil
    redirect_to root_url
  end
end


#routes.rb
match '/logout' => 'sessions#destroy', :as => :logout
match '/login' => 'sessions#new', :as => :login
match '/auth/facebook/callback' => 'sessions#create'

次に、ApplicationControllerいくつかのヘルパー メソッドを設定します。

class ApplicationController < ActionController::Base

  protected  
  # Use this in your views and controllers to get 
  # a handle of the user that is currently logged in. 
  # it will return nil if there is no user logged in.
  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
  helper_method :current_user

  # Use this to check wether a user is logged in. 
  # returns true if there is a user, false otherwise.
  def logged_in?
    !current_user.nil?
  end
  helper_method :logged_in?

  # Block access to controllers or actions based on 
  # wether there's a user or not.
  def require_login
    unless logged_in?
      # if we need the user to log in, we send him on his way
      # but send him back to the current page afterwards. 
      session[:return_to] = request.fullpath
      redirect_to root_url(subdomain: false), :alert => "Please login"
    end
  end

  # When a user is not logged in, but you send him to log in,
  # you can force him to return to the url he was in or if nothing
  # was set go to a standard path. 
  # See this being set up in SessionsController#new and in require_login and then
  # being used in SessionsController#create
  def return_or(path)
    session.delete(:return_to) || path
  end
  helper_method :return_or
end

これらのヘルパー メソッドはすべて から継承されるため、すべてのコントローラーで使用できますApplicationControllerPostsController次に、ログインしていないユーザーを送信してログインするように指示できます。その後、ユーザーは PostsController に戻されます。

次に、認証後にのみ投稿を保存するという要件に対処するには、投稿を作成して保存しますが、ユーザーが認証された後にのみ公開するように更新するか、投稿のコンテンツをセッションに保存して復元しますユーザーが認証された後:

class PostsController < ApplicationController
  def new
    @post = Post.new(session[:post_params] || {})
  end

  def create
    if logged_in?
      @post = Post.create(params[:post])
      # ... etc
    else
      session[:post_params] = params[:post]
      session[:return_to] = new_post_path
    end
  end
end

これはかなり脆弱なアプローチであることに注意してください。Post実際に を作成し、まだ公開されていないものとしてマークし、投稿のみidをセッションに保存することをお勧めします。認証後、その post_id を見つけてオブジェクトを再作成し、ステータスを public に設定して current_user に関連付けることができます。

于 2013-02-27T07:39:52.993 に答える