Ruby on rails Omniauth Facebook的其他用户属性验证失败

Ruby on rails Omniauth Facebook的其他用户属性验证失败,ruby-on-rails,ruby,facebook,devise,omniauth-facebook,Ruby On Rails,Ruby,Facebook,Devise,Omniauth Facebook,大家好,感谢您的专业知识和帮助 我对RubyonRails不是很熟练(刚开始于3个月前),我正在构建一个相当复杂的应用程序。关于Omniauth Facebook,我遇到了一个障碍。我有Devise、omniauth facebook、omniauth_回调控制器、Devise registrations_控制器、Devise users_控制器和一个用户模型,其中包含多个字段的验证(请参阅下面的所有代码)。在设置所有这些时,我或多或少地遵循了这个Youtube视频:以及许多其他分散的指南,当我

大家好,感谢您的专业知识和帮助

我对RubyonRails不是很熟练(刚开始于3个月前),我正在构建一个相当复杂的应用程序。关于Omniauth Facebook,我遇到了一个障碍。我有Devise、omniauth facebook、omniauth_回调控制器、Devise registrations_控制器、Devise users_控制器和一个用户模型,其中包含多个字段的验证(请参阅下面的所有代码)。在设置所有这些时,我或多或少地遵循了这个Youtube视频:以及许多其他分散的指南,当我尝试排除故障时。有些已经过时了,我甚至不确定我的代码中哪些部分可能已经过时了

我的注册表单的作用:用户可以填写我的自定义注册表单,并将其正确添加到数据库中,所有设计操作都正常运行,所有自定义表属性都被记录。用户可以单击“使用Facebook注册”按钮,并被引导到Facebook进行登录/注册,其中将返回提供商和UID,以及(似乎)姓名、电子邮件和密码。在我的模式中,State和Zip是默认的,因此不会引发验证异常

失败之处:当Facebook发回信息时,它似乎在回复电子邮件时中断(“用户存在”)。尽管我已经包含了“auth.info.last_name、auth.info.image等”,但终端错误从未显示从Facebook返回的其他字段,但验证不会引发异常,包括电子邮件。在我的数据库中,我确保没有重复的电子邮件。由于我的DB和验证,似乎我所需的姓氏、性别、出生日期、地址和城市也没有填写,这是可以理解的(除了姓氏),因为我无法从Facebook收到这些信息

这就是我想要的:如上所述,Facebook似乎没有返回“姓氏”、“地址”或“图片”。我还需要包括出生日期,性别和他们的城市。似乎我不能在omniauth facebook上这样做,因为facebook的Auth哈希不包括这些字段。我如何允许用户通过Facebook使用提供的字段注册,通过Facebook登录,然后直接进入一个页面,在那里他们可以输入数据库所需的其他缺失信息?那么,在通过facebook注册之后,我如何让用户被发送到另一个页面(没有抛出那些验证异常?),然后输入附加信息(姓氏、出生日期、地址、地址2[如果需要]、性别、城市/州/邮编,或/或其他任何缺失的字段)?为什么“姓氏”可能会失败,但“名字”可以

下面是你们可能需要的所有东西的图片,我认为可能需要。再一次,我理解了Ruby和Rails的基本原理,并认为自己是中间人,但需要帮助理解为什么/如何回答我正在经历的这个问题。遗憾的是,我缺乏关于高级路线和控制器如何工作的知识,因此,如果您有任何资源可以帮助我提高这方面的知识,我也将不胜感激

用户表(schema.rb):

  create_table "users", force: :cascade do |t|
    t.string "first_name", null: false
    t.string "last_name", null: false
    t.boolean "admin", default: false
    t.boolean "subscribed", default: true
    t.string "zip", default: "44107", null: false
    t.string "phone_number"
    t.string "address", null: false
    t.string "city_name", default: "Lakewood", null: false
    t.string "state", default: "Ohio", null: false
    t.date "dob", null: false
    t.integer "city_id"
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.string "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string "unconfirmed_email"
    t.integer "failed_attempts", default: 0, null: false
    t.string "unlock_token"
    t.datetime "locked_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "address2"
    t.boolean "gender"
    t.string "provider"
    t.string "uid"
    t.string "name"
    t.text "image"
    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
  end 
class User < ApplicationRecord
      # Below - Devise Modules. We have not used = :timeoutable 
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, 
             :validatable, :confirmable, 
             :omniauthable, omniauth_providers: [:facebook]

      # Below - Additional validations of DB field entries presence at Model-level.
      validates :first_name, presence: true, length: { maximum: 30 }
      validates :last_name, presence: true, length: { maximum: 30 }
      validates :dob, presence: { message: "(Date of Birth) must be entered" } 
      validates :zip, presence: true, length: { maximum: 11 }
      validates :city_name, presence: true   
      validates :state, presence: true, length: { maximum: 15 }
      validates :address, presence: true
      validates :gender, presence: { message: "must be selected" } 

       # Below - Associates Users into a One to Many relationship with Cities.
      belongs_to :city


      def self.new_with_session(params, session)
        super.tap do |user|
          if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
            user.email = data["email"] if user.email.blank?
          end
        end
      end


      def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_create! do |user|
          user.provider       = auth.provider
          user.uid            = auth.uid
          user.email          = auth.info.email
          user.first_name     = auth.info.first_name
          user.password       = Devise.friendly_token[0,20] 
          user.last_name      = auth.info.last_name
          user.image          = auth.info.image
          user.address        = auth.info.location
          user.skip_confirmation!

          user.save

      end


      end

      # Below - Turns emails into downcase when saved from the controller into DB.      
      before_save { self.email = email.downcase }

    end
class Users::SessionsController < Devise::SessionsController
  # before_action :configure_sign_in_params, only: [:create]
  class SessionsController < ApplicationController
    def create
      @user = User.find_or_create_from_auth_hash(auth_hash)
      self.current_user = @user
      redirect_to '/'
    end

    protected

    def auth_hash
      request.env['omniauth.auth']
    end
  end
