获取(omniauth-facebook)和(omniauth-twitter)工作

我正在使用:

  • Ruby on Rails 4
  • 设计3.0.3
  • omn​​iauth(1.1.4)
  • omn​​iauth-facebook(1.4.1)
  • omn​​iauth-twitter(1.0.0)

我最近建立了我的omniauth-facebook ,一切正常。 现在我想添加omniauth-twitter但不知怎的,我搞砸了,非常糟糕。

1.)设置我的Omniauth-Facebook我做到了这一点(简而言之):

 gem 'omniauth' gem 'omniauth-facebook' 

2.)在我的用户模型中添加了“ provider ”和“ uid ”列。

3.)接下来,我在config / initializers / devise.rb中声明了提供程序:

 require "omniauth-facebook" config.omniauth :facebook, "App_ID", "App_Secret", {:scope => 'email,offline_access', :client_options => {:ssl => {:ca_file => 'lib/assets/cacert.pem'}}, :strategy_class => OmniAuth::Strategies::Facebook} 

4.)我编辑了Model User.rb

 # Facebook Settings def self.find_for_facebook_oauth(auth, signed_in_resource = nil) user = User.where(provider: auth.provider, uid: auth.uid).first if user.present? user else user = User.create(first_name:auth.extra.raw_info.first_name, last_name:auth.extra.raw_info.last_name, facebook_link:auth.extra.raw_info.link, user_name:auth.extra.raw_info.name, provider:auth.provider, uid:auth.uid, email:auth.info.email, password:Devise.friendly_token[0,20]) end end 

并添加了设计的属性:

 :omniauth_providers => [:facebook] 

5.)我编辑了路线:

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

结束

虽然这对Facebook来说非常有效,但我现在花了好几个小时来为Twitter工作,我只是想弄清楚。

如果有经验的人,或者只是知道解决方案可以帮我设置,我会非常感激:)

谢谢你们,对不起,长期邮报感到抱歉。

此外

Twitter没有提供:电子邮件属性所以我必须拆分我的用户注册流程我猜?

我在我的用户模型中的 Twitter操作

 # Twitter Settings def self.find_for_twitter_oauth(auth, signed_in_resource=nil) user = User.where(:provider => auth[:provider], :uid => auth[:uid]).first unless user user = User.create(:first_name => auth[:name], :user_name => auth[:screen_name], :provider => auth[:provider], :uid => auth[:uid], :password => Devise.friendly_token[0,20] ) end user end # build auth cookie hash for twitter def self.build_twitter_auth_cookie_hash data { :provider => data.provider, :uid => data.uid.to_i, :access_token => data.credentials.token, :access_secret => data.credentials.secret, :first_name => data.name, :user_name => data.screen_name, } end 

我必须为用户迁移确认 – > 如何:添加:确认用户

我的表格的问题,(至少我现在开始这个poing :))

在此处输入图像描述

要解决您的电子邮件问题,您可以设置一个虚拟邮件,或添加第二步,用户添加他/她的电子邮件。

虚拟邮件:

 class User < ActiveRecord::Base before_create :set_dummy_mail, if self.provider == "twitter" private def set_dummy_mail self.email = "#{self.name}_email@example.com" end end 

或者第二步选项:

如果提供商是推特并且电子邮件为空,则修改您的控制器以重定向到添加电子邮件步骤。 如果提供者是推特,也许您还必须修改您的validation以允许在创建时将电子邮件留空。

更新 :我这样做如下:

的Gemfile:

 gem "devise" gem "omniauth" gem "omniauth-facebook" gem "omniauth-twitter" 

我用了:

  • 设计版本2.2.3
  • omn​​iauth 1.1.4
  • omn​​iauth-facebook 1.3.0
  • omn​​iauth-twitter 0.0.17

如果您使用的是不同的版本,您可能必须更改一些内容..

routes.rb中:

 devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } devise_scope :user do post "account/create" => "users/accounts#create" end 

应用程序/模型/ user.rb

 class User < ActiveRecord::Base # allow email blank for first create validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true, :if => :email_changed? # facebook find method def self.find_for_facebook_oauth(auth, signed_in_resource=nil) user = User.where(:provider => auth.provider, :uid => auth.uid).first unless user user = User.create(:first_name => auth.extra.raw_info.first_name, :last_name => auth.extra.raw_info.last_name, :facebook_link => auth.extra.raw_info.link, :user_name => auth.extra.raw_info.name :provider => auth.provider, :uid => auth.uid, :email => auth.info.email, :password => Devise.friendly_token[0,20] ) user.confirm! end user end # twitter find method def self.find_for_twitter_oauth(auth, signed_in_resource=nil) user = User.where(:provider => auth[:provider], :uid => auth[:uid]).first unless user user = User.create(:first_name => auth[:first_name], :user_name => auth[:user_name], :provider => auth[:provider], :uid => auth[:uid], :password => Devise.friendly_token[0,20] ) end user end # build auth cookie hash for twitter def self.build_twitter_auth_cookie_hash data { :provider => data.provider, :uid => data.uid.to_i, :access_token => data.credentials.token, :access_secret => data.credentials.secret, :first_name => data.screen_name, :user_name => data.name, } end end 

