简体   繁体   English

整合Wicked,Devise和Omniauth-Facebook

[英]Integrating Wicked, Devise and Omniauth-Facebook

I am developing an application using these three gem I wrote in the title of this post. 我正在使用我在帖子标题中编写的这三个gem开发一个应用程序。 I set up devise with the confirmable module(?), so when a user creates an account with its email/password, it receives a confirmation email. 我使用可确认模块(?)设置了devise,因此,当用户使用其电子邮件/密码创建帐户时,它将收到确认电子邮件。 If the user sign up with facebook (using omniauth-facebook gem) devise skips the confirmation step. 如果用户(使用omniauth-facebook gem)使用facebook进行注册,则devise跳过确认步骤。

In user.rb 在user.rb中

    "Of course the :confirmable is active in the model"
    ...

    # Omniauth-facebook
    def self.find_for_facebook_oauth(auth)
      where(auth.slice(:provider, :uid)).first_or_create do |user|
        user.provider = auth.provider
        user.uid = auth.uid
        user.email = auth.info.email
        user.password = Devise.friendly_token[0,20]
        user.first_name = auth.info.first_name
        user.last_name = auth.info.last_name
        user.skip_confirmation!
        # user.image = auth.info.image # assuming the user model has an image
      end
    end

    ...

The thing comes when I added the wicked gem for the wizard. 当我为向导添加邪恶的宝石时,事情就来了。 I configured the routes file 我配置了路由文件

in routes.rb 在routes.rb中

MyApp::Application.routes.draw do

  devise_for :users, :controllers => { :omniauth_callbacks =>  "users/omniauth_callbacks",
          :registrations => "registrations" }

  root 'home#index'

  # Registration wizard routes
  resources :after_register
end

The I created a registration_controller to override the devise registration methods 我创建了一个registration_controller来覆盖设计注册方法

    class RegistrationsController < Devise::RegistrationsController

      def create
        super
      end

    protected

     def after_sign_in_path_for(resource)
       puts "<<<<<<<<<<<<<<<< SIGN IN"
       after_register_path(:import_contacts)
     end

     def after_sign_up_path_for(resource)
       puts "<<<<<<<<<<<<<<<< SIGN UP ACTIVE"
     after_register_path(:import_contacts)
   end

   def after_inactive_sign_up_path_for(resource)
    puts "<<<<<<<<<<<<<<<< SIGN IN INACTIVE"
    after_register_path(:import_contacts)
   end
 end

And then, I created a new controller to handle the steps of the wizard with wicked. 然后,我创建了一个新的控制器来处理邪恶的向导步骤。

   class AfterRegisterController < ApplicationController
     include Wicked::Wizard
     before_filter :authenticate_user!

     steps :import_contacts, :select_agents, :wish_form

     def show
       @user = current_user
       render_wizard
     end

     def update
       @user = current_user
       @user.attributes = params[:user]
       render_wizard @user
     end

   end

When I create a user rith email/password, the wizard comes and everything works fine, but when I try to sign up with facebook, the wizars never comes. 当我创建一个用户密码或密码时,向导会出现,并且一切正常,但是当我尝试注册Facebook时,wizar永远不会出现。

Any hint??? 任何提示?

Thank you!! 谢谢!!

If everything is configured in the usual way (and what I can see looks pretty standard), then signing in using Facebook won't go via the RegistrationsController at all. 如果一切都以通常的方式配置(我所看到的看起来很标准),那么使用Facebook登录根本就不会通过RegistrationsController It will go via the OmniauthCallbacks controller which you haven't posted the code for. 它将通过您尚未为其发布代码的OmniauthCallbacks控制器进行。 It depends what you do in there when they log in via Facebook. 当他们通过Facebook登录时,这取决于您在那做什么。 I assume that you have a facebook() method which calls User.find_for_facebook_oauth(auth) . 我假设您有一个调用User.find_for_facebook_oauth(auth)facebook()方法。 Are you then just signing them in rather than going to the RegistrationsController ? 然后,您只是登录他们而不是去RegistrationsController吗? If so, then the RegistrationsController won't be touched, so its overridden after_sign_in_path_for won't have any effect. 如果是这样,那么RegistrationsController将不会被触摸,因此其重写的after_sign_in_path_for将不起作用。

