获取(omniauth-facebook)和(omniauth-twitter)工作
我正在使用:
- Ruby on Rails 4
- 设计3.0.3
- omniauth(1.1.4)
- omniauth-facebook(1.4.1)
- omniauth-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
- omniauth 1.1.4
- omniauth-facebook 1.3.0
- omniauth-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