Tôi đang cố gắng tạo một ứng dụng trong Rails 4. Tôi đã cố gắng trong 3 năm qua (ngoại trừ 10 ngày), để bắt đầu làm việc.Rails 4 - Devise Omniauth (nhiều chiến lược)
Tôi đang cố gắng để làm theo hướng dẫn này: http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/
Xin đừng khuyên tài liệu hướng dẫn/đá quý khác. Tôi đã thử ít nhất 30 hướng dẫn khác và tài liệu về đá quý có đầy đủ các lỗi và thành phần mà tôi không hiểu.
Vấn đề hiện tại của tôi là khi tôi đến bước đăng ký kết thúc trong hướng dẫn này, biểu mẫu yêu cầu tôi cung cấp địa chỉ email của tôi.
Bộ điều khiển người dùng có một phương thức đăng ký kết thúc như:
def finish_signup
# authorize! :update, @user
if request.patch? && params[:user] #&& params[:user][:email]
if @user.update(user_params)
@user.skip_reconfirmation!
# sign_in(@user, :bypass => true)
# redirect_to root_path, notice: 'Your profile was successfully updated.'
# redirect_to [@user, @user.profile || @user.build_profile]
sign_in_and_redirect(@user, :bypass => true)
else
@show_errors = true
end
end
end
Khi tôi cố gắng này, tôi nhận được lỗi này:
undefined method `match' for {:host=>"localhost", :port=>3000}:Hash
Những điểm lỗi tại dòng này:
<div class="intpol3"><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></div>
Môi trường phát triển của tôi được thiết lập để bao gồm tất cả chi tiết cấu hình cho người gửi email của tôi.
Khi tôi thử các bước tương tự trong chế độ sản xuất, tôi nhận được lỗi này:
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"profiles", :id=>nil} missing required keys: [:id]):
Nó tìm kiếm một hồ sơ id bởi vì tôi có một hành động after_create trong mô hình sử dụng của tôi là:
after_create :gen_profile
def gen_profile
Profile.create(user: self) # Associations must be defined correctly for this syntax, avoids using ID's directly.
# Profile.save
end
Vấn đề khác của tôi với hướng dẫn này là các trường trong bảng nhận dạng không được phổ biến.
Tôi rất muốn tìm một người đã triển khai thành công hướng dẫn này hoặc có thể xem cách thực hiện công việc này.
Mã của tôi là:
gemfile
gem 'devise', '3.4.1'
gem 'devise_zxcvbn'
gem 'omniauth'
gem 'omniauth-oauth2', '1.3.1'
gem 'omniauth-google-oauth2'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-linkedin-oauth2'
gem 'google-api-client', require: 'google/api_client'
tuyến
devise_for :users, #class_name: 'FormUser',
:controllers => {
:registrations => "users/registrations",
# :omniauth_callbacks => "users/authentications"
:omniauth_callbacks => 'users/omniauth_callbacks'
}
# get '/auth/:provider/callback' => 'users/authentications#create'
# get '/authentications/sign_out', :to => 'users/authentications#destroy'
# PER SOURCEY TUTORIAL ----------
match '/users/:id/finish_signup' => 'users#finish_signup', via: [:get, :patch], :as => :finish_signup
resources :users do
resources :profiles, only: [:new, :create]
end
user.rb
lớp người dùng < ActiveRecord :: Base
TEMP_EMAIL_PREFIX = '[email protected]'
TEMP_EMAIL_REGEX = /\[email protected]/
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:confirmable, :lockable,
# :zxcvbnable,
:omniauthable, :omniauth_providers => [:facebook, :linkedin, :twitter, :google_oauth2 ]
# --------------- associations
has_many :authentications, :dependent => :delete_all
has_one :profile
has_many :identities
# --------------- scopes
# --------------- validations
# validates_presence_of :first_name, :last_name
validates_uniqueness_of :email
# per sourcey tutorial - how do i confirm email registrations are unique?
# this is generating an error about the options in the without function -- cant figure out the solution
validates_format_of :email, :without => TEMP_EMAIL_REGEX, on: :update
# --------------- class methods
# sourcey tutorial
def self.find_for_oauth(auth, signed_in_resource = nil)
# Get the identity and user if they exist
identity = Identity.find_for_oauth(auth)
# If a signed_in_resource is provided it always overrides the existing user
# to prevent the identity being locked with accidentally created accounts.
# Note that this may leave zombie accounts (with no associated identity) which
# can be cleaned up at a later date.
user = signed_in_resource ? signed_in_resource : identity.user
# p '11111'
# Create the user if needed
if user.nil?
# p 22222
# Get the existing user by email if the provider gives us a verified email.
# If no verified email was provided we assign a temporary email and ask the
# user to verify it on the next step via UsersController.finish_signup
email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
email = auth.info.email if email_is_verified # take out this if stmt for chin yi's solution
user = User.where(:email => email).first if email
# Create the user if it's a new registration
if user.nil?
# p 33333
user = User.new(
# at least one problem with this is that each provider uses different terms to desribe first name/last name/email. See notes on linkedin above
first_name: auth.info.first_name,
last_name: auth.info.last_name,
email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
#username: auth.info.nickname || auth.uid,
password: Devise.friendly_token[0,20])
# fallback for name fields - add nickname to user table
# debugger
# if email_is_verified
user.skip_confirmation!
# end
# user.skip_confirmation!
user.save!
end
end
# Associate the identity with the user if needed
if identity.user != user
identity.user = user
identity.save!
end
user
end
def email_verified?
self.email && TEMP_EMAIL_REGEX !~ self.email
end
người dùng điều khiển
class UsersController < ApplicationController
before_action :set_user, only: [:index, :show, :edit, :update, :finish_signup, :destroy]
# i added finish_signup to the set_user action (not shown in tutorial)
def index
# if params[:approved] == "false"
# @users = User.find_all_by_approved(false)
# else
@users = User.all
# end
end
# GET /users/:id.:format
def show
# authorize! :read, @user
end
# GET /users/:id/edit
def edit
# authorize! :update, @user
end
# PATCH/PUT /users/:id.:format
def update
# authorize! :update, @user
respond_to do |format|
if @user.update(user_params)
sign_in(@user == current_user ? @user : current_user, :bypass => true)
format.html { redirect_to @user, notice: 'Your profile was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
# GET/PATCH /users/:id/finish_signup
def finish_signup
# authorize! :update, @user
if request.patch? && params[:user] #&& params[:user][:email]
if @user.update(user_params)
@user.skip_reconfirmation!
# sign_in(@user, :bypass => true)
# redirect_to root_path, notice: 'Your profile was successfully updated.'
# redirect_to [@user, @user.profile || @user.build_profile]
sign_in_and_redirect(@user, :bypass => true)
else
@show_errors = true
end
end
end
# DELETE /users/:id.:format
def destroy
# authorize! :delete, @user
@user.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
# params.require(:user).permit(policy(@user).permitted_attributes)
accessible = [ :first_name, :last_name, :email, :avatar ] # extend with your own params
accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank?
# accessible << [:approved] if user.admin
params.require(:user).permit(accessible)
end
end
callbacks omniauth khiển
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
@user = User.find_for_oauth(env["omniauth.auth"], current_user)
if @user.persisted?
sign_in_and_redirect @user, event: :authentication
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
# , current_user has been deleted from the end of line 51
#come back to put current_user into fidn by oauth so i can link other accounts - i have added this back for the purpose of solving the current problem
# puts current_user.inspect
# sign_in_and_redirect [@user, @user.profile || @user.build_profile]
# sign_in_and_redirect_user(:user, event: :authentication)
[:twitter, :facebook, :linkedin, :google_oauth2].each do |provider|
provides_callback_for provider
end
def after_sign_in_path_for(resource)
if resource.email_verified?
super resource
else
finish_signup_path(resource)
end
end
end
đăng ký điều khiển
class Users::RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
profile_path(resource)
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password)
end
end
Identity.rb
class Identity < ActiveRecord::Base
belongs_to :user
validates_presence_of :uid, :provider
validates_uniqueness_of :uid, :scope => :provider
def self.find_for_oauth(auth)
find_or_create_by(uid: auth.uid, provider: auth.provider)
end
end
Identities khiển
class IdentitiesController < ApplicationController
before_action :set_identity, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /identities
# GET /identities.json
def index
@identities = Identity.all
end
# GET /identities/1
# GET /identities/1.json
def show
end
# GET /identities/new
def new
@identity = Identity.new
end
# GET /identities/1/edit
def edit
end
# POST /identities
# POST /identities.json
def create
@identity = Identity.new(identity_params)
respond_to do |format|
if @identity.save
format.html { redirect_to @identity, notice: 'Identity was successfully created.' }
format.json { render :show, status: :created, location: @identity }
else
format.html { render :new }
format.json { render json: @identity.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /identities/1
# PATCH/PUT /identities/1.json
def update
respond_to do |format|
if @identity.update(identity_params)
format.html { redirect_to @identity, notice: 'Identity was successfully updated.' }
format.json { render :show, status: :ok, location: @identity }
else
format.html { render :edit }
format.json { render json: @identity.errors, status: :unprocessable_entity }
end
end
end
# DELETE /identities/1
# DELETE /identities/1.json
def destroy
@identity.destroy
respond_to do |format|
format.html { redirect_to identities_url, notice: 'Identity was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_identity
@identity = Identity.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def identity_params
params[:identity]
end
end
devise bưu phẩm - Xác nhận
<div class="intpol3"><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></div>
TÓM TẮT CÁC VẤN ĐỀ HIỆN:
Trong chế độ phát triển: Có một vấn đề với liên kết đến confi mã thông báo rmation. Tôi không thể tìm thấy bất kỳ tài liệu nào cho biết lý do tại sao điều này có thể phát sinh. Lỗi này là: (ActionView :: Template :: Error (phương thức undefined `match 'cho {: host =>" localhost ",: port => 3000}: Hash):
Trong chế độ sản xuất, có một Thông báo lỗi là: ActionView :: Template :: Error (Không khớp với đường dẫn {: action => "show",: controller => "profiles",: id => nil} thiếu các khóa cần thiết : [: id]):
hồ sơ của tôi đường bay:
resources :profiles, only: [:show, :edit, :update, :destroy]
resources :users do
resources :profiles, only: [:new, :create]
end
- Không ai trong số các trường trong mô hình nhận dạng được phổ biến. Tất cả chúng đều hiển thị là không.
Things Done khác biệt so với như trong Tutorial:
Tôi cũng cho phép email đăng ký
tôi thêm 'finish_sign_up' đến set_user trước khi hành động trong bộ điều khiển người dùng
Tôi thêm chiến lược g + (có nghĩa là đá quý của tôi hơi khác nhau)
Phương thức người dùng mới của tôi không sử dụng thông tin thô. Nó sử dụng thông tin được xử lý oauth.
Chuyển hướng của tôi trong phương thức đăng ký kết thúc hơi khác một chút, mặc dù tôi đã nhận xét điều đó và quay lại cách thức được nêu trong hướng dẫn để làm việc này (mặc dù các vấn đề trên đang lặp lại).
Tôi đang điên cố gắng giải quyết những vấn đề này. Tôi muốn nói 3 năm là quá lâu để bị mắc kẹt về vấn đề này. Nếu bất cứ ai có thể giúp, tôi sẽ trả tiền trước đó 10x và sau đó một số. Cảm ơn bạn.
Tôi đã làm điều này thành công. Bạn có thể xác minh từ bảng điều khiển đường ray mà hồ sơ của bạn thực sự đang được tạo không? Bạn có câu hỏi cụ thể hơn không? – errata
Có - một hồ sơ được tạo cho người dùng. Câu hỏi cụ thể của tôi là làm thế nào để tôi có được thiết lập hướng dẫn này? Lỗi hiện tại là thách thức ngay lập tức, vì vậy nếu có cách giải quyết bất cứ điều gì có thể gây ra vấn đề đó, tôi muốn bắt đầu bằng cách giải quyết điều đó. – Mel
Hi Errata - bạn đã thêm một số loại nút nào đó trong mã của bạn để cho phép người dùng (một lần trong một phiên) thêm danh tính người dùng khác? Bạn đã làm điều đó ở đâu? Tôi đang nghĩ, khi tất cả các vấn đề hiện tại được giải quyết, có thể có nghĩa là thêm nó vào phương thức đăng ký kết thúc. Bạn đã xử lý như thế nào? – Mel