class Users::RegistrationsController < Devise::RegistrationsController
   before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
   def new
     @user = User.new
   end

  # POST /resource
  def create
    super
  end

  # GET /resource/edit
   def edit
     super
   end

  # PUT /resource
   def update
     super
   end

  protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :gender, :dob, :admin, :phone_number, :address, :address2, :city_name, :state, :zip, :subscribed, :city_id, :name, :image, :uid, :provider])
  end

end 
class UsersController < ApplicationController

    # Main Users Controller

      # Index Action for all Users
      def index
        @users = User.all
      end

      # Show Action for individual user ID
      def show 
        @user = User.find(params[:id])
      end 
    end
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Main MOdel for Facebook OmniAuth User Login/Signup

  def facebook
    #raise request.env["omniauth.auth"].to_yaml
    @user = User.from_omniauth(request.env["omniauth.auth"])

    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

  def failure
    redirect_to root_path
  end

end
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?

# Below, permits strong params from signup process, sign_in, and Account_update
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:login, keys: [:email, :password])
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :address, :address2, :dob, :city_name, :state, :zip, :gender, :phone_number, :subscribed, :email, :password, :password_confirmation, :city_id, :name, :image, :uid, :provider]) 
    devise_parameter_sanitizer.permit(:account_update, keys: [:email, :address, :address2, :city_name, :state, :zip, :phone_number, :subscribed, :password, :password_confirmation, :current_password])
  end

end
 # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  config.omniauth :facebook, 'BLANK', 'BLANK', callback_url: 'MYWEBADRESS/users/auth/facebook/callback'
Rails.application.routes.draw do
# Main Routes file for all route, URL names and Action Methods. 

  # Below - Sets up custom login and log out path names for routes for user model.
  devise_for :users, path_names: { sign_in: "login", sign_out: "logout" }, controllers: {
                                    sessions: 'users/sessions', 
                                    :omniauth_callbacks => "users/omniauth_callbacks"   }

  # Not logged in visitors will be greeted by Index page
  root 'visitors#index'

  get 'cities/index'

  # Callback Route after OmniAuth redirects back to Ossemble for User Signup
  get '/auth/facebook/callback', to: 'sessions#create'

  # Below - Sets up routes for admin model.
  devise_for :admins

  # Below - Creates all routes for City model.
  resources :cities, except: [:destroy]

  # Below - Creates show route for Users & Model
  resources :users, only: [:show, :index]

end
<%= form_for(resource, as: resource_name, url: registration_path(resource_name),
      :html => {class: "form", role: "form"}) do |f| %>
    <div class="container alert"> <!-- Begin - Error Message(s) Wrapper for User Signup -->
      <%= devise_error_messages! %>
    </div>                        <!-- End - Error Message(s) Wrapper for User Signup -->
    <div class="container"> <!-- Begin -- Signup Form -->
      <div class="form-row"> <!-- Begin - First, Last Name, Gender, & Date of Birth Form Row -->
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :first_name, "First Name" %> 
          </div>
            <%= f.text_field :first_name, autofocus: true, class: "form-control", placeholder: "Enter First Name" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :last_name, "Last Name" %> 
          </div>
            <%= f.text_field :last_name, class: "form-control", placeholder: "Enter Last Name" %>
        </div>
       <div class="form-group col-md-2">
          <div class="control-label">
            <label class="control-label"> 
            Gender
            </label>
          </div>   
            <div class="gender_form form-control center" >
              <%= f.label :gender, "Male", id: "male_text", class: "gender_text" %>
              <%= f.radio_button :gender, true,  class: "gender_box"%>
              <%= f.label :gender, "Female", id: "female_text", class: "gender_text" %>
              <%= f.radio_button :gender, false, class: "gender_box" %>
            </div>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :dob, "Birth Date" %> 
          </div>
            <%= f.date_field :dob, class: "form-control" %>
        </div>
      </div> 
      <br> <!-- End - of Name, Gender & DOB form row -->

    <!-- Begin - Email & Password Form Row -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :email, "Email Address" %>
          </div>
            <%= f.email_field :email, type:"text", class: "form-control", placeholder: "Enter Email Address: youremail@example.com" %>
        </div>  
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password, "Password" %>
            <!-- Begin - If statement checks for password minimum character length  -->
            <small>
              (Minimum: <%= @minimum_password_length %> characters) 
            </small>
          </div>
            <%= f.password_field :password, autocomplete: "off", id:"inputPassword", class: "form-control", placeholder: "Create a Password" %>
          <!-- End - password character length if statement -->
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password_confirmation, "Confirm Password" %> 
          </div>  
            <%= f.password_field :password_confirmation, autocomplete: "off", id:"inputPasswordConfirm", class: "form-control", placeholder: "Re-enter Password" %>
        </div>
      </div> 
      <br> <!-- End - Email & Password Form Row -->

    <!-- Begin -  Address & Phone Number Form Row--> 
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address, "Primary Address" %> 
            </div>
            <%= f.text_field :address, autocomplete: "on", class: "form-control", placeholder: "Enter Address: 1234 Main Street" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address2, "Secondary Address" %> <small> (optional) </small>
          </div>
            <%= f.text_field :address2, autocomplete: "on", class: "form-control", placeholder: "Apartment, Suite #" %>
        </div>
        <!--  Phonne number currently hideen on form due to "style-" and "disabled :true" -->
        <div class="form-group col-md-3" style="display: none">
          <div class="control-label">
            <%= f.label :phone_number, "Phone Number" %> 
          </div>
            <%= f.phone_field :phone_number, disabled: true, class: "form-control", placeholder: "Enter Phone #: 555-555-5555" %>
        </div>
      </div> <br> <!-- End - Address & Phone Number Row -->

  <!--  Beginning - Location Form Row  -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :city_name, "City" %> 
              <small>
                (Currently Lakewood, OH Supported)
              </small>
          </div> 
