0

我正在开发一个使用 Devise、OmniAuth 和 OmniAuth-Facebook 的可安装引擎(称为 SimpleUser)。首先,我用宝石制作了一个测试应用程序,每个都运行良好。接下来,我以测试应用程序的代码为例,从头开始构建引擎。

一切都差不多完成了,除了与 Facebook 的连接(它使用 Javascript 弹出窗口)。当我单击“登录”时,会显示 FB 弹出窗口,我授予该应用程序,它会重定向到指定的路线(请参阅路线),但会引发此错误:

NoMethodError in SimpleUser::AuthController#create
undefined method `[]' for nil:NilClass

错误发生在该操作中,在auth为 nil的行authentication = Authentication.find_by_provider_and_uid(auth['provider'], auth['uid'])中( auth来自)。auth = request.env["omniauth.auth"]

我检查的一件事是回调阶段它没有初始化。这是测试应用程序的日志:

在 2013 年 3 月 14 日 08:52:56 -0600 (facebook) 开始为 127.0.0.1 获取“/auth/facebook/callback” 回调阶段。由 AuthController#create 作为 HTML 参数处理:{"provider"=>"facebook"}

这是引擎应用程序的日志:

Started GET "/simple_user/auth/facebook/callback" for 127.0.0.1 at 2013-03-14 08:51:19 -0600
Processing by SimpleUser::AuthController#create as HTML
  Parameters: {"provider"=>"facebook"}

为了管理 OmniAuth,我将 gem 添加到 .gemspec 和 Gemfile;另外,我需要引擎中的 gem,并且在引擎的生成器中,我在安装期间将omniauth.rb 的模板移动到父应用程序的配置/初始化程序。这就是我所拥有的:

AuthController(位于 app/controllers/simple_user/auth_controller.rb 中)

module SimpleUser
  class AuthController < ApplicationController

    def create
      auth = request.env["omniauth.auth"]   
      authentication = Authentication.find_by_provider_and_uid(auth['provider'], auth['uid'])

      if authentication
        flash[:notice] = "Signed in successfully."
        sign_in(:user, authentication.user)
        redirect_to root_url
      else
        user = User.build_new_auth(auth)
        #user.apply_omniauth(auth)
        if user.save(:validate => false)
          flash[:notice] = "Account created and signed in successfully."
          sign_in(:user, user)
          redirect_to root_url
        else
          flash[:error] = "Error while creating the user account. Please try again."
          redirect_to root_url
        end
      end
    end

  end
end

引擎

module SimpleUser

  require 'rubygems'
  require 'devise'
  require 'cancan'
  require 'rolify'
  require 'omniauth'
  require 'omniauth-facebook'
  require 'simple_form'

  class Engine < ::Rails::Engine
    isolate_namespace SimpleUser

    config.before_configuration do
      env_file = File.join(Rails.root, 'config', 'fb_config.yml')
      YAML.load(File.open(env_file)).each do |key, value|
        ENV[key.to_s] = value.to_s
      end if File.exists?(env_file)

      env_file = File.join(Rails.root, 'config', 'devise_config.yml')
      YAML.load(File.open(env_file)).each do |key, value|
        ENV[key.to_s] = value.to_s
      end if File.exists?(env_file)
    end
  end
end

发电机

module SimpleUser
  module Generators
    class InstallGenerator < ::Rails::Generators::Base
      source_root File.expand_path("../templates", __FILE__)
      desc "Install SimpleUser"

      def copy_config_file
        copy_file "fb_config.yml", "config/fb_config.yml"
        copy_file "devise_config.yml", "config/devise_config.yml"
        copy_file "omniauth.rb", "config/initializers/omniauth.rb"
      end

      def copy_migrations
        rake "simple_user:install:migrations"
        SimpleUser::Engine.load_seed
      end

    end
  end
end

omn​​iauth.rb 的模板

require 'omniauth'
require 'omniauth-facebook'

OmniAuth.config.logger = Rails.logger

Rails.application.config.middleware.use OmniAuth::Builder do
    provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], :scope => ENV['FACEBOOK_SCOPE']
end

路线(在引擎上)

match 'auth/:provider/callback', to: 'auth#create'
match 'auth/failure', to: redirect('/')

路线(在虚拟应用程序上)

mount SimpleUser::Engine => "/simple_user", :as => "simple_user"

.gemspec 依赖项

  s.add_dependency "rails", "~> 3.2.12"
  s.add_dependency "devise"
  s.add_dependency "cancan"
  s.add_dependency "rolify"
  s.add_dependency "omniauth"
  s.add_dependency "omniauth-facebook", "1.4.1"
  s.add_dependency "simple_form"

  #s.add_development_dependency "mysql2"
  s.add_development_dependency "sqlite3"
  s.add_development_dependency "jquery-rails"
  s.add_development_dependency "debugger"

宝石文件

source "http://rubygems.org"

gemspec

gem 'devise'
gem 'cancan'
gem 'rolify'
gem 'omniauth'
gem 'omniauth-facebook', '1.4.1'
gem 'simple_form'

# Development
gem 'jquery-rails'
gem 'debugger'

我认为问题是没有初始化的回调,原因可能是OmniAuth没有被加载,但我不知道它是否以及如何解决它。

你可以在https://github.com/pablomarti/simple_user查看项目,如果你想克隆它并测试你可以使用生成器rails g simple_user:install,你也可以看到 test/dummy 的代码来了解这个想法。

非常感谢您提前。

4

1 回答 1

0

解决的办法是去掉omniauth.rb,在引擎中包含OmniAuth的中间件,所以引擎看起来是这样的:

module SimpleUser

  require 'rubygems'
  require 'devise'
  require 'cancan'
  require 'rolify'
  require 'omniauth'
  require 'omniauth-facebook'
  require 'simple_form'

  class Engine < ::Rails::Engine
    isolate_namespace SimpleUser

    middleware.use OmniAuth::Builder do
      provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], :scope => ENV['FACEBOOK_SCOPE']
    end

    config.before_configuration do
      env_file = File.join(Rails.root, 'config', 'fb_config.yml')
      YAML.load(File.open(env_file)).each do |key, value|
        ENV[key.to_s] = value.to_s
      end if File.exists?(env_file)

      env_file = File.join(Rails.root, 'config', 'devise_config.yml')
      YAML.load(File.open(env_file)).each do |key, value|
        ENV[key.to_s] = value.to_s
      end if File.exists?(env_file)
    end

  end
end

感谢 Dmitry Lihachev在类似问题中的回答https://stackoverflow.com/a/8413724/347501 。

于 2013-03-14T21:54:33.423 回答