私は、ユーザーがFacebookでサインインしてから、プロファイルフィードにリダイレクトできるWebアプリを構築してきました。ユーザーが存在しない場合は、Facebookの資格情報を使用して新しいレコードが作成され、ユーザーモデルに保存されます。
私が抱えている問題は、Facebookコールバックからユーザーのプロファイルページにリダイレクトしようとすると、UsersController#showでActiveRecord :: RecordNotFoundエラーが発生するかどうかに関係なく、レコードが見つからないことです。レコードはすでに存在していたか、サインインの過程で新しく作成されました。
認証とFacebookGraphAPIへのアクセスにOmniAuthを使用していますが、Ryan Bates RailsCast#360(http://railscasts.com/episodes/360-facebook-authentication?autoplay=true)で概説されている規則に大まかに従っています。
これが私のユーザーモデルです:
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(auth.slice(:uid)).first_or_create.tap do |user|
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.img_url = auth.info.image
user.save!
end
end
end
関連する2つのコントローラーと同様に、
SessionsController:
class SessionsController < ApplicationController
def new
redirect_to '/auth/facebook'
end
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to user
end
def destroy
session[:user_id] = nil
redirect_to root_url
end
end
およびUsersController:
class UsersController < ApplicationController
def show
@user = User.find(params[:uid])
end
end
トレースデータとセッションダンプ
さらに、トレースは、ユーザーコントローラーの「show」メソッドでエラーが発生していることを示しています。
app/controllers/users_controller.rb:4:in `show'
私が理解していないのは、リクエストパラメータに示されているように、ユーザーを表示するクエリがモデルの一部ではないidフィールドを使用する理由です。
{"id"=>"1"}
およびセッションダンプ:
_csrf_token: "sjym9SfVWrLipH/7Lxn4RCp2Df6kQTNITnhjro2tirI="
session_id: "7d2c6e70bcae6f1ec257fd634a73c44b"
user_id: 1
最も厄介なのは、railsコンソールを使用してUsersデータベースを調べると、元のスキーマの一部ではなかった追加のIDフィールドが含まれた次のハッシュが返されることです。
=> #<User id: 1, uid: "1123581321", name: "Bob Loblaw", oauth_token: "AAAHFZAqhAyeEBADdZCxeCIdFQWjkbQFjfGfJjCiZA8VKSAw5zy...", oauth_expires_at: "2013-04-14 01:15:20", created_at: "2013-02-13 01:19:24", updated_at: "2013-02-13 01:57:18", img_url: "http://graph.facebook.com/1123581321/picture?type=s...">
スキーマ:
create_table "users", :force => true do |t|
t.string "uid"
t.string "name"
t.string "oauth_token"
t.datetime "oauth_expires_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "img_url"
end
ルート
ルートはかなり標準的です、私は問題がそこにあるとは思わない:
resources :users
root to: 'static_pages#home'
match 'auth/:provider/callback', to: 'sessions#create'
match 'auth/failure', to: redirect('/')
match 'signout', to: 'sessions#destroy', as: 'signout'
match '/how_it_works', to: 'static_pages#how_it_works'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'