2011-06-01 161 views
2

我添加了一個:username_or_email屬性,以我的用戶模型,例如:attr_accessor導致Rspec的測試失敗

class User < ActiveRecord::Base 

    #authlogic 
    acts_as_authentic do |c| 
    c.login_field = :username_or_email 
    end 

    #virtual field for allowing a user to login with their username or email 
    attr_accessor :username_or_email 

    attr_accessible :username, :email, :password, :password_confirmation, :username_or_email 

    validates :username, :presence => true, 
         :length => { :within => 3..20 }, 
         :uniqueness => true, 
         :format => { :with => /\A[a-z0-9][a-z0-9\-]+[a-z0-9]\z/ } 

    validates :email, :presence => true, 
        :format => { :with => /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i }, 
        :uniqueness => { :case_sensative => false } 

    validates :password, :presence => true, 
         :confirmation => true, 
         :length => { :within => 6..40 } 

    def self.find_by_username_or_email(username_or_email) 
    User.find_by_username(username_or_email) || User.find_by_email(username_or_email) 
    end 

end 

這樣做的目的是創建一個虛擬的領域,它允許用戶與登錄的任何用戶名或電子郵件使用Authlogic。這在我運行服務器時完美運行,完全按照我想要的方式進行。但是,它會導致所有的以下規格的失敗:

require 'spec_helper' 

describe User do 

    before(:each) do 
    @attr = { 
     :username => "example", 
     :email => "[email protected]", 
     :password => "password", 
     :password_confirmation => "password" 
    } 
    end 

    describe "username validations" do 

    it "should allow usernames with numbers" do 
     User.create!(@attr.merge(:username => 'example123')) 
    end 

    it "should allow hyphens" do 
     User.create!(@attr.merge(:username => 'example-two')) 
    end 

    it "should require a username" do 
     no_username_user = User.new (@attr.merge(:username => "")) 
     no_username_user.should_not be_valid 
    end 

    it "should reject usernames that are too long" do 
     user = User.new(@attr.merge(:username => ("a" * 21))) 
     user.should_not be_valid 
    end 

    it "should reject username that are too short" do 
     user = User.new(@attr.merge(:username => ("a" * 2))) 
     user.should_not be_valid 
    end 

    it "should reject username with uppercase letters" do 
     user = User.new(@attr.merge(:username => "Example")) 
     user.should_not be_valid 
    end 

    it "should reject duplicate usernames" do 
     User.create!(@attr) 
     user = User.new(@attr.merge(:email => "[email protected]")) 
     user.should_not be_valid 
    end 

    it "should reject usernames with whitespace characters" do 
     u1 = User.new(@attr.merge(:username => "exa mple")) 
     u2 = User.new(@attr.merge(:username => " example")) 
     u3 = User.new(@attr.merge(:username => "example ")) 
     u4 = User.new(@attr.merge(:username => "exa\tmple")) 
     u5 = User.new(@attr.merge(:username => "exa\nmple")) 

     u1.should_not be_valid 
     u2.should_not be_valid 
     u3.should_not be_valid 
     u4.should_not be_valid 
     u5.should_not be_valid 
    end 

    it "should reject usernames with special characters" do 
     u1 = User.new(@attr.merge(:username => 'ex&mple')) 
     u2 = User.new(@attr.merge(:username => 'ex*mple')) 
     u3 = User.new(@attr.merge(:username => 'ex"mple')) 
     u4 = User.new(@attr.merge(:username => 'ex^mple')) 
     u5 = User.new(@attr.merge(:username => 'ex;mple')) 

     u1.should_not be_valid 
     u2.should_not be_valid 
     u3.should_not be_valid 
     u4.should_not be_valid 
     u5.should_not be_valid 
    end 

    it "should reject usernames that begin with a hypen" do 
     user = User.new(@attr.merge(:username => '-example')) 
     user.should_not be_valid 
    end 

    it "should reject usernames that end with a hypen" do 
     user = User.new(@attr.merge(:username => 'example-')) 
     user.should_not be_valid 
    end 

    end 



    describe "email validations" do 

    it "should require an email" do 
     no_email_user = User.new (@attr.merge(:email => "")) 
     no_email_user.should_not be_valid 
    end 

    it "should reject duplicate emails" do 
     User.create!(@attr) 
     user2 = User.new(@attr.merge(:username => "example2")) 
     user2.should_not be_valid 
    end 

    it "should accept valid email addresses" do 
     addresses = %w[[email protected] [email protected] [email protected]] 
     addresses.each do |address| 
     valid_email_user = User.new(@attr.merge(:email => address)) 
     valid_email_user.should be_valid 
     end 
    end 

    it "should reject invalid email addresses" do 
     addresses = %w[[email protected],com user_at_foo.org [email protected]] 
     addresses.each do |address| 
     invalid_email_user = User.new(@attr.merge(:email => address)) 
     invalid_email_user.should_not be_valid 
     end 
    end 

    it "should reject email address idential up to case" do 
     User.create!(@attr) 
     user = User.new(@attr.merge(:email => @attr[:email].capitalize)) 
     user.should_not be_valid 
    end 

    end 



    describe "password validations" do 

    it "should require a password or a password confirmation" do 
     user = User.new(@attr.merge(:password => "", :password_confirmation => "")) 
     user.should_not be_valid 
    end 

    it "should require a password" do 
     user = User.new(@attr.merge(:password => "")) 
     user.should_not be_valid 
    end 

    it "should require a password confirmation" do 
     user = User.new(@attr.merge(:password_confirmation => "")) 
     user.should_not be_valid 
    end 

    it "should require a matching password confirmation" do 
     user = User.new(@attr.merge(:password_confirmation => "invalid")) 
     user.should_not be_valid 
    end 

    it "should reject passwords that are too short" do 
     password = "a" * 5 
     user = User.new(@attr.merge(:password => password, :password_confirmation => password)) 
     user.should_not be_valid 
    end 

    it "should reject passwords that are too long" do 
     password = "a" * 41 
     user = User.new(@attr.merge(:password => password, :password_confirmation => password)) 
     user.should_not be_valid 
    end 

    it "should require case sensative password confirmations" do 
     password = "password" 
     user = User.new(@attr.merge(:password => password, 
     :password_confirmation => password.capitalize)) 
     user.should_not be_valid 
    end 

    end 

