0

在我的 Rails 应用程序 (3.2.2) 中,我使用 Devise 进行身份验证,包括 Facebook 登录。

除了我的应用程序重定向到新的注册表单时,一切都通过 Facebook 连接过程进行。除了 Facebook 提供的信息(即用户名和密码/密码确认)之外,我们还需要一些信息,以便将用户放在该表单上以完成它。

当我在 Facebook 登录过程结束时提交一个创建新用户的表单时,尽管在表单中为用户名提供了一个字符串值,但 Devise 抱怨“用户名不能为空”。我的第一个假设是表单没有正确标记,并且数据没有进入验证。我检查了表格,一切都是正确的。日志中的输出还显示 username 的值实际上是存在的,但 Devise 仍然抱怨。

我四处搜索,发现很多有此错误但没有解决方案的 gists 和 pastebins。这是我认为相关的代码 - 如果您想查看其他内容,请告诉我。

_form.html.erb

<fieldset id="required-user-form-fields">
<h2 class="user-form-header">These we need.</h2><br>

<%= f.label :first_name, class: "user-form-label" %><br>
<%= f.text_field :first_name, size: "30", class: "standard-blue-text-field" %><br>

<%= f.label :email, class: "user-form-label" %><br>
<%= f.text_field :email, class: "standard-blue-text-field", size: "30" %><br>

<%= f.label :username, class: "user-form-label" %><br>
<%= f.text_field :username, class: "standard-blue-text-field#{" disabled" if f.object.persisted?}", size: "30", :disabled => f.object.persisted? %><br>
  <% if f.object.persisted? %>
    <span class="help-block">Username cannot be changed.</span><br>
  <% end %>

<%= f.label :password, class: "user-form-label" %><br>
<%= f.password_field :password, class: "standard-blue-text-field ", size: "30" %><br>
  <% if f.object.persisted? %>
    <span class="help-block">Leave this blank if you don't want your password to change.</span><br>
  <% else %>
    <span class="help-block">Hint: this should be at least 6 characters long.</span><br>
  <% end %>
<%= f.label :password_confirmation, "confirm your password", class: "user-form-label" %><br>
<%= f.password_field :password_confirmation, class: "standard-blue-text-field", size: "30" %><br>

</fieldset>

<fieldset id="optional-user-form-fields">
<h2 class="user-form-header">These are optional.</h2><br>

<%= f.label :zip_code, "Home zip code", class: "user-form-label" %><br>
<%= f.text_field :zip_code, size: "10", class: "standard-blue-text-field" %><br>

<%= f.label :last_name, class: "user-form-label" %><br>
<%= f.text_field :last_name, class: "standard-blue-text-field", size: "30" %><br>

<%= f.label :gender, class: "user-form-label" %><br>
<%= f.select :gender, ['Male', 'Female'], include_blank: true, class: "user-form-gender" %><br>

<%= f.label :birth_month, "When is your birthday?", class: "user-form-label" %><br>
<%= f.select :birth_month, ::Date::MONTHNAMES, {}, class: 'side-by-side' %>
<%= f.select :birth_day, 1..31, {include_blank: true}, class: 'side-by-side' %><br>

<%= f.label :twitter_username, "Are you on Twitter?", class: "user-form-label" %><br>
<%= f.text_field :twitter_username, class: "standard-blue-text-field", size: "30" %><br>

<%= f.label :bio, "Share your cliff note biography in 250 characters or less.", class: "user-form-label" %><br>
<%= f.text_area :bio, class: "standard-blue-text-field", size: "250" %><br>

用户.rb(例外)

class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username
has_merit

# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable
# and :omniauthable

before_save :create_permalink

devise :invitable, :database_authenticatable, :registerable, :confirmable, :lockable,
     :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :invitable,
     :omniauth_providers => [:facebook]

default_accessible_fields = [:email, :first_name, :last_name, :birth_month,
                           :birth_day, :password, :password_confirmation,
                           :remember_me, :username, :zip_code, :gender, :confirmed_at,
                           :bio, :twitter_username, :permalink] #, :permalink
