首页 文章

试图让omniauth-facebook工作未定义的方法`user_id'为nil:NilClass rails

提问于
浏览
2

我正在使用ryan bates facebook身份验证railscast和coderwall上的这篇文章来实现omniauth-facebook的登录功能

https://coderwall.com/p/bsfitw

所以对于我的gemfile,我有这两个

gem 'omniauth'
gem 'omniauth-facebook'

这是我的omniauth.rb

OmniAuth.config.logger = Rails.logger

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, 'commentedoutappid', 'commentedoutsecretid'
end

我的路线看起来像这样

match 'auth/:provider/callback', to: 'sessions#create', via: [:get, :post]
  match 'auth/failure', to: redirect('/'), via: [:get, :post]
  match 'signout', to: 'sessions#destroy', as: 'signout', via: [:get, :post]

  resources :movies do 
    resources :reviews
  end 
  root to: 'movies#index'

这是我的会话控制器

class SessionsController < ApplicationController
  def create
    user = User.from_omniauth(env["omniauth.auth"])
    session[:user_id] = current_user.user_id 
    redirect_to root_url
  end
end

这是我的用户模型

class User < ActiveRecord::Base
  def self.from_omniauth(auth)
    where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
      user.provider = auth.provider 
      user.uid = auth.uid
      user.name = auth.info.name
      user.oauth_token = auth.credentials.oauth_token 
      user.oauth_expires_at = Time.at(auth.credentials.expires_at)
      user.save
     end
   end 
end

这是我的用户表

create_table "users", force: true do |t|
    t.string   "provider"
    t.string   "uid"
    t.string   "name"
    t.string   "oauth_token"
    t.datetime "oauth_expires_at"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
  end

我在application.html.erb中有这些链接

<div id="user-widget">
  <% if current_user %>
    Signed in as <strong><%= current_user.name %></strong>!
    <%= link_to "Sign out", signout_path, id: "sign_out" %>
  <% else %>
    <%= link_to "Sign in with facebook", "/auth/facebook", id: "sign_in" %>
  <% end %>
</div>

当我点击指向auth / facebook的链接时

我在会话控制器中获取了 undefined method user_id'为nil:NilClass` .

哦,我也有一个current_user帮助方法

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end 
  helper_method :current_user
end

到目前为止,我完全理解流程,但不理解错误 . 我完全按照指南从上到下 .

我开始使用空白的rails 4应用程序 . 我甚至尝试过安装设备,因此有一个current_user,但我最终卸载了设计因为它们发生了冲突 .

1 回答

  • 2

    更新 SessionsController 中的 create 操作,如下所示:

    class SessionsController < ApplicationController
      def create
        user = User.from_omniauth(env["omniauth.auth"]) ## Setting "user" here
        session[:user_id] = user.id  ## Changed this to use the set "user"
        redirect_to root_url
      end
    end
    

    使用 user.id 而不是 current_user.user_id . 从逻辑上讲,您将在 users 表中拥有 id 列而不是 user_id .

    正如你指定的那样

    user = User.from_omniauth(env["omniauth.auth"])

    你需要设置 session[:user_id] = user.id 作为 user 变量具有 omniauth 的当前保存用户的实例 .

    在旁注中,我刚刚好奇地检查了您在问题中提供的链接,发现使用 session[:user_id] = user.id 时明确提到了 . 你一定错过了,但我的上述解释会让你知道为什么会这样 .

相关问题