<!-- Below, we list all cities to be selected and we set the user's "city_id" field to the corresponding City table's City ID, completing the User's Association to City  -->
            <%= f.collection_select :city_id, City.all, :id, :name, {prompt: "Choose a City"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2 ">
          <div class="control-label">
            <%= f.label :state, "State" %> 
              <small>
                (Currently Ohio)
              </small>
          </div>
            <%= f.collection_select :state, City.all, :state, :state, {prompt: "Choose a State"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :zip, "Zip Code" %> <small> (5-Digit Zip)</small>
          </div>
            <%= f.collection_select :zip, City.all, :zip, :zip, {prompt: "Choose Zip-Code"}, maxlength: "5", class: "select_form form-control" %>
        </div>
      </div> <!--  End - Location Form Row -->

    <!-- Begin - Subscribe Option -->
      <div class="form-row">
        <div class="form-group col-md-12 pull-left">
          <div class="form-check">
            <div class="control-label">
              <%= f.label :subscribed, "Subscribe?" %> 
                <small>
                  <em>
                  Stay up to date with Ossemble!
                  </em>
                </small> 
              <br>
              <div class="form-row pull-left">  
                <div class="col-md-12">
                  <div>
                    <%= f.check_box :subscribed, class: "check_box"  %>
                    <%= f.label "Yes!", class: "check_box_label"  %>
                  </div>
                </div>
              </div>
            </div> 
          </div> 
        </div>
      </div> <!-- End - Subscribe Option -->
      <div class="form-row"> <!-- Begin - Create Account Button Row (FB) -->  
        <div class="form-group col-md-2">
          <div class="actions">
            <%= f.submit "Create Account", class: "form_btn btn btn-success btn-lg btn-xlarge" %>
          </div>
        </div> 
        <div class="form-group col-md-4"> <!-- Begin - Signup With Facebook Button -->
          <%- if devise_mapping.omniauthable? %> <!-- Begin - OmniAuth If Statement -->
              <!-- Below - OmniAuth & FB Signup Button -->
              **<%= link_to '<i class="fa fa-facebook fa-lg fa-fw fb_log_sign_icon" aria-hidden="true"></i> Facebook Signup'.html_safe, 
                                     user_facebook_omniauth_authorize_path, 
                                     class: "form_btn btn btn-primary btn-lg btn-xlarge" %> <br />
          <% end -%>**                  <!-- End - OmniAuth If Statement -->
        </div>                        <!-- End - Signup with Facebook Button -->
      </div>                 <!-- End - Create Account Button Row (FB) -->
    </div>                  <!-- End - Signup Form -->
<% end %> 
用户模型(user.rb):

  create_table "users", force: :cascade do |t|
    t.string "first_name", null: false
    t.string "last_name", null: false
    t.boolean "admin", default: false
    t.boolean "subscribed", default: true
    t.string "zip", default: "44107", null: false
    t.string "phone_number"
    t.string "address", null: false
    t.string "city_name", default: "Lakewood", null: false
    t.string "state", default: "Ohio", null: false
    t.date "dob", null: false
    t.integer "city_id"
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.string "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string "unconfirmed_email"
    t.integer "failed_attempts", default: 0, null: false
    t.string "unlock_token"
    t.datetime "locked_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "address2"
    t.boolean "gender"
    t.string "provider"
    t.string "uid"
    t.string "name"
    t.text "image"
    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
  end 
class User < ApplicationRecord
      # Below - Devise Modules. We have not used = :timeoutable 
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, 
             :validatable, :confirmable, 
             :omniauthable, omniauth_providers: [:facebook]

      # Below - Additional validations of DB field entries presence at Model-level.
      validates :first_name, presence: true, length: { maximum: 30 }
      validates :last_name, presence: true, length: { maximum: 30 }
      validates :dob, presence: { message: "(Date of Birth) must be entered" } 
      validates :zip, presence: true, length: { maximum: 11 }
      validates :city_name, presence: true   
      validates :state, presence: true, length: { maximum: 15 }
      validates :address, presence: true
      validates :gender, presence: { message: "must be selected" } 

       # Below - Associates Users into a One to Many relationship with Cities.
      belongs_to :city


      def self.new_with_session(params, session)
        super.tap do |user|
          if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
            user.email = data["email"] if user.email.blank?
          end
        end
      end


      def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_create! do |user|
          user.provider       = auth.provider
          user.uid            = auth.uid
          user.email          = auth.info.email
          user.first_name     = auth.info.first_name
          user.password       = Devise.friendly_token[0,20] 
          user.last_name      = auth.info.last_name
          user.image          = auth.info.image
          user.address        = auth.info.location
          user.skip_confirmation!

          user.save

      end


      end

      # Below - Turns emails into downcase when saved from the controller into DB.      
      before_save { self.email = email.downcase }

    end
class Users::SessionsController < Devise::SessionsController
  # before_action :configure_sign_in_params, only: [:create]
  class SessionsController < ApplicationController
    def create
      @user = User.find_or_create_from_auth_hash(auth_hash)
      self.current_user = @user
      redirect_to '/'
    end

    protected

    def auth_hash
      request.env['omniauth.auth']
    end
  end
class Users::RegistrationsController < Devise::RegistrationsController
   before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
   def new
     @user = User.new
   end

  # POST /resource
  def create
    super
  end

  # GET /resource/edit
   def edit
     super
   end

  # PUT /resource
   def update
     super
   end

  protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :gender, :dob, :admin, :phone_number, :address, :address2, :city_name, :state, :zip, :subscribed, :city_id, :name, :image, :uid, :provider])
  end

end 
class UsersController < ApplicationController

    # Main Users Controller

      # Index Action for all Users
      def index
        @users = User.all
      end

      # Show Action for individual user ID
      def show 
        @user = User.find(params[:id])
      end 
    end
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Main MOdel for Facebook OmniAuth User Login/Signup

  def facebook
    #raise request.env["omniauth.auth"].to_yaml
    @user = User.from_omniauth(request.env["omniauth.auth"])

    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

  def failure
    redirect_to root_path
  end

end
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?

# Below, permits strong params from signup process, sign_in, and Account_update
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:login, keys: [:email, :password])
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :address, :address2, :dob, :city_name, :state, :zip, :gender, :phone_number, :subscribed, :email, :password, :password_confirmation, :city_id, :name, :image, :uid, :provider]) 
    devise_parameter_sanitizer.permit(:account_update, keys: [:email, :address, :address2, :city_name, :state, :zip, :phone_number, :subscribed, :password, :password_confirmation, :current_password])
  end

