Ruby on rails Omniauth Twitter-重定向到表单以获取更多信息
我正在关注,但在用户连接omniauth时,如何将用户重定向到页面以填写更多信息方面失败 在我的用户模型中,我有:Ruby on rails Omniauth Twitter-重定向到表单以获取更多信息,ruby-on-rails,ruby-on-rails-4,devise,omniauth,twitter-oauth,Ruby On Rails,Ruby On Rails 4,Devise,Omniauth,Twitter Oauth,我正在关注,但在用户连接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.provide
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
配置文件\u以下各项的有效检查:
def profile_valid?
self.email && self.email !~ TEMP_EMAIL_REGEX
end
Twitter auth不会给你一封电子邮件,这是我注册时需要的,所以我传递一封带有正则表达式(TEMP_email_regex)的虚拟电子邮件
因此,当一封有效的电子邮件不存在时,它应该重定向到finish_signup_页面,该页面包含:
<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>
添加电子邮件
'user',:url=>finish_signup_path(当前_用户),:html=>{role:'form'})do | f |%>
true,:value=>'',类:'form control',占位符:'Username'>
请输入您的用户名
true,:value=>'',类:'form control',占位符:'Example:email@me.com' %>
请确认您的电子邮件地址。没有垃圾邮件
“btn btn主节点”%>
这是我的问题,当我输入一些东西时,它不会保存用户,如果在实际字段中出现当前值会更好吗
但我不知道该怎么做,或者我现在尝试这个太久了,有一个隧道式的视野
我遗漏了什么?首先要完成以下课程。您需要为用户存储正确的数据,生成的电子邮件不是一个好的解决方案。因此,我们基本上将提供者的数据存储在一个单独的模型中社交提供者
注册流程:
- sp=已创建社交提供商
- 用户由从提供程序接收的数据初始化(未保存)
- 我们将sp id存储在会话中,以将其与用户访问隔离
- 我们呈现设备注册/新视图(添加我们需要的所有字段)
- 成功注册后,我们将sp链接到创建的用户
1.用户类具有
updatefrom\u oauth
方法,该方法更新用户中的主要属性而不保存它。
##########################
#用户类
##########################
类用户
2.SocialProvider类或(标识)
class SocialProvider
3.Omniauth回调控制器
###############################
#OmniAuth回调控制器
###############################
类用户::OmniAuthCallbackController<设计::OmniAuthCallbackController
过滤前:准备验证
def facebook
连接(:facebook)
结束
def推特
连接(:twitter)
结束
def google_oauth2
连接(:谷歌)
结束
私有的
def prepare_auth
@auth=request.env[“omniauth.auth”]
结束
def连接(提供程序_类型)
social\u provider=SocialProvider.find\u for\u oauth(@auth,provider\u type)
如果用户已登录?
如果social_provider和social_provider.user_id==当前_user.id
flash[:notice]=“您的#{provider\u type}帐户已附加”
将_重定向到当前_用户并返回
elsif社交网络提供商。用户\ id.nil?
当前用户。从oauth(@auth,provider\u type)更新
当前\u用户。社交\u提供程序:身份验证
否则#如果用户没有帐户
会话[:sp_id]=社交提供商.id
呈现“注册/新”
结束
结束
结束
结束
4.覆盖设计注册控制器
#################################
#设计::注册控制器
#################################
类注册控制器<设计::注册控制器
def创建
超级的
如果用户已登录?和会话[:sp_id]。是否存在?
SocialProvider.find_by(id:session[:sp_id],user_id:nil).update(user_id:current_user.id)
结束
结束
嘿,穆罕默德,非常感谢你的回答。你能尽可能和我一起聊天吗?
##########################
# 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
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
###############################
# 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
#################################
# 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