2011-06-01 311 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