end
 # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  config.omniauth :facebook, 'BLANK', 'BLANK', callback_url: 'MYWEBADRESS/users/auth/facebook/callback'
Rails.application.routes.draw do
# Main Routes file for all route, URL names and Action Methods. 

  # Below - Sets up custom login and log out path names for routes for user model.
  devise_for :users, path_names: { sign_in: "login", sign_out: "logout" }, controllers: {
                                    sessions: 'users/sessions', 
                                    :omniauth_callbacks => "users/omniauth_callbacks"   }

  # Not logged in visitors will be greeted by Index page
  root 'visitors#index'

  get 'cities/index'

  # Callback Route after OmniAuth redirects back to Ossemble for User Signup
  get '/auth/facebook/callback', to: 'sessions#create'

  # Below - Sets up routes for admin model.
  devise_for :admins

  # Below - Creates all routes for City model.
  resources :cities, except: [:destroy]

  # Below - Creates show route for Users & Model
  resources :users, only: [:show, :index]

end
<%= form_for(resource, as: resource_name, url: registration_path(resource_name),
      :html => {class: "form", role: "form"}) do |f| %>
    <div class="container alert"> <!-- Begin - Error Message(s) Wrapper for User Signup -->
      <%= devise_error_messages! %>
    </div>                        <!-- End - Error Message(s) Wrapper for User Signup -->
    <div class="container"> <!-- Begin -- Signup Form -->
      <div class="form-row"> <!-- Begin - First, Last Name, Gender, & Date of Birth Form Row -->
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :first_name, "First Name" %> 
          </div>
            <%= f.text_field :first_name, autofocus: true, class: "form-control", placeholder: "Enter First Name" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :last_name, "Last Name" %> 
          </div>
            <%= f.text_field :last_name, class: "form-control", placeholder: "Enter Last Name" %>
        </div>
       <div class="form-group col-md-2">
          <div class="control-label">
            <label class="control-label"> 
            Gender
            </label>
          </div>   
            <div class="gender_form form-control center" >
              <%= f.label :gender, "Male", id: "male_text", class: "gender_text" %>
              <%= f.radio_button :gender, true,  class: "gender_box"%>
              <%= f.label :gender, "Female", id: "female_text", class: "gender_text" %>
              <%= f.radio_button :gender, false, class: "gender_box" %>
            </div>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :dob, "Birth Date" %> 
          </div>
            <%= f.date_field :dob, class: "form-control" %>
        </div>
      </div> 
      <br> <!-- End - of Name, Gender & DOB form row -->

    <!-- Begin - Email & Password Form Row -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :email, "Email Address" %>
          </div>
            <%= f.email_field :email, type:"text", class: "form-control", placeholder: "Enter Email Address: youremail@example.com" %>
        </div>  
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password, "Password" %>
            <!-- Begin - If statement checks for password minimum character length  -->
            <small>
              (Minimum: <%= @minimum_password_length %> characters) 
            </small>
          </div>
            <%= f.password_field :password, autocomplete: "off", id:"inputPassword", class: "form-control", placeholder: "Create a Password" %>
          <!-- End - password character length if statement -->
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password_confirmation, "Confirm Password" %> 
          </div>  
            <%= f.password_field :password_confirmation, autocomplete: "off", id:"inputPasswordConfirm", class: "form-control", placeholder: "Re-enter Password" %>
        </div>
      </div> 
      <br> <!-- End - Email & Password Form Row -->

    <!-- Begin -  Address & Phone Number Form Row--> 
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address, "Primary Address" %> 
            </div>
            <%= f.text_field :address, autocomplete: "on", class: "form-control", placeholder: "Enter Address: 1234 Main Street" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address2, "Secondary Address" %> <small> (optional) </small>
          </div>
            <%= f.text_field :address2, autocomplete: "on", class: "form-control", placeholder: "Apartment, Suite #" %>
        </div>
        <!--  Phonne number currently hideen on form due to "style-" and "disabled :true" -->
        <div class="form-group col-md-3" style="display: none">
          <div class="control-label">
            <%= f.label :phone_number, "Phone Number" %> 
          </div>
            <%= f.phone_field :phone_number, disabled: true, class: "form-control", placeholder: "Enter Phone #: 555-555-5555" %>
        </div>
      </div> <br> <!-- End - Address & Phone Number Row -->

  <!--  Beginning - Location Form Row  -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :city_name, "City" %> 
              <small>
                (Currently Lakewood, OH Supported)
              </small>
          </div> 