end 

他們失敗與錯誤:

Running: spec/models/user_spec.rb 
FFFFFFFFFFFFFFFFFFFFFFF 

Failures: 

    1) User username validations should allow usernames with numbers 
    Failure/Error: User.create!(@attr.merge(:username => 'example123')) 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x000001017c1850> 
    # ./spec/models/user_spec.rb:17:in `block (3 levels) in <top (required)>' 

    2) User username validations should allow hyphens 
    Failure/Error: User.create!(@attr.merge(:username => 'example-two')) 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000100d50f10> 
    # ./spec/models/user_spec.rb:21:in `block (3 levels) in <top (required)>' 

    3) User username validations should require a username 
    Failure/Error: no_username_user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000100cc9da8> 
    # ./spec/models/user_spec.rb:26:in `block (3 levels) in <top (required)>' 

    4) User username validations should reject usernames that are too long 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000100c333f8> 
    # ./spec/models/user_spec.rb:31:in `block (3 levels) in <top (required)>' 

    5) User username validations should reject username that are too short 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000100aafbd0> 
    # ./spec/models/user_spec.rb:36:in `block (3 levels) in <top (required)>' 

    6) User username validations should reject username with uppercase letters 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x000001032e2f58> 
    # ./spec/models/user_spec.rb:41:in `block (3 levels) in <top (required)>' 

    7) User username validations should reject duplicate usernames 
    Failure/Error: User.create!(@attr) 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000103167f70> 
    # ./spec/models/user_spec.rb:45:in `block (3 levels) in <top (required)>' 

    8) User username validations should reject usernames with whitespace characters 
    Failure/Error: u1.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x000001032dbb40> 
    # ./spec/models/user_spec.rb:57:in `block (3 levels) in <top (required)>' 

    9) User username validations should reject usernames with special characters 
    Failure/Error: u1.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x0000010328d0d0> 
    # ./spec/models/user_spec.rb:71:in `block (3 levels) in <top (required)>' 

    10) User username validations should reject usernames that begin with a hypen 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x0000010323f3d0> 
    # ./spec/models/user_spec.rb:80:in `block (3 levels) in <top (required)>' 

    11) User username validations should reject usernames that end with a hypen 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000103212a10> 
    # ./spec/models/user_spec.rb:85:in `block (3 levels) in <top (required)>' 

    12) User email validations should require an email 
    Failure/Error: no_email_user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x000001031ed4e0> 
    # ./spec/models/user_spec.rb:96:in `block (3 levels) in <top (required)>' 

    13) User email validations should reject duplicate emails 
    Failure/Error: User.create!(@attr) 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x000001031bf630> 
    # ./spec/models/user_spec.rb:100:in `block (3 levels) in <top (required)>' 

    14) User email validations should accept valid email addresses 
    Failure/Error: valid_email_user.should be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x000001031991b0> 
    # ./spec/models/user_spec.rb:109:in `block (4 levels) in <top (required)>' 
    # ./spec/models/user_spec.rb:107:in `each' 
    # ./spec/models/user_spec.rb:107:in `block (3 levels) in <top (required)>' 

    15) User email validations should reject invalid email addresses 
    Failure/Error: invalid_email_user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x0000010315d1b0> 
    # ./spec/models/user_spec.rb:117:in `block (4 levels) in <top (required)>' 
    # ./spec/models/user_spec.rb:115:in `each' 
    # ./spec/models/user_spec.rb:115:in `block (3 levels) in <top (required)>' 

    16) User email validations should reject email address idential up to case 
    Failure/Error: User.create!(@attr) 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x0000010310a898> 
    # ./spec/models/user_spec.rb:122:in `block (3 levels) in <top (required)>' 

    17) User password validations should require a password or a password confirmation 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x0000010172f2c0> 
    # ./spec/models/user_spec.rb:135:in `block (3 levels) in <top (required)>' 

    18) User password validations should require a password 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x000001015f5b98> 
    # ./spec/models/user_spec.rb:140:in `block (3 levels) in <top (required)>' 

    19) User password validations should require a password confirmation 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x0000010155f120> 
    # ./spec/models/user_spec.rb:145:in `block (3 levels) in <top (required)>' 

    20) User password validations should require a matching password confirmation 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000101310298> 
    # ./spec/models/user_spec.rb:150:in `block (3 levels) in <top (required)>' 

    21) User password validations should reject passwords that are too short 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000100eecbf8> 
    # ./spec/models/user_spec.rb:156:in `block (3 levels) in <top (required)>' 

    22) User password validations should reject passwords that are too long 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000100d7f400> 
    # ./spec/models/user_spec.rb:162:in `block (3 levels) in <top (required)>' 

    23) User password validations should require case sensative password confirmations 
    Failure/Error: user.should_not be_valid 
    NoMethodError: 
     undefined method `username_or_email_changed?' for #<User:0x00000100cf0b38> 
    # ./spec/models/user_spec.rb:169:in `block (3 levels) in <top (required)>' 

