Rails 5 is now out and I am upgrading my basic login/CRUD app to use the new framework, which involved updating Devise to 4.2 as well. Things were pretty straightforward, except for one rspec
test that is failing. I tried stepping through the code with pry
, but finding the problem was beyond me. Any pointers would be appreciated.
This is the error:
Failures:
1) User email rejects email addresses with improper format
Failure/Error: expect(user).not_to be_valid
ArgumentError:
wrong number of arguments (given 0, expected 1)
# ./spec/models/problem_test_user_spec.rb:13:in `block (4 levels) in <top (required)>'
# ./spec/models/problem_test_user_spec.rb:11:in `each'
# ./spec/models/problem_test_user_spec.rb:11:in `block (3 levels) in <top (required)>'
Here is the pared-down test:
1 require 'rails_helper'
2 require 'devise'
3
4 RSpec.describe User, type: :model do
5 let (:user) { FactoryGirl.create :user }
6
7 describe "email" do
8 it "rejects email addresses with improper format" do
9 invalid_addresses = %w[ user@example,com user_at_foo.org user.name@example. ]
10
11 invalid_addresses.each do |addr|
12 user.email = addr
13 expect(user).not_to be_valid
14 end
15 end
16 end
17 end
And here is my model:
class User < ApplicationRecord
devise :database_authenticatable, :validatable
validates :email, length: { maximum: 254 } # max length per RFC 3696, errata ID 1690
end
Here is my factory:
FactoryGirl.define do
factory :user do
name { Faker::Name.name }
tone_name { "#{Faker::Company.name} Tone" }
email { Faker::Internet.email }
password SOME_PASSWORD
password_confirmation SOME_PASSWORD
admin false
end
end
One postscript: the app runs fine in my development environment, but it will allow an invalid password of the form name@example,com
where the rails 4.2 version passes the rspec
test and catches this invalid password with an error.
Another clue: I learned that Devise changed the default email_regexp
to a less strict expression in v4.1. My test is actually failing because an email address that used to be identified as illegal now is accepted. The ArgumentError
is not in my code. I believe it is an error either in Devise or in Rspec. If I put a binding.pry
in my test, then a simple #inspect
on my model causes the following:
12: invalid_addresses.each do |addr|
13: user.email = addr
14: binding.pry
=> 15: expect(user).not_to be_valid
16: end
17: end
18: end
19: end
[1] pry(#<RSpec::ExampleGroups::User::Email>)> user.inspect
ArgumentError: wrong number of arguments (given 0, expected 1)
from /Users/tarsa/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/devise-4.2.0/lib/devise/models/database_authenticatable.rb:146:in `password_digest'
The Devise code does not look to be at fault, I suspect some interaction with ActiveRecord is going on, but I am at the limit of my debugging skills at this point.
I can workaround the problem by configuring Devise to use the 4.0.3 version of email_regexp
. If all the password strings are recognized as invalid, then the bug, wherever it is, does not get tickled.
The problem was not a Rails 5 issue, but turned out to be from my continued use of password_digest
in my model, which was originally validated with ActiveRecord. When I switched to Devise, I left this attribute in the table. As of Devise 4.2.0, the mechanism by which validation is done was changed to use serializable_hash
and that is trying to call the vestigal password_digest
attribute as a method, causing the error.
Removing the field eliminated the problem and the test failed with the proper message.
Thanks to the folks at Devise for the insight into this.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.