繁体   English   中英

Omniauth Twitter-重定向至表格以获取更多信息

[英]Omniauth Twitter - Redirect to form for extra Information

我正在按照本教程进行操作,但是当用户使用omniauth连接时,如何将用户重定向到页面以填写更多信息失败。

在我的用户模型中,我有:

user = User.new(
  name: auth.extra.raw_info.name,
  user_name: auth.info.nickname,
  about_me: auth.info.description,
  email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
  password: Devise.friendly_token[0,20]
)
user.skip_confirmation!
user.save!

在我的Omniauth回调控制器中,我有:

def after_sign_in_path_for(resource)
  if resource.profile_valid?
    super resource
  else
    finish_signup_path(resource        
  end
end

profile_valid检查以下内容:

def profile_valid?
  self.email && self.email !~ TEMP_EMAIL_REGEX
end

Twitter身份验证没有给您发送电子邮件,我需要注册才能通过电子邮件发送,因此我要传递带有正则表达式(TEMP_EMAIL_REGEX)的虚拟电子邮件。

因此,当没有有效的电子邮件时,应将其重定向到包含以下内容的finish_signup_page:

<div id="add-email" class="container">
  <h1>Add Email</h1>
  <%= form_for(current_user, :as => 'user', :url => finish_signup_path(current_user), :html => { role: 'form'}) do |f| %>


    <% if @show_errors && current_user.errors.any? %>
      <div id="error_explanation">
        <% current_user.errors.full_messages.each do |msg| %>
          <%= msg %><br>
        <% end %>
      </div>
    <% end %>

    <!-- User Name -->
    <div class="form-group">
      <%= f.label :user_name %>
      <div class="controls">
        <%= f.text_field :user_name, :autofocus => true, :value => '', class: 'form-control', placeholder: 'Username' %>
        <p class="help-block">Please enter your username</p>
      </div>
    </div>

    <div class="form-group">
      <%= f.label :email %>
      <div class="controls">
        <%= f.text_field :email, :autofocus => true, :value => '', class: 'form-control', placeholder: 'Example: email@me.com' %>
        <p class="help-block">Please confirm your email address. No spam.</p>
      </div>
    </div>
    <div class="actions">
      <%= f.submit 'Continue', :class => 'btn btn-primary' %>
    </div>
  <% end %>
</div>

这是我的问题,当我输入某些内容时不会保存用户,如果在实际字段中显示当前值会更好?

但是我对如何做到这一点迷失了,或者也许我已经尝试了太久了,并且已经有了一个通道视觉。

我想念什么?

首先经历以下课程。 您需要为用户存储正确的数据,生成的电子邮件不是一个好的解决方案。 因此,我们基本上将提供者的数据存储在单独的模型Social Provider

注册流程:

  • sp =社会提供者已创建
  • 通过从提供者接收的数据(未保存)初始化用户。
  • 我们将sp id存储在会话中,以将其与用户隔离。
  • 我们呈现设备注册/新视图(添加我们需要的所有字段)。
  • 成功注册后,我们将sp链接到创建的用户。

update_from_oauth类具有update_from_oauth方法,该方法将更新用户中的主要属性而不保存它。

##########################
# User Class
##########################

class User < ActiveRecord::Base
  has_many :social_providers, dependent: :destroy

  # update from OAuth
  def update_from_oauth(auth, provider_type)
    self.email = auth[:info][:email] if self.email.blank?
    case provider_type
    when :twitter
      name = auth[:info][:name].split(' ')
      self.first_name ||= name[0]
      self.last_name ||= name[1]
      self.remote_avatar_url = auth[:extra][:raw_info][:profile_image_url]
    when :facebook
      ...
    when :google
      ...
    end
  end
end

2. SocialProvider类别或(身份)

class SocialProvider < ActiveRecord::Base

  #Relations
  belongs_to :user

  def self.find_for_oauth(auth, provider_type)
    unless social_provider = self.find_by(pid: auth[:uid].to_s, provider_type: provider_type)
      user = User.find_by_email(auth[:info][:email])
      social_provider = user.social_providers.where(provider_type: provider_type).first if user.present?
      social_provider ||= SocialProvider.new
    end
    social_provider.update_from_oauth(auth, provider_type)
    social_provider
  end

  def update_from_oauth(auth, provider_type)
    self.email= auth[:info][:email]
    self.pid= auth[:uid]
    self.provider_type= provider_type
    credentials = auth[:credentials]
    case provider_type
    when :twitter
      self.token = credentials[:token]
      self.secret = credentials[:secret]
      self.url = auth[:info][:urls][:Twitter]
    when :facebook
      ...
    when :google
      ...
    end
  end
end

##########################
# SocialProvider Migration
##########################

class CreateSocialProviders < ActiveRecord::Migration
  def change
    create_table "social_providers" do |t|
      t.string   "pid" # user provider id
      t.string   "token"
      t.string   "refresh_token"
      t.string   "secret"
      t.datetime "expires_at"
      t.string   "provider_type"
      t.integer  "user_id"
      t.string   "url"
      t.string   "email"
      t.timestamps
    end
  end
end

3. Omniauth回调控制器

###############################
# OmniAuth Callbacks Controller
###############################

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  before_filter :prepare_auth

  def facebook
    connect(:facebook)
  end

  def twitter
    connect(:twitter)
  end

  def google_oauth2
    connect(:google)
  end

  private

    def prepare_auth
      @auth = request.env["omniauth.auth"]
    end

    def connect(provider_type)
      social_provider = SocialProvider.find_for_oauth(@auth, provider_type)
      if user_signed_in?
        if social_provider and social_provider.user_id == current_user.id
          flash[:notice] = "Your #{provider_type} account is already attached"
          redirect_to current_user and return
        elsif social_provider.user_id.nil?
          current_user.update_from_oauth(@auth, provider_type)
          current_user.social_providers << social_provider if current_user.save
          flash[:notice] = "Successfully attached #{provider_type} account"
          redirect_to current_user and return
        else
          flash[:notice] = "#{provider_type} is already connected to another account"
          redirect_to current_user and return
        end
      else
        @user = social_provider.user || User.find_by_email(@auth[:info][:email]) || User.new
        @user.update_from_oauth(@auth, provider_type)
        social_provider.save
        if @user.persisted? # If user already has account and not logged in
          @user.social_providers << social_provider if @user.save
          flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider_type.capitalize
          sign_in_and_redirect @user, :event => :authentication
        else # If user has no account
          session[:sp_id] = social_provider.id 
          render 'registrations/new'
        end
      end
    end
end

4.覆盖Devise注册控制器

#################################
# Devise::RegistrationsController
#################################

class RegistrationsController < Devise::RegistrationsController

  def create
    super
    if user_signed_in? and session[:sp_id].present?
      SocialProvider.find_by(id: session[:sp_id],user_id: nil).update(user_id: current_user.id)
    end
  end

暂无
暂无

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

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