我正在关注Michael Hartl的RoR教程,但在测试我的代码时遇到以下错误。我似乎无法弄清楚为什么我的对象没有传递为有效。
我的user.rb文件:
class User < ActiveRecord::Base
before_save { |user| user.email = user.email.downcase }
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 }
end
这是我的user_rspec.rb:
require 'spec_helper'
describe User do
before { @user = User.new(name: "bobo", email: "user@example.com") }
subject { @user }
it { should respond_to(:name) }
it { should respond_to(:email) }
it { should be_valid }
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.]
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
end
当我运行测试时,我收到以下错误: 故障:
1) User
Failure/Error: it { should be_valid }
expected valid? to return true, got false
# ./spec/models/user_spec.rb:12:in `block (2 levels) in <top (required)>'
Finished in 0.21355 seconds
9 examples, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:12 # User `
当我在rails控制台中运行user_with_same_email.errors时,我得到以下答案:
ruby-2.0.0-p247 :001 > user = User.new(name: "bobo", email: "user@example.com")
=> #<User id: nil, name: "bobo", email: "user@example.com", created_at: nil, updated_at: nil>
ruby-2.0.0-p247 :002 > user_with_same_email = user.dup
=> #<User id: nil, name: "bobo", email: "user@example.com", created_at: nil, updated_at: nil>
ruby-2.0.0-p247 :003 > user_with_same_email.valid?
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('user@example.com') LIMIT 1
=> true
ruby-2.0.0-p247 :004 > user_with_same_email.errors
=> #<ActiveModel::Errors:0x007fad6491f780 @base=#<User id: nil, name: "bobo", email: "user@example.com", created_at: nil, updated_at: nil>, @messages={}>
ruby-2.0.0-p247 :005 >
如您所见,错误未传递任何消息。
有人知道如何解决这个错误吗?
谢谢!
添加了:
当我尝试使用已保存的电子邮件保存用户时,似乎出现错误。
$ rails console --sandbox
Loading development environment in sandbox (Rails 4.0.0)
Any modifications you make will be rolled back on exit
ruby-2.0.0-p247 :001 > user = User.new(name: "bobo", email: "user@example.com")
=> #<User id: nil, name: "bobo", email: "user@example.com", created_at: nil, updated_at: nil>
ruby-2.0.0-p247 :002 > user.save
(0.1ms) SAVEPOINT active_record_1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('user@example.com') LIMIT 1
SQL (3.3ms) INSERT INTO "users" ("created_at", "email", "name", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Wed, 16 Oct 2013 10:15:19 UTC +00:00], ["email", "user@example.com"], ["name", "bobo"], ["updated_at", Wed, 16 Oct 2013 10:15:19 UTC +00:00]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
ruby-2.0.0-p247 :003 > user_with_same_email = user.dup
=> #<User id: nil, name: "bobo", email: "user@example.com", created_at: nil, updated_at: nil>
ruby-2.0.0-p247 :004 > user_with_same_email.save
(0.1ms) SAVEPOINT active_record_1
User Exists (0.1ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('user@example.com') LIMIT 1
(0.1ms) ROLLBACK TO SAVEPOINT active_record_1
=> false
ruby-2.0.0-p247 :005 >
我不确定为什么会这样。我的验证不应该解决这个问题吗?
谢谢!
答案 0 :(得分:0)
您传递的名称不超过50个字符,并且您的电子邮件与您制作的正则表达式相匹配。唯一剩下的就是电子邮件的唯一性。我打赌你没有在规格之间正确清理你的数据库。您可以通过将should be_valid
规范扩展到此来确认吗?
it "is valid" do
subject.valid?
subject.errors.full_messages.should eq []
end
调用valid?
将填充errors数组,然后规范将失败并显示错误消息。
如果已经收到电子邮件,请尝试使用database_cleaner
https://github.com/bmabey/database_cleaner#rspec-example(您必须先将其添加到Gemfile
才能使用。
答案 1 :(得分:0)
如前所述,@user.errors.messages
的错误消息包含{:email=>["has already been taken"]}
。
您可以通过添加 spec_helper.rb (在RSpec.configure do |config|
区块中)初步解决此问题:
# clears user table
config.before(:suite) do
User.destroy_all
end
但我不相信这个解决方案。看来,用户在测试用例之后不会破坏自己。
答案 2 :(得分:0)
我的测试也失败了
it { should be_Valid }
我的rails控制台会话(上图)user.valid为true
以下更正的测试
it { should be_valid }
大写'be_Valid'是问题