<!-- Below, we list all cities to be selected and we set the user's "city_id" field to the corresponding City table's City ID, completing the User's Association to City  -->
            <%= f.collection_select :city_id, City.all, :id, :name, {prompt: "Choose a City"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2 ">
          <div class="control-label">
            <%= f.label :state, "State" %> 
              <small>
                (Currently Ohio)
              </small>
          </div>
            <%= f.collection_select :state, City.all, :state, :state, {prompt: "Choose a State"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :zip, "Zip Code" %> <small> (5-Digit Zip)</small>
          </div>
            <%= f.collection_select :zip, City.all, :zip, :zip, {prompt: "Choose Zip-Code"}, maxlength: "5", class: "select_form form-control" %>
        </div>
      </div> <!--  End - Location Form Row -->

    <!-- Begin - Subscribe Option -->
      <div class="form-row">
        <div class="form-group col-md-12 pull-left">
          <div class="form-check">
            <div class="control-label">
              <%= f.label :subscribed, "Subscribe?" %> 
                <small>
                  <em>
                  Stay up to date with Ossemble!
                  </em>
                </small> 
              <br>
              <div class="form-row pull-left">  
                <div class="col-md-12">
                  <div>
                    <%= f.check_box :subscribed, class: "check_box"  %>
                    <%= f.label "Yes!", class: "check_box_label"  %>
                  </div>
                </div>
              </div>
            </div> 
          </div> 
        </div>
      </div> <!-- End - Subscribe Option -->
      <div class="form-row"> <!-- Begin - Create Account Button Row (FB) -->  
        <div class="form-group col-md-2">
          <div class="actions">
            <%= f.submit "Create Account", class: "form_btn btn btn-success btn-lg btn-xlarge" %>
          </div>
        </div> 
        <div class="form-group col-md-4"> <!-- Begin - Signup With Facebook Button -->
          <%- if devise_mapping.omniauthable? %> <!-- Begin - OmniAuth If Statement -->
              <!-- Below - OmniAuth & FB Signup Button -->
              **<%= link_to '<i class="fa fa-facebook fa-lg fa-fw fb_log_sign_icon" aria-hidden="true"></i> Facebook Signup'.html_safe, 
                                     user_facebook_omniauth_authorize_path, 
                                     class: "form_btn btn btn-primary btn-lg btn-xlarge" %> <br />
          <% end -%>**                  <!-- End - OmniAuth If Statement -->
        </div>                        <!-- End - Signup with Facebook Button -->
      </div>                 <!-- End - Create Account Button Row (FB) -->
    </div>                  <!-- End - Signup Form -->
<% end %> 
路线(Routes.rb):

  create_table "users", force: :cascade do |t|
    t.string "first_name", null: false
    t.string "last_name", null: false
    t.boolean "admin", default: false
    t.boolean "subscribed", default: true
    t.string "zip", default: "44107", null: false
    t.string "phone_number"
    t.string "address", null: false
    t.string "city_name", default: "Lakewood", null: false
    t.string "state", default: "Ohio", null: false
    t.date "dob", null: false
    t.integer "city_id"
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.string "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string "unconfirmed_email"
    t.integer "failed_attempts", default: 0, null: false
    t.string "unlock_token"
    t.datetime "locked_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "address2"
    t.boolean "gender"
    t.string "provider"
    t.string "uid"
    t.string "name"
    t.text "image"
    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
  end 
class User < ApplicationRecord
      # Below - Devise Modules. We have not used = :timeoutable 
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, 
             :validatable, :confirmable, 
             :omniauthable, omniauth_providers: [:facebook]

      # Below - Additional validations of DB field entries presence at Model-level.
      validates :first_name, presence: true, length: { maximum: 30 }
      validates :last_name, presence: true, length: { maximum: 30 }
      validates :dob, presence: { message: "(Date of Birth) must be entered" } 
      validates :zip, presence: true, length: { maximum: 11 }
      validates :city_name, presence: true   
      validates :state, presence: true, length: { maximum: 15 }
      validates :address, presence: true
      validates :gender, presence: { message: "must be selected" } 

       # Below - Associates Users into a One to Many relationship with Cities.
      belongs_to :city


      def self.new_with_session(params, session)
        super.tap do |user|
          if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
            user.email = data["email"] if user.email.blank?
          end
        end
      end


      def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_create! do |user|
          user.provider       = auth.provider
          user.uid            = auth.uid
          user.email          = auth.info.email
          user.first_name     = auth.info.first_name
          user.password       = Devise.friendly_token[0,20] 
          user.last_name      = auth.info.last_name
          user.image          = auth.info.image
          user.address        = auth.info.location
          user.skip_confirmation!

          user.save

      end


      end

      # Below - Turns emails into downcase when saved from the controller into DB.      
      before_save { self.email = email.downcase }

    end
class Users::SessionsController < Devise::SessionsController
  # before_action :configure_sign_in_params, only: [:create]
  class SessionsController < ApplicationController
    def create
      @user = User.find_or_create_from_auth_hash(auth_hash)
      self.current_user = @user
      redirect_to '/'
    end

    protected

    def auth_hash
      request.env['omniauth.auth']
    end
  end
class Users::RegistrationsController < Devise::RegistrationsController
   before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
   def new
     @user = User.new
   end

  # POST /resource
  def create
    super
  end

  # GET /resource/edit
   def edit
     super
   end

  # PUT /resource
   def update
     super
   end

  protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :gender, :dob, :admin, :phone_number, :address, :address2, :city_name, :state, :zip, :subscribed, :city_id, :name, :image, :uid, :provider])
  end

end 
class UsersController < ApplicationController

    # Main Users Controller

      # Index Action for all Users
      def index
        @users = User.all
      end

      # Show Action for individual user ID
      def show 
        @user = User.find(params[:id])
      end 
    end
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Main MOdel for Facebook OmniAuth User Login/Signup

  def facebook
    #raise request.env["omniauth.auth"].to_yaml
    @user = User.from_omniauth(request.env["omniauth.auth"])

    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

  def failure
    redirect_to root_path
  end

end
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?

# Below, permits strong params from signup process, sign_in, and Account_update
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:login, keys: [:email, :password])
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :address, :address2, :dob, :city_name, :state, :zip, :gender, :phone_number, :subscribed, :email, :password, :password_confirmation, :city_id, :name, :image, :uid, :provider]) 
    devise_parameter_sanitizer.permit(:account_update, keys: [:email, :address, :address2, :city_name, :state, :zip, :phone_number, :subscribed, :password, :password_confirmation, :current_password])
  end

end
 # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  config.omniauth :facebook, 'BLANK', 'BLANK', callback_url: 'MYWEBADRESS/users/auth/facebook/callback'
Rails.application.routes.draw do
# Main Routes file for all route, URL names and Action Methods. 

  # Below - Sets up custom login and log out path names for routes for user model.
  devise_for :users, path_names: { sign_in: "login", sign_out: "logout" }, controllers: {
                                    sessions: 'users/sessions', 
                                    :omniauth_callbacks => "users/omniauth_callbacks"   }

  # Not logged in visitors will be greeted by Index page
  root 'visitors#index'

  get 'cities/index'

  # Callback Route after OmniAuth redirects back to Ossemble for User Signup
  get '/auth/facebook/callback', to: 'sessions#create'

  # Below - Sets up routes for admin model.
  devise_for :admins

  # Below - Creates all routes for City model.
  resources :cities, except: [:destroy]

  # Below - Creates show route for Users & Model
  resources :users, only: [:show, :index]