admin_only_fields = [:admin]

attr_accessible *default_accessible_fields
attr_accessible *(default_accessible_fields + admin_only_fields), :as => :admin

has_many :venue_scores

has_many :tips
has_many :tip_likes, dependent: :destroy
has_many :liked_tips, through: :tip_likes, source: :tip
has_many :lists
has_many :list_likes, dependent: :destroy
has_many :liked_lists, through: :list_likes, source: :list

has_many :my_follows, foreign_key: :follower_id, class_name: 'Follow', dependent: :destroy
has_many :follows, through: :my_follows, source: :followed

has_many :their_follows, foreign_key: :followed_id, class_name: 'Follow', dependent: :destroy
has_many :followers, through: :their_follows

has_many :invitations, :class_name => self.to_s, :as => :invited_by


validates :first_name, presence: true
validates :username, presence: true, uniqueness: true
validates :email, presence: true, uniqueness: true 
validates :zip_code, numericality: true, length: { is: 5 } unless :has_zip_code?
validates :birth_month, :birth_day, presence: { if: :birthday_provided? }
validates :birth_month, inclusion: { in: ::Date::MONTHNAMES, allow_blank: true }
validates :birth_day, inclusion: { in: 1..31, allow_blank: true }
validate :check_date_for_realness
# Removing username update validation - should check later for conflicts or issues arising from this
# validate :prevent_username_change, on: :update

def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
email = conditions.delete(:email)
where(conditions).where(["lower(email) = :value OR lower(username) = :value", { :value => email.strip.downcase }]).first
end

表单提交后在日志中输出

Started POST "/users" for 127.0.0.1 at 2013-11-03 12:15:57 -0800
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"yb9qpXpGfsTJmpL++Kd9S1LPoSVOHA3If1jjKWMTGuY=", "user"=>{"first_name"=>"Tom", "email"=>"dhaocew_liangsky_1383438854@tfbnw.net", "username"=>"thomas", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "zip_code"=>"", "last_name"=>"Liangsky", "gender"=>"Male", "birth_month"=>"", "birth_day"=>"", "twitter_username"=>"", "bio"=>""}}
(0.2ms)  BEGIN
User Exists (0.7ms)  SELECT 1 FROM "users" WHERE "users"."email" = 'dhaocew_liangsky_1383438854@tfbnw.net' LIMIT 1
CACHE (0.0ms)  SELECT 1 FROM "users" WHERE "users"."email" = 'dhaocew_liangsky_1383438854@tfbnw.net' LIMIT 1
User Exists (0.3ms)  SELECT 1 FROM "users" WHERE "users"."username" = '' LIMIT 1
CACHE (0.0ms)  SELECT 1 FROM "users" WHERE "users"."email" = 'dhaocew_liangsky_1383438854@tfbnw.net' LIMIT 1
(0.2ms)  ROLLBACK
Rendered devise/registrations/_form.html.erb (4.1ms)
Rendered devise/registrations/new.html.slim within layouts/application (6.7ms)
Completed 200 OK in 113ms (Views: 28.2ms | ActiveRecord: 0.0ms | Solr: 0.0ms)

注册控制器.rb

class RegistrationsController < Devise::RegistrationsController

  def after_sign_up_path_for(devise_resource)
    edit_user_registration_path
  end

  #def account_update_params
  #  devise_parameter_sanitizer.for(:account_update)
  #end

end
4

1 回答 1

0

我相信我解决了根本原因。用作 facebook 身份验证一部分的方法:

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"]
        user.first_name = data["first_name"]
        user.last_name = data["last_name"]
        #user.username = data["username"]
        user.gender = data["gender"].capitalize
        user.facebook_id = data["id"]
        user.skip_confirmation!
      end
    end
  end

在从 facebook 身份验证派生的数据上调用 user.username。我们不请求用户名作为 Facebook 范围的一部分,因此它不存在,但由于控制器中的此调用,应用程序忽略了表单数据。您会看到我已将其注释掉,现在似乎一切都在与测试用户合作。

于 2013-11-03T23:26:37.310 回答