2016-01-08 8 views
8

मैं रेल 4 में एक ऐप बनाने की कोशिश कर रहा हूं। मैं काम करने के लिए तैयार होने के लिए पिछले 3 वर्षों (10 दिनों के अलावा) की कोशिश कर रहा हूं। http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/रेल 4 - डेविस ओमनिथ (एकाधिक रणनीतियों)

कृपया अन्य ट्यूटोरियल/मणि प्रलेखन अनुशंसा नहीं करते हैं:

मैं इस ट्यूटोरियल का पालन करने की कोशिश कर रहा हूँ। मैंने कम से कम 30 अन्य ट्यूटोरियल की कोशिश की है और मणि दस्तावेज त्रुटियों और घटकों से भरा है जो मुझे समझ में नहीं आता है।

मेरी वर्तमान समस्या यह है कि जब मैं इस ट्यूटोरियल में फिनिश साइन अप चरण तक पहुंच जाता हूं, तो फॉर्म मुझे मेरे ईमेल पते के लिए पूछता है।

 <div class="intpol3"><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></div> 
: इस लाइन पर

undefined method `match' for {:host=>"localhost", :port=>3000}:Hash 

त्रुटि अंक:

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 

जब मैं यह कोशिश, मैं इस त्रुटि मिलती है:

उपयोगकर्ताओं नियंत्रक के रूप में एक खत्म साइनअप विधि है

मेरा विकास वातावरण मेरे ईमेल प्रेषक के लिए सभी कॉन्फ़िगरेशन विवरण शामिल करने के लिए स्थापित किया गया है।

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 
: क्योंकि मैं के रूप में मेरे उपयोगकर्ता मॉडल में एक after_create कार्रवाई

ActionView::Template::Error (No route matches {:action=>"show", :controller=>"profiles", :id=>nil} missing required keys: [:id]): 

यह एक प्रोफ़ाइल आईडी की तलाश में:

जब मैं उत्पादन मोड में एक ही कदम की कोशिश, मैं इस त्रुटि मिलती है

इस ट्यूटोरियल के साथ मेरा दूसरा मुद्दा यह है कि पहचान तालिका में फ़ील्ड पॉप्युलेट नहीं किए जा रहे हैं।

मुझे किसी ऐसे व्यक्ति को ढूंढना अच्छा लगेगा जिसने सफलतापूर्वक इस ट्यूटोरियल को कार्यान्वित किया है या यह देख सकता है कि यह काम कैसे करें।

मेरे कोड है:

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' 

मार्गों

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

वर्ग उपयोगकर्ता < ActiveRecord :: बेस

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 

उपयोगकर्ताओं नियंत्रक

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 

omniauth कॉलबैक नियंत्रक

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 

पंजीकरण नियंत्रक

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 

पहचान।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 

पहचान नियंत्रक

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 

वसीयत मेलर - पुष्टि

 <div class="intpol3"><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></div> 

वर्तमान समस्याओं का सारांश:

  1. विकास मोड में: वहाँ के साथ एक समस्या है confi के लिए लिंक rmation टोकन। मुझे कोई भी सामग्री नहीं मिल रही है जो इंगित करती है कि यह क्यों उत्पन्न हो सकता है। त्रुटि यह है: (एक्शन व्यू :: टेम्पलेट :: त्रुटि ({होस्ट => "लोकलहोस्ट",: पोर्ट => 3000}: हैश):

  2. उत्पादन मोड में, वहां एक अपरिभाषित विधि 'मिलान' है प्रोफाइल आईडी की तलाश में उपयोगकर्ता के साथ त्रुटि। त्रुटि संदेश है: एक्शन व्यू :: टेम्पलेट :: त्रुटि (कोई रूट मैचों {: action => "show",: नियंत्रक => "प्रोफाइल",: id => nil} आवश्यक कुंजी अनुपलब्ध [: id]):

मेरे प्रोफाइल मार्ग हैं:

resources :profiles, only: [:show, :edit, :update, :destroy] 
resources :users do 
    resources :profiles, only: [:new, :create] 
    end 
  1. में फ़ील्ड नहीं पहचान मॉडल populating हैं। वे सभी शून्य के रूप में दिखा रहे हैं।

कुछ अलग किया तुलना में ट्यूटोरियल में दिखाया गया है:

  1. मैं भी ईमेल

  2. मैं उन नियंत्रक में कार्रवाई से पहले set_user करने के लिए 'finish_sign_up' जोड़ने पर हस्ताक्षर की अनुमति दे

  3. मैं जी + रणनीति जोड़ता हूं (जिसका अर्थ है कि मेरे रत्न थोड़ा अलग हैं)

  4. मेरी नई उपयोगकर्ता विधि कच्ची जानकारी का उपयोग नहीं करती है। यह oauth संसाधित जानकारी का उपयोग करता है।

  5. फिनिश साइन अप विधि में मेरा रीडायरेक्ट थोड़ा अलग है, हालांकि मैंने यह टिप्पणी की है और यह काम करने के लिए ट्यूटोरियल में सेट किए गए तरीके से वापस चला गया है (हालांकि उपरोक्त समस्याएं दोहरा रही हैं)।

मैं इन समस्याओं को हल करने की कोशिश कर पागल हो रहा हूं। मैं कहूंगा कि इस समस्या पर फंसने के लिए 3 साल लंबा रास्ता है। अगर कोई मदद कर सकता है, तो मैं इसे आगे 10x और फिर कुछ भुगतान करूंगा। धन्यवाद।

+0

मैंने इसे सफलतापूर्वक किया है। क्या आप रेल कंसोल से सत्यापित कर सकते हैं कि आपकी प्रोफाइल वास्तव में बनाई जा रही हैं? क्या आपके पास एक और विशिष्ट सवाल है? – errata

+0

हां - उपयोगकर्ता के लिए प्रोफ़ाइल बनाई गई है। मेरा विशिष्ट सवाल यह है कि मैं इस ट्यूटोरियल सेटअप को कैसे प्राप्त करूं? वर्तमान त्रुटि तत्काल चुनौती है, इसलिए यदि समस्या को हल करने के लिए कोई भी तरीका हल करने का कोई तरीका है, तो मैं इसे हल करके शुरू करना चाहता हूं। – Mel

+0

हाय इरेटा - क्या आपने अन्य उपयोगकर्ता पहचान जोड़ने के लिए उपयोगकर्ताओं को (सत्र में एक बार) अनुमति देने के लिए अपने कोड में कहीं भी कुछ प्रकार का बटन जोड़ा था? तुमने ऐसा कहाँ किया? मैं सोच रहा हूं, जब सभी मौजूदा समस्याओं का समाधान हो जाता है, तो संभवतः इसे साइन अप विधि में जोड़ने का अर्थ होता है। आपने इसे कैसे संभाला? – Mel

उत्तर

1
<div class="intpol3"><%= link_to 'Confirm my account', 
    confirmation_url(@resource, confirmation_token: @token) %></div> 

resource बजाय @resource की कोशिश करो। AFAIK यह केवल एक helper_method है, उदाहरण आवृत्ति नहीं है।

मुझे लगता है कि उत्पादन में पूरी तरह से आपकी समस्या का समाधान होगा। चूंकि @resourceresource जैसा नहीं है, इसलिए यह सेट नहीं किया गया है, और आप मूल रूप से confirmation_url(nil, confirmation_token: @token) पर कॉल कर रहे हैं, और nil त्रुटि संदेश के माध्यम से पारित हो रहा है।

विकास में, वहाँ एक अतिरिक्त मुद्दा है, जो सबसे शायद तुम कैसे config/environments/development.rb में config.action_mailer.default_url_options कॉन्फ़िगर कर दिया है और सबसे अधिक संभावना ActionDispatch::Http::Url.build_host_url में अपवाद बढ़ा रहा है के साथ क्या करना है प्रतीत होता है। मुझे लगता है कि आप की तरह कुछ है:

है कि
config.action_mailer.default_url_options[:host] = { host: 'localhost', port: 9000 } 

बदलें:

config.action_mailer.default_url_options[:host] = 'localhost:9000' 

और देखते हैं कि अगर सब कुछ हल करती है। अगर मैं config.action_mailer.default_url_options कॉन्फ़िगर करने के बारे में गलत हूं, तो कृपया अपने config/environments/development.rb और अपनी विकास त्रुटि से एक पूर्ण स्टैक ट्रेस पेस्ट करें ताकि हम आपकी सहायता कर सकें।

संबंधित मुद्दे