end
<%= form_for(resource, as: resource_name, url: registration_path(resource_name),
      :html => {class: "form", role: "form"}) do |f| %>
    <div class="container alert"> <!-- Begin - Error Message(s) Wrapper for User Signup -->
      <%= devise_error_messages! %>
    </div>                        <!-- End - Error Message(s) Wrapper for User Signup -->
    <div class="container"> <!-- Begin -- Signup Form -->
      <div class="form-row"> <!-- Begin - First, Last Name, Gender, & Date of Birth Form Row -->
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :first_name, "First Name" %> 
          </div>
            <%= f.text_field :first_name, autofocus: true, class: "form-control", placeholder: "Enter First Name" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :last_name, "Last Name" %> 
          </div>
            <%= f.text_field :last_name, class: "form-control", placeholder: "Enter Last Name" %>
        </div>
       <div class="form-group col-md-2">
          <div class="control-label">
            <label class="control-label"> 
            Gender
            </label>
          </div>   
            <div class="gender_form form-control center" >
              <%= f.label :gender, "Male", id: "male_text", class: "gender_text" %>
              <%= f.radio_button :gender, true,  class: "gender_box"%>
              <%= f.label :gender, "Female", id: "female_text", class: "gender_text" %>
              <%= f.radio_button :gender, false, class: "gender_box" %>
            </div>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :dob, "Birth Date" %> 
          </div>
            <%= f.date_field :dob, class: "form-control" %>
        </div>
      </div> 
      <br> <!-- End - of Name, Gender & DOB form row -->

    <!-- Begin - Email & Password Form Row -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :email, "Email Address" %>
          </div>
            <%= f.email_field :email, type:"text", class: "form-control", placeholder: "Enter Email Address: youremail@example.com" %>
        </div>  
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password, "Password" %>
            <!-- Begin - If statement checks for password minimum character length  -->
            <small>
              (Minimum: <%= @minimum_password_length %> characters) 
            </small>
          </div>
            <%= f.password_field :password, autocomplete: "off", id:"inputPassword", class: "form-control", placeholder: "Create a Password" %>
          <!-- End - password character length if statement -->
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password_confirmation, "Confirm Password" %> 
          </div>  
            <%= f.password_field :password_confirmation, autocomplete: "off", id:"inputPasswordConfirm", class: "form-control", placeholder: "Re-enter Password" %>
        </div>
      </div> 
      <br> <!-- End - Email & Password Form Row -->

    <!-- Begin -  Address & Phone Number Form Row--> 
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address, "Primary Address" %> 
            </div>
            <%= f.text_field :address, autocomplete: "on", class: "form-control", placeholder: "Enter Address: 1234 Main Street" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address2, "Secondary Address" %> <small> (optional) </small>
          </div>
            <%= f.text_field :address2, autocomplete: "on", class: "form-control", placeholder: "Apartment, Suite #" %>
        </div>
        <!--  Phonne number currently hideen on form due to "style-" and "disabled :true" -->
        <div class="form-group col-md-3" style="display: none">
          <div class="control-label">
            <%= f.label :phone_number, "Phone Number" %> 
          </div>
            <%= f.phone_field :phone_number, disabled: true, class: "form-control", placeholder: "Enter Phone #: 555-555-5555" %>
        </div>
      </div> <br> <!-- End - Address & Phone Number Row -->

  <!--  Beginning - Location Form Row  -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :city_name, "City" %> 
              <small>
                (Currently Lakewood, OH Supported)
              </small>
          </div> 