If you want to have your overridden after_sign_in_path_for take effect throughout your app, you can define it in your ApplicationController . 如果要使覆盖的after_sign_in_path_for在整个应用程序中生效,则可以在ApplicationController对其进行定义。 If you only want it to take effect in your OmniauthCallbacksController , you could define it there. 如果只希望它在OmniauthCallbacksController ,则可以在那里定义它。 In either case, they'll be hitting it every time they log in using Facebook (and if you put it in the ApplicationController , every time anyone logs in using any method), so you'd need to keep track of the fact that they have already been through the wizard, assuming you want to make sure that it only happens the first time they sign in. If you're using the devise :trackable module, perhaps checking the user.sign_in_count would be appropriate, or perhaps you have some other way to easily check if they have been through the wizard already. 无论哪种情况,他们每次使用Facebook登录时都会被击中(如果您将其放置在ApplicationController ,则任何人每次使用任何方法登录时都将被击中),因此您需要跟踪他们假设您想确保它仅在他们第一次登录时就已经通过了向导。如果您正在使用devise:trackable模块,则可能需要检查user.sign_in_count,或者您有一些另一种轻松检查它们是否已经通过向导的方法。

UPDATE FOR COMMENT QUESTIONS: 评论问题的更新:

Your first question: "Assuming I put the after_sign_in_path_fot in ApplicationController, I should remove the after_inactive_sign_up_path_for method in RegistrationsController, right?" 您的第一个问题:“假设我将after_sign_in_path_fot放在ApplicationController中,我应该在RegistrationsController中删除after_inactive_sign_up_path_for方法,对吗?” It depends on what behaviour you want. 这取决于您想要的行为。 With the RegistrationsController as in your question it will go to the wizard after they've signed up and before they've confirmed their email (because of after_inactive_sign_up_path_for which will be called in this case). 按照您的问题使用RegistrationsController ,在他们注册后并且确认电子邮件之前,它将进入向导(因为在这种情况下将调用after_inactive_sign_up_path_for )。 When they confirm and sign in, the after_sign_in_path_for in ApplicationController will send them to the wizard again. 当他们确认并登录后, ApplicationControllerafter_sign_in_path_for将再次将其发送给向导。 So yes, remove inactive from RegistrationsController if you just want wizard after sign in. Then probably after_sign_up_path_for(resource) in RegistrationsController is unnecessary because the default implementation in devise just calls after_sign_in_path_for(resource) which you will have in your ApplicationController . 因此,是的,如果您只想在登录后使用向导,则从RegistrationsController删除不活动的对象。然后在RegistrationsController可能after_sign_up_path_for(resource) ,因为after_sign_in_path_for(resource)的默认实现只是调用了您将在ApplicationController after_sign_in_path_for(resource) Anyway, after_sign_up_path_for() won't be called if you always require confirmation because of the logic in the default implementation of RegistrationsController.create() - requiring confirmation will result in resource.active_for_authentication? 无论如何,由于RegistrationsController.create()的默认实现中的逻辑,如果总是需要确认,将不会调用after_sign_up_path_for() -要求确认将导致resource.active_for_authentication? returning false which causes after_inactive_sign_up_path_for(resource) to be called. 返回false会导致after_inactive_sign_up_path_for(resource)被调用。

For the question in your second comment, you said "If I remove the after_sign_in_path_for in ApplicationController" - I assume you meant RegistrationsController ? 对于第二条评论中的问题,您说“如果我在ApplicationController中删除after_sign_in_path_for”,则认为您的意思是RegistrationsController If that's right, then yes, there would be no methods needed in your overridden version of RegistrationsController (if that's the whole controller you pasted in your question) because your create() just calls super , the after_sign_in_path_for would be in ApplicationController and you probably don't want either of the after_(inactive)_sign_up_path_for methods as discussed above. 如果是正确的话,那么是的,在您的重写版本的RegistrationsController不需要任何方法(如果这是您在问题中粘贴的整个控制器),因为您的create()只是调用superafter_sign_in_path_for将在ApplicationController ,您可能不after_sign_in_path_for不需要上述after_(inactive)_sign_up_path_for方法中的任何一个。 So yes, there would be no need for your RegistrationsController . 因此,是的,不需要您的RegistrationsController You could remove it completely and remove the :registrations => "registrations" in routes.rb - the devise implementation of RegistrationsController will then be used again. 您可以将其完全删除,然后在route.rb中删除:registrations => "registrations" -然后,将再次使用RegistrationsController的设计实现。

Then you say "just override the methods of RegistrationsController in ApplicationController?". 然后,您说“仅在ApplicationController中覆盖RegistrationsController的方法?”。 The only method you will have left from your RegistrationsController is the after_sign_in_path_for(resource) in ApplicationController , so I don't think there will be any other methods from your RegistrationsController that you need in ApplicationController . 您从RegistrationsController剩下的唯一方法是ApplicationControllerafter_sign_in_path_for(resource) ,因此,我认为RegistrationsController中没有其他需要在ApplicationController Let me know if I've missed one of your requirements or made an incorrect assumption. 让我知道我是否错过了您的要求之一或做出了错误的假设。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM