2013-04-17 21 views
12

我运行我的测试时遇到此错误。我已经检查确认所有email_confirmation拼写正确(除非我疯了)。我有点像Rails noob,所以它可能很简单。获取“ActiveRecord :: UnknownAttributeError:未知属性:email_confirmation”错误与rspec

用户模型

class User < ActiveRecord::Base 
    attr_accessible :email, :email_confirmation, :first_name, :last_name, 
        :password, :password_confirmation 
    has_secure_password 

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

    validates :first_name, presence: true, length: { maximum: 25 } 
    validates :last_name, presence: true, length: { maximum: 25 } 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 
    validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, 
        uniqueness: { case_sensitive: false } 
    validates :email_confirmation, presence: true 
    validates :password, presence: true, length: { maximum: 6 } 
    validates :password_confirmation, presence: true 
end 

Rspec的测试

require 'spec_helper' 

describe User do 
    before { @user = User.new(email: "[email protected]", 
          first_name: "John", last_name: "Smith", 
          password: "foobar", password_confirmation: "foobar", 
          email_confirmation: "[email protected]") } 

    subject { @user } 

    it { should respond_to(:first_name) } 
    it { should respond_to(:last_name) } 
    it { should respond_to(:email) } 
    it { should respond_to(:email_confirmation) } 
    it { should respond_to(:password_digest) } 
    it { should respond_to(:password) } 
    it { should respond_to(:password_confirmation) } 
    it { should respond_to(:authenticate) } 

    it { should be_valid } 

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

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

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

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

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

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

    describe "when email format is invalid" do 
    it "should be invalid" do 
     addresses = %w[[email protected],com user_at_foo.org [email protected] 
          [email protected]_baz.com [email protected]+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[[email protected] [email protected] [email protected] [email protected]] 
     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 "when password doesn't match confirmation" do 
    before { @user.password_confirmation = "mismatch" } 
    it { should_not be_valid } 
    end 

    describe "when email doesn't match confirmation" do 
    before { @user.email_confirmation = "[email protected]" } 
    it { should_not be_valid } 
    end 

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

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

    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 
end 

schema.rb

ActiveRecord::Schema.define(:version => 20130417021135) do 

    create_table "users", :force => true do |t| 
    t.string "first_name" 
    t.string "last_name" 
    t.string "email" 
    t.datetime "created_at",  :null => false 
    t.datetime "updated_at",  :null => false 
    t.string "password_digest" 
    end 

    add_index "users", ["email"], :name => "index_users_on_email", :unique => true 

end 
+1

您可以粘贴您的数据库架构为支持此模型的表吗? –

+0

用它编辑帖子 – josephndenton

+0

谢谢。 Rails支持内置确认验证,请参阅下面的建议。 –

回答

19

你得到UnknownAttributeError,因为你没有在你叫users表有一栏email_confirmation。默认情况下,ActiveRecord的将寻找名为一样的,你用它来构建模型的属性数据库列,但该行正试图构建一个与用户属性数据库不知道:

before { @user = User.new(email: "[email protected]", 
         first_name: "John", last_name: "Smith", 
         password: "foobar", password_confirmation: "foobar", 
         email_confirmation: "[email protected]") } 

是你真的打算将电子邮件确认保存在数据库中,还是只想在保存之前检查它是否与电子邮件匹配?我认为是后者,和Rails居然还内置了支持正是这样做的:

class User < ActiveRecord::Base 
    validates :email, :confirmation => true 
    validates :email_confirmation, :presence => true 
end 

见关于Rails Guide to Validations,或者validates_confirmation_of API文档的更多细节。 (您可能需要为:password_confirmation做同样的事情。)

+0

我有同样的问题。数据库架构是问题(我认为这是迁移)。谢谢! – Jeff

+1

有时迁移尚未在特定环境中完成。像'rake RAILS_ENV = production db:migrate'这样的发出命令解决了这个问题。 –

+0

如果您修改了架构,您也可以尝试删除这些Cookie –

10

我知道上面的答案标记为正确并解决了OP的问题。但是这个错误的另一个原因是在这个主题的许多stackoverflow帖子中没有注意到。当你忘记使用has_many的as选项时,这个错误可能发生在许多到多个多态中。例如:

class AProfile < ActiveRecord::Base 
    has_many :profile_students 
    has_many :students, through: :profile_students 
end 

class BProfile < ActiveRecord::Base 
    has_many :profile_students 
    has_many :students, through: :profile_students 
end 

class ProfileStudent < ActiveRecord::Base 
    belongs_to :profile, polymorphic: :true 
    belongs_to :student 
end 

class Student < ActiveRecord::Base 
    has_many :profile_students 
    has_many :aprofiles, through: :profile_students 
    has_many :bprofiles, through: :profile_students 
end 

这会给你这个错误:当您尝试做以下

Getting “ActiveRecord::UnknownAttributeError: unknown attribute: profile_id 

a = AProfile.new 
a.students << Student.new 

的解决方案是增加的:作为选项AProfile和BProfile:

class AProfile < ActiveRecord::Base 
    has_many :profile_students, as: :profile 
    has_many :students, through: :profile_students 
end 

class BProfile < ActiveRecord::Base 
    has_many :profile_students, as: :profile 
    has_many :students, through: :profile_students 
end 
-1

我有sa我消息错误,我弄不好订购PARAMS为列定义的顺序相同的数据库:

CONTROLLER

def create 
    worktime = Worktime.create(name: params[:name], workhours: params[:workhours], organization: @organization, workdays: params[:workdays]) 

    render json: worktime 
end 

DATABASE

Table: worktimes 
Columns: 
id int(11) AI PK 
name varchar(255) 
workhours text 
organization_id int(11) 
workdays text 
+5

我99.999%确定无论您遇到什么问题,都无法通过将参数按特定顺序解决。如果是的话,那么其他的东西就在起作用。 – DickieBoy

9

刚走花了大量的时间调试自己的这种情况下,我想我会用第三种可能性加入。

我已经完成了正确的迁移,并通过在导轨控制台中检查我的ActiveRecord进行了验证。我曾多次尝试从架构重新创建数据库,并尝试多次重新运行迁移,但都无济于事。

在我的情况下,问题是运行我的单元测试时发现问题,而不是运行时。问题是我的测试数据库在迁移/回滚测试中已经不同步。解决方案非常简单。我所要做的就是重置测试数据库:

rake db:test:prepare 
+0

好的。我的情况有点不同。我在Rails 5.0.0.1中使用了SQL模式格式,并且我做了db:rollback once和db:再次迁移。在回滚和迁移之间,我修改了最后一个数据库迁移文件。正如http://edgeguides.rubyonrails.org/active_record_migrations.html#changing-existing-migrations中记录的那样,这种模式不被推荐,但在早期开发中可能非常方便。我不知道如何或为什么,但生成的structure.sql模式对我来说是个问题,我不得不删除它并再次运行db:migrate。 – bhtabor

+0

这是一个很好的补充答案。像广告一样工作! – jlbenc

相关问题