<!-- Below, we list all cities to be selected and we set the user's "city_id" field to the corresponding City table's City ID, completing the User's Association to City  -->
            <%= f.collection_select :city_id, City.all, :id, :name, {prompt: "Choose a City"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2 ">
          <div class="control-label">
            <%= f.label :state, "State" %> 
              <small>
                (Currently Ohio)
              </small>
          </div>
            <%= f.collection_select :state, City.all, :state, :state, {prompt: "Choose a State"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :zip, "Zip Code" %> <small> (5-Digit Zip)</small>
          </div>
            <%= f.collection_select :zip, City.all, :zip, :zip, {prompt: "Choose Zip-Code"}, maxlength: "5", class: "select_form form-control" %>
        </div>
      </div> <!--  End - Location Form Row -->

    <!-- Begin - Subscribe Option -->
      <div class="form-row">
        <div class="form-group col-md-12 pull-left">
          <div class="form-check">
            <div class="control-label">
              <%= f.label :subscribed, "Subscribe?" %> 
                <small>
                  <em>
                  Stay up to date with Ossemble!
                  </em>
                </small> 
              <br>
              <div class="form-row pull-left">  
                <div class="col-md-12">
                  <div>
                    <%= f.check_box :subscribed, class: "check_box"  %>
                    <%= f.label "Yes!", class: "check_box_label"  %>
                  </div>
                </div>
              </div>
            </div> 
          </div> 
        </div>
      </div> <!-- End - Subscribe Option -->
      <div class="form-row"> <!-- Begin - Create Account Button Row (FB) -->  
        <div class="form-group col-md-2">
          <div class="actions">
            <%= f.submit "Create Account", class: "form_btn btn btn-success btn-lg btn-xlarge" %>
          </div>
        </div> 
        <div class="form-group col-md-4"> <!-- Begin - Signup With Facebook Button -->
          <%- if devise_mapping.omniauthable? %> <!-- Begin - OmniAuth If Statement -->
              <!-- Below - OmniAuth & FB Signup Button -->
              **<%= link_to '<i class="fa fa-facebook fa-lg fa-fw fb_log_sign_icon" aria-hidden="true"></i> Facebook Signup'.html_safe, 
                                     user_facebook_omniauth_authorize_path, 
                                     class: "form_btn btn btn-primary btn-lg btn-xlarge" %> <br />
          <% end -%>**                  <!-- End - OmniAuth If Statement -->
        </div>                        <!-- End - Signup with Facebook Button -->
      </div>                 <!-- End - Create Account Button Row (FB) -->
    </div>                  <!-- End - Signup Form -->
<% end %> 
最后是我的注册表格(views/design/registrations/new.html.erb):

  create_table "users", force: :cascade do |t|
    t.string "first_name", null: false
    t.string "last_name", null: false
    t.boolean "admin", default: false
    t.boolean "subscribed", default: true
    t.string "zip", default: "44107", null: false
    t.string "phone_number"
    t.string "address", null: false
    t.string "city_name", default: "Lakewood", null: false
    t.string "state", default: "Ohio", null: false
    t.date "dob", null: false
    t.integer "city_id"
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.string "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string "unconfirmed_email"
    t.integer "failed_attempts", default: 0, null: false
    t.string "unlock_token"
    t.datetime "locked_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "address2"
    t.boolean "gender"
    t.string "provider"
    t.string "uid"
    t.string "name"
    t.text "image"
    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
  end 
class User < ApplicationRecord
      # Below - Devise Modules. We have not used = :timeoutable 
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, 
             :validatable, :confirmable, 
             :omniauthable, omniauth_providers: [:facebook]

      # Below - Additional validations of DB field entries presence at Model-level.
      validates :first_name, presence: true, length: { maximum: 30 }
      validates :last_name, presence: true, length: { maximum: 30 }
      validates :dob, presence: { message: "(Date of Birth) must be entered" } 
      validates :zip, presence: true, length: { maximum: 11 }
      validates :city_name, presence: true   
      validates :state, presence: true, length: { maximum: 15 }
      validates :address, presence: true
      validates :gender, presence: { message: "must be selected" } 

       # Below - Associates Users into a One to Many relationship with Cities.
      belongs_to :city


      def self.new_with_session(params, session)
        super.tap do |user|
          if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
            user.email = data["email"] if user.email.blank?
          end
        end
      end


      def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_create! do |user|
          user.provider       = auth.provider
          user.uid            = auth.uid
          user.email          = auth.info.email
          user.first_name     = auth.info.first_name
          user.password       = Devise.friendly_token[0,20] 
          user.last_name      = auth.info.last_name
          user.image          = auth.info.image
          user.address        = auth.info.location
          user.skip_confirmation!

          user.save

      end


      end

      # Below - Turns emails into downcase when saved from the controller into DB.      
      before_save { self.email = email.downcase }

    end
class Users::SessionsController < Devise::SessionsController
  # before_action :configure_sign_in_params, only: [:create]
  class SessionsController < ApplicationController
    def create
      @user = User.find_or_create_from_auth_hash(auth_hash)
      self.current_user = @user
      redirect_to '/'
    end

    protected

    def auth_hash
      request.env['omniauth.auth']
    end
  end
class Users::RegistrationsController < Devise::RegistrationsController
   before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
   def new
     @user = User.new
   end

  # POST /resource
  def create
    super
  end

  # GET /resource/edit
   def edit
     super
   end

  # PUT /resource
   def update
     super
   end

  protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :gender, :dob, :admin, :phone_number, :address, :address2, :city_name, :state, :zip, :subscribed, :city_id, :name, :image, :uid, :provider])
  end

end 
class UsersController < ApplicationController

    # Main Users Controller

      # Index Action for all Users
      def index
        @users = User.all
      end

      # Show Action for individual user ID
      def show 
        @user = User.find(params[:id])
      end 
    end
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Main MOdel for Facebook OmniAuth User Login/Signup

  def facebook
    #raise request.env["omniauth.auth"].to_yaml
    @user = User.from_omniauth(request.env["omniauth.auth"])

    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

  def failure
    redirect_to root_path
  end

end
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?

# Below, permits strong params from signup process, sign_in, and Account_update
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:login, keys: [:email, :password])
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, :address, :address2, :dob, :city_name, :state, :zip, :gender, :phone_number, :subscribed, :email, :password, :password_confirmation, :city_id, :name, :image, :uid, :provider]) 
    devise_parameter_sanitizer.permit(:account_update, keys: [:email, :address, :address2, :city_name, :state, :zip, :phone_number, :subscribed, :password, :password_confirmation, :current_password])
  end

end
 # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  config.omniauth :facebook, 'BLANK', 'BLANK', callback_url: 'MYWEBADRESS/users/auth/facebook/callback'
Rails.application.routes.draw do
# Main Routes file for all route, URL names and Action Methods. 

  # Below - Sets up custom login and log out path names for routes for user model.
  devise_for :users, path_names: { sign_in: "login", sign_out: "logout" }, controllers: {
                                    sessions: 'users/sessions', 
                                    :omniauth_callbacks => "users/omniauth_callbacks"   }

  # Not logged in visitors will be greeted by Index page
  root 'visitors#index'

  get 'cities/index'

  # Callback Route after OmniAuth redirects back to Ossemble for User Signup
  get '/auth/facebook/callback', to: 'sessions#create'

  # Below - Sets up routes for admin model.
  devise_for :admins

  # Below - Creates all routes for City model.
  resources :cities, except: [:destroy]

  # Below - Creates show route for Users & Model
  resources :users, only: [:show, :index]