应用程序/控制器/用户/ omniauth_callbacks_controller.rb

 class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController # callback action for facebook auth def facebook @user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user) if @user.persisted? sign_in_and_redirect @user, :event => :authentication set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format? else session["devise.facebook_data"] = request.env["omniauth.auth"] redirect_to new_user_registration_url end end # callback action for twitter auth def twitter data = session["devise.omniauth_data"] = User.build_twitter_auth_cookie_hash(request.env["omniauth.auth"]) user = User.find_for_twitter_oauth(data) if user.confirmed? # already registered, login automatically flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Twitter" sign_in_and_redirect user, :event => :authentication elsif !user.email? flash[:error] = "You must add an email to complete your registration." @user = user render :add_email else flash[:notice] = "Please confirm your email first to continue." redirect_to new_user_confirmation_path end end end 

应用程序/视图/用户/ omniauth_callbacks / add_email.html.erb

 <%= form_for(@user, :as => "user", :url => account_create_path, :html => {:class => "form-inline"}) do |f| %> <%= f.email_field :email, :placeholder => User.human_attribute_name(:email), :class => "input-medium" %> <%= f.submit "Finish registration", :class => "btn btn-small" %> <% end %> 

应用程序/控制器/用户/ accounts_controller.rb

 class Users::AccountsController < ApplicationController def create data = session["devise.omniauth_data"] data[:email] = params[:user][:email] user = User.find_for_twitter_oauth(data) user.email = data[:email] if user.save flash[:notice] = I18n.t "devise.registrations.signed_up_but_unconfirmed" redirect_to root_path else flash[:error] = I18n.t "devise.omniauth_callbacks.failure", :kind => data[:provider].titleize, :reason => user.errors.full_messages.first render "users/omniauth_callbacks/add_email" end end end 

也许您必须修改我的解决方案的一个或其他部分。您还可以重构用户模型中的两个方法(find_for_facebook_auth,find_for_twitter_auth)以使用一个动态方法。 如果你还有问题的话,试试看,让我知道。 如果您发现任何拼写错误,请让我知道..此外,您应该编写测试来检查系统中的所有内容。

在gem文件中添加它

 gem 'omniauth-twitter' 

捆绑并重新启动服务器

在此之后,在config / initializer / devise.rb中添加app_id和密钥

 require "omniauth-twitter" config.omniauth :twitter, "app_id", "secret_key" 

编辑您的用户模型

 :omniauth_providers => [:facebook,:twitter] def self.find_for_twitter_oauth(auth, signed_in_resource=nil) user = User.where(:provider => auth.provider, :uid => auth.uid).first unless user user = User.create(name:auth.extra.raw_info.name, provider:auth.provider, uid:auth.uid, email:auth.info.email, password:Devise.friendly_token[0,20] ) end user end 

添加新的控制器文件

应用程序/控制器/用户/ omniauth_callbacks_controller.rb

  def twitter @user = User.find_for_twitter_oauth(request.env["omniauth.auth"], current_user) if @user.persisted? sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format? else session["devise.twitter_data"] = request.env["omniauth.auth"] redirect_to new_user_registration_url end 

结束

在视图文件中添加此链接

 <%= link_to 'sign in with twitter', user_omniauth_authorize_path(:twitter) %> 

用户模型中作为twitter所需的更改不返回用户的电子邮件ID:创建迁移文件以允许用户的电子邮件列中的空值:

 class ChangeEmailToNullInUser < ActiveRecord::Migration def up change_column :users, :email, :string, :null=>true end def down end end 

在此之后,您还需要覆盖用户模型validation,因此请在user.rb中添加

 def email_required? false end 

注意:在执行此操作之前,您应该在Twitter上创建应用程序并提供适当的回调路径。 它非常重要,因为在通过Twitter进行身份validation后,控制器将返回到您在Twitter上的应用程序中指定的路径。

如果您有任何问题,请告诉我。

Mattherick有一个很好的解决方案,但我无法让before_create工作。 回调对条件if语句不好用,因为逗号之后的任何内容都是一个选项哈希。 因此:

 before_save :set_dummy_email, if self.provider == "twitter" 

弹出我的错误。

这是我如何修复这个:

 before_save :set_dummy_email def set_dummy_email self.email ||= "#{self.name}-CHANGEME@example.com" end 

如果提供商未提供电子邮件(即:Twitter),则仅设置电子邮件。

然后是一种更“通用”的设置属性的方式(所以你不需要一个独特的策略:

 def self.from_omniauth(auth) where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user| user.name = auth.info.name || auth.info.nickname user.provider = auth.provider user.uid = auth.uid user.email = auth.info.email if auth.info.email user.save end end