-3

パスワードを忘れたユーザーのためにパスワードのリセットを追加しようとしています。ユーザーは [パスワードを忘れましたか?] をクリックします。サインアップページで。次に、ユーザーがメールを入力して [パスワードのリセット] をクリックすると、トークンが作成され、パスワードをリセットするためのリンクが記載されたメールが送信されます。ほとんどの場合、メールボックスが空白であるか、正確に6つのランダムな文字/数字がある場合にのみ機能しますが、ユーザーがメールを入力してパスワードのリセットをクリックすると機能せず、エラーメッセージが表示されます:

**Validation failed: Password can't be blank
Password cant be blank, password is too short(6 min)**

user.rb を変更すると、:password、presence: true、長さ: { 最小: 6 } が検証され、:password_confirmation、presence: true が検証されます。

さまざまなエラーが発生しました。このパスワードのリセット フォームからこの検証を除外する方法はありますか

app/models/user.rb:30:in `send_password_reset'
app/controllers/password_resets_controller.rb:7:in `create'

ビデオ 275 How I Test でこのエラーに遭遇しました。11:20に

失敗/エラー: click_button "パスワードのリセット" ActiveRecord::RecordInvalid: 検証に失敗しました: パスワードを空白にすることはできません、パスワードが短すぎます (最小 6 文字)、パスワードの確認を空白にすることはできません

     # ./app/models/user.rb:30:in `send_password_reset'
     # ./app/controllers/password_resets_controller.rb:7:in `create'
     # (eval):2:in `click_button'
     # ./spec/requests/password_resets_spec.rb:9:in `block (2 levels) in <top (required)>'

13.66秒で完走 95例 失敗1回

これは使用されているコードの一部です。

user.rb

    # == Schema Information
    #
    # Table name: users
    #
    #  id         :integer         not null, primary key
    #  name       :string(255)
    #  email      :string(255)
    #  created_at :datetime        not null
    #  updated_at :datetime        not null
    #

    class User < ActiveRecord::Base
     attr_accessible :name, :email, :password, :password_confirmation
     has_secure_password

      before_save { |user| user.email = email.downcase }
      before_save :create_remember_token

      validates :name, presence: true, length: { maximum: 50 }
      VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
      validates :email, presence:   true,
                format:     { with: VALID_EMAIL_REGEX },
                uniqueness: { case_sensitive: false }
      validates :password, presence: true, length: { minimum: 6 }
      validates :password_confirmation, presence: true

      def send_password_reset
        generate_token(:password_reset_token)
        self.password_reset_sent_at = Time.zone.now
        save!
        UserMailer.password_reset(self).deliver
      end

      def generate_token(column)
        begin
          self[column] = SecureRandom.urlsafe_base64
        end while User.exists?(column => self[column])
      end

      def self.search(search)
        if search
          find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
        else
          find(:all)
        end
      end

      private

        def create_remember_token
          self.remember_token = SecureRandom.urlsafe_base64
        end
    end

password_resets_controller.rb

            class PasswordResetsController < ApplicationController
      def new
      end

      def create
        user = User.find_by_email(params[:email])
        user.send_password_reset
        redirect_to root_url, :notice => "Email sent with password reset instructions."
      end

      def edit
        @user = User.find_by_password_reset_token!(params[:id])
      end
    end

password_resets_spec

    require 'spec_helper'

    describe "PasswordResets" do
      it "emails user when requesting password reset" do
        user = Factory(:user)
        visit signin_path
        click_link "password"
        fill_in "Email", :with => user.email
        click_button "Reset Password"
        current_path.should eq(root_path)
        page.should have_content("Email sent")
        last_email.to.should include(user.email)
      end
    end