Finished in 0.19613 seconds 
23 examples, 23 failures 

好像問題與valid?方法發生,但我不明白爲什麼考慮:username_or_email沒有任何驗證。爲什麼會發生這些錯誤,我該如何解決這些錯誤?

謝謝。

+1

你的規格是什麼?它看起來像被誤認爲是某種數據庫屬性。 – tadman 2011-06-01 19:07:45

+0

哎呀,我猜我的帖子寫得不是很好。我用更多的信息更新了它。 – LandonSchropp 2011-06-01 19:29:07

回答

0

解決方案其實很簡單。在user.rb:

class User < ActiveRecord::Base 

    #authlogic 
    acts_as_authentic do |c| 
    c.login_field = :username_or_email 
    c.validates_login_field = false 
    end 

    ... 

end 

此方法的文檔可以發現here

1

我想這是因爲username_or_email不是ActiveRecord意義上的屬性,所以不應該用attr_accessible來提及。

+0

我試圖刪除它並得到相同的結果。 (還是)感謝你的建議。 – LandonSchropp 2011-06-01 22:48:32

+0

我沒有想到acts_as_authentic調用可能是個問題。 login_field config選項指定一個數據庫列。由於username_or_password不是一個數據庫列,這不會工作。也許你可以結合check_passwords_against_database來修復它。看看http://rdoc.info/github/binarylogic/authlogic/master/Authlogic/ActsAsAuthentic/Password/Config#check_passwords_against_database-instance_method – moritz 2011-06-01 23:00:43

+0

它不是'check_passwords_against_database'字段,但你的建議讓我環顧四周該文檔多一點,我發現'validate_login_field ='方法。將該方法設置爲false可以修復問題。如果你更新你的答案,我會給你複選標記。感謝所有的幫助。 – LandonSchropp 2011-06-02 01:08:27