end
<%= form_for(resource, as: resource_name, url: registration_path(resource_name),
      :html => {class: "form", role: "form"}) do |f| %>
    <div class="container alert"> <!-- Begin - Error Message(s) Wrapper for User Signup -->
      <%= devise_error_messages! %>
    </div>                        <!-- End - Error Message(s) Wrapper for User Signup -->
    <div class="container"> <!-- Begin -- Signup Form -->
      <div class="form-row"> <!-- Begin - First, Last Name, Gender, & Date of Birth Form Row -->
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :first_name, "First Name" %> 
          </div>
            <%= f.text_field :first_name, autofocus: true, class: "form-control", placeholder: "Enter First Name" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :last_name, "Last Name" %> 
          </div>
            <%= f.text_field :last_name, class: "form-control", placeholder: "Enter Last Name" %>
        </div>
       <div class="form-group col-md-2">
          <div class="control-label">
            <label class="control-label"> 
            Gender
            </label>
          </div>   
            <div class="gender_form form-control center" >
              <%= f.label :gender, "Male", id: "male_text", class: "gender_text" %>
              <%= f.radio_button :gender, true,  class: "gender_box"%>
              <%= f.label :gender, "Female", id: "female_text", class: "gender_text" %>
              <%= f.radio_button :gender, false, class: "gender_box" %>
            </div>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :dob, "Birth Date" %> 
          </div>
            <%= f.date_field :dob, class: "form-control" %>
        </div>
      </div> 
      <br> <!-- End - of Name, Gender & DOB form row -->

    <!-- Begin - Email & Password Form Row -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :email, "Email Address" %>
          </div>
            <%= f.email_field :email, type:"text", class: "form-control", placeholder: "Enter Email Address: youremail@example.com" %>
        </div>  
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password, "Password" %>
            <!-- Begin - If statement checks for password minimum character length  -->
            <small>
              (Minimum: <%= @minimum_password_length %> characters) 
            </small>
          </div>
            <%= f.password_field :password, autocomplete: "off", id:"inputPassword", class: "form-control", placeholder: "Create a Password" %>
          <!-- End - password character length if statement -->
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :password_confirmation, "Confirm Password" %> 
          </div>  
            <%= f.password_field :password_confirmation, autocomplete: "off", id:"inputPasswordConfirm", class: "form-control", placeholder: "Re-enter Password" %>
        </div>
      </div> 
      <br> <!-- End - Email & Password Form Row -->

    <!-- Begin -  Address & Phone Number Form Row--> 
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address, "Primary Address" %> 
            </div>
            <%= f.text_field :address, autocomplete: "on", class: "form-control", placeholder: "Enter Address: 1234 Main Street" %>
        </div>
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :address2, "Secondary Address" %> <small> (optional) </small>
          </div>
            <%= f.text_field :address2, autocomplete: "on", class: "form-control", placeholder: "Apartment, Suite #" %>
        </div>
        <!--  Phonne number currently hideen on form due to "style-" and "disabled :true" -->
        <div class="form-group col-md-3" style="display: none">
          <div class="control-label">
            <%= f.label :phone_number, "Phone Number" %> 
          </div>
            <%= f.phone_field :phone_number, disabled: true, class: "form-control", placeholder: "Enter Phone #: 555-555-5555" %>
        </div>
      </div> <br> <!-- End - Address & Phone Number Row -->

  <!--  Beginning - Location Form Row  -->
      <div class="form-row">
        <div class="form-group col-md-4">
          <div class="control-label">
            <%= f.label :city_name, "City" %> 
              <small>
                (Currently Lakewood, OH Supported)
              </small>
          </div> 
<!-- Below, we list all cities to be selected and we set the user's "city_id" field to the corresponding City table's City ID, completing the User's Association to City  -->
            <%= f.collection_select :city_id, City.all, :id, :name, {prompt: "Choose a City"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2 ">
          <div class="control-label">
            <%= f.label :state, "State" %> 
              <small>
                (Currently Ohio)
              </small>
          </div>
            <%= f.collection_select :state, City.all, :state, :state, {prompt: "Choose a State"}, class: "select_form form-control" %>
        </div>
        <div class="form-group col-md-2">
          <div class="control-label">
            <%= f.label :zip, "Zip Code" %> <small> (5-Digit Zip)</small>
          </div>
            <%= f.collection_select :zip, City.all, :zip, :zip, {prompt: "Choose Zip-Code"}, maxlength: "5", class: "select_form form-control" %>
        </div>
      </div> <!--  End - Location Form Row -->

    <!-- Begin - Subscribe Option -->
      <div class="form-row">
        <div class="form-group col-md-12 pull-left">
          <div class="form-check">
            <div class="control-label">
              <%= f.label :subscribed, "Subscribe?" %> 
                <small>
                  <em>
                  Stay up to date with Ossemble!
                  </em>
                </small> 
              <br>
              <div class="form-row pull-left">  
                <div class="col-md-12">
                  <div>
                    <%= f.check_box :subscribed, class: "check_box"  %>
                    <%= f.label "Yes!", class: "check_box_label"  %>
                  </div>
                </div>
              </div>
            </div> 
          </div> 
        </div>
      </div> <!-- End - Subscribe Option -->
      <div class="form-row"> <!-- Begin - Create Account Button Row (FB) -->  
        <div class="form-group col-md-2">
          <div class="actions">
            <%= f.submit "Create Account", class: "form_btn btn btn-success btn-lg btn-xlarge" %>
          </div>
        </div> 
        <div class="form-group col-md-4"> <!-- Begin - Signup With Facebook Button -->
          <%- if devise_mapping.omniauthable? %> <!-- Begin - OmniAuth If Statement -->
              <!-- Below - OmniAuth & FB Signup Button -->
              **<%= link_to '<i class="fa fa-facebook fa-lg fa-fw fb_log_sign_icon" aria-hidden="true"></i> Facebook Signup'.html_safe, 
                                     user_facebook_omniauth_authorize_path, 
                                     class: "form_btn btn btn-primary btn-lg btn-xlarge" %> <br />
          <% end -%>**                  <!-- End - OmniAuth If Statement -->
        </div>                        <!-- End - Signup with Facebook Button -->
      </div>                 <!-- End - Create Account Button Row (FB) -->
    </div>                  <!-- End - Signup Form -->
<% end %> 
{class:“form”,role:“form”})do | f |%>
性别

(最少:个字符)
(可选)
(目前支持俄亥俄州莱克伍德) (目前为俄亥俄州) (5位邮政编码) 与Ossemble保持同步!
**
**
和我在浏览器和终端中的错误:

在您的设计初始值设定项(
config/initializers/designe.rb
)中,您需要使用
info\u字段
参数添加您希望Facebook返回的项目。默认情况下,Facebook只返回姓名、电子邮件和id。例如:

# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], 
   callback_url: 'https://ossemble-workspace-twistedben.c9users.io/users/auth/facebook/callback',
   info_fields: 'email,name,birthday,locale,gender'
您可以在Facebook用户对象上获得可用项目的列表。有些项目(如生日)需要用户许可和特别批准