user_spec.rb

    # == Schema Information
    #
    # Table name: users
    #
    #  id         :integer         not null, primary key
    #  name       :string(255)
    #  email      :string(255)
    #  created_at :datetime        not null
    #  updated_at :datetime        not null
    #

    require 'spec_helper'

    describe User do

      describe "#send_password_reset" do
        let(:user) { Factory(:user) }

        it "generates a unique password_reset_token each time" do
          user.send_password_reset
          last_token = user.password_reset_token
          user.send_password_reset
          user.password_reset_token.should_not eq(last_token)
        end

        it "saves the time the password reset was sent" do
          user.send_password_reset
          user.reload.password_reset_sent_at.should be_present
        end

        it "delivers email to user" do
          user.send_password_reset
          last_email.to.should include(user.email)
        end
      end

      before do
        @user = User.new(name: "Example User", email: "user@example.com", 
                 password: "foobar", password_confirmation: "foobar")
      end

      subject { @user }

      it { should respond_to(:name) }
      it { should respond_to(:email) }
      it { should respond_to(:password_digest) }
      it { should respond_to(:password) }
      it { should respond_to(:password_confirmation) }
      it { should respond_to(:remember_token) }
      it { should respond_to(:authenticate) }

      it { should respond_to(:admin) }
      it { should respond_to(:authenticate) }

      it { should be_valid }
      it { should_not be_admin }

      describe "with admin attribute set to 'true'" do
        before { @user.toggle!(:admin) }

        it { should be_admin }
      end

      describe "when name is not present" do
        before { @user.name = " " }
        it { should_not be_valid }
      end

      describe "when email is not present" do
        before { @user.email = " " }
        it { should_not be_valid }
      end

      describe "when name is too long" do
        before { @user.name = "a" * 51 }
        it { should_not be_valid }
      end

      describe "when email format is invalid" do
        it "should be invalid" do
          addresses = %w[user@foo,com user_at_foo.org example.user@foo.
                   foo@bar_baz.com foo@bar+baz.com]
          addresses.each do |invalid_address|
            @user.email = invalid_address
            @user.should_not be_valid
          end      
        end
       end

      describe "when email format is valid" do
        it "should be valid" do
          addresses = %w[user@foo.COM A_US-ER@f.b.org frst.lst@foo.jp a+b@baz.cn]
          addresses.each do |valid_address|
            @user.email = valid_address
            @user.should be_valid
          end      
        end
      end

      describe "when email address is already taken" do
        before do
          user_with_same_email = @user.dup
          user_with_same_email.email = @user.email.upcase
          user_with_same_email.save
        end

        it { should_not be_valid }
      end

      describe "email address with mixed case" do
        let(:mixed_case_email) { "Foo@ExAMPle.CoM" }

        it "should be saved as all lower-case" do
          @user.email = mixed_case_email
          @user.save
          @user.reload.email.should == mixed_case_email.downcase
        end
      end

      describe "when password is not present" do
        before { @user.password = @user.password_confirmation = " " }
        it { should_not be_valid }
      end

      describe "when password doesn't match confirmation" do
        before { @user.password_confirmation = "mismatch" }
        it { should_not be_valid }
      end

      describe "when password confirmation is nil" do
        before { @user.password_confirmation = nil }
        it { should_not be_valid }
      end

      it { should respond_to(:authenticate) }

      describe "with a password that's too short" do
        before { @user.password = @user.password_confirmation = "a" * 5 }
        it { should be_invalid }
      end

      describe "return value of authenticate method" do
        before { @user.save }
        let(:found_user) { User.find_by_email(@user.email) }

        describe "with valid password" do
          it { should == found_user.authenticate(@user.password) }
        end

       describe "with invalid password" do
          let(:user_for_invalid_password) { found_user.authenticate("invalid") }

          it { should_not == user_for_invalid_password }
          specify { user_for_invalid_password.should be_false }
        end
      end

      describe "remember token" do
        before { @user.save }
        its(:remember_token) { should_not be_blank }
      end
    end
4

2 に答える 2

2

使用しているsend_password_resetメソッドで:

save!

代わりに使用

save!(validate: false)

そしてすべてがうまくいくでしょう。問題は、モデルを保存しようとしていて、検証が干渉していることです。ユーザーから何も生成されないため、send_password_reset メソッドで何も検証する必要はありません。無効な情報がデータベースに保存される危険はありません。

于 2012-09-19T17:28:34.513 に答える
0

一見すると、パスワードをリセットするときに、コードは空白のパスワードを保存しようとしています (したがって、エラー)。を使用して一度に 1 行ずつデバッグしてlogger.debugみて、パスワードを保存する前に、コードがパスワードを無効にする時点を見つけてください。UserMailer は使用していませんが、エラーは次のUserMailer.password_reset(self).deliver行にあるようです。メソッドを作成した場合は、最初にデバッグを検討します。自動化されている場合は、メーラーのすべてのパラメーターを設定するセクションを試してデバッグし、トークンを生成してパスワードをリセットします。

お役に立てれば。

于 2012-06-12T22:35:08.510 に答える