我正在关注Michael Hartl Ruby on Rails教程。我在第6.3节遇到了测试失败的问题。代码应验证空白密码,但如果我使用密码创建User对象,然后将密码字段更改为空白,valid?
将返回true,根据测试规范,这不是预期的。我错过了什么吗?
我必须安装protected_attributes
宝石。我更喜欢使用这个gem来遵循教程代码而不做任何修改。
正在运行bundle exec rspec spec
:
rspec ./spec/models/user_spec.rb:90 # User when password confirmation is nil
rspec ./spec/models/user_spec.rb:80 # User when password is not present
这是我的档案。
user.rb:
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_secure_password
before_save { |user| user.email = 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 }
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
end
user_spec.rb(只有失败的测试):
describe "when password is not present" do
before { @user.password = @user.password_confirmation = " " }
it { should_not be_valid }
end
describe "when password confirmation is nil" do
before { @user.password_confirmation = nil }
it { should_not be_valid }
end
以下是我在控制台中运行的一些测试:
max@top:~/prog/ruby/railstut$ rails c --sandbox
Loading development environment in sandbox (Rails 4.0.0.rc1)
Any modifications you make will be rolled back on exit
irb(main):001:0> # Should return true.
irb(main):002:0* User.new(name: "Example User", email: "user@example.com",
irb(main):003:1* password: "foobar", password_confirmation: "foobar").valid?
User Exists (1.8ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('user@example.com') LIMIT 1
=> true
irb(main):004:0>
irb(main):005:0* # Should return false.
irb(main):006:0* User.new(name: "Example User", email: "user@example.com",
irb(main):007:1* password: "", password_confirmation: "foobar").valid?
User Exists (0.8ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('user@example.com') LIMIT 1
=> false
irb(main):008:0>
irb(main):009:0* # Oops. Expecting false.
irb(main):010:0* user = User.new(name: "Example User", email: "user@example.com",
irb(main):011:1* password: "foobar", password_confirmation: "foobar")
=> #<User id: nil, name: "Example User", email: "user@example.com", created_at: nil, updated_at: nil, password_digest: "$2a$10$ygkdtuJYF89ysbD86ZcO9ugiQZ0/FxOKvj87zEegJq.f...">
irb(main):012:0>
irb(main):013:0* user.password = ""
=> ""
irb(main):014:0>
irb(main):015:0* user.valid?
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('user@example.com') LIMIT 1
=> true
答案 0 :(得分:1)
这是Rails 4中的一个奇怪问题,由于某种原因,您无法在该上下文中为密码分配空白值。 Rails 4.0RC1 version of the tutorial和sample app中的代码为Rails 4提供了解决方法。基本上,您必须使用哈希重新创建对象,如
describe "when password is not present" do
before do
@user = User.new(name: "Example User", email: "user@example.com",
password: " ", password_confirmation: " ")
end
it { should_not be_valid }
end
我已经提交issue on the Rails GitHub repository希望解决此问题。
答案 1 :(得分:0)
我认为您的validates :password, presence: true
验证可能会与Rails 4中has_secure_password添加的验证冲突。请参阅Ryan B的回答here
另外,has_secure_password应该已为您validates :password_confirmation, presence: true
执行,因此您应该从模型中删除该行。