Reputation: 117
Working my way through a rails tutorial, getting stumped on this error.
Getting the above error when trying to run a validates uniqueness test. These errors seem to crop up after I insert a users fixture. I don't understand what I'm doing wrong, because my users model definitely has :password defined in the attr_accessible line, even though it seems to say users has no password attribute? Anyways, relevant lines of code below:
models/users:
attr_accessible :email, :password, :password_confirmation, :remember_me,
:first_name, :last_name, :profile_name
validates :profile_name, presence: true, uniqueness: true
fixtures/users.yml:
name:
first_name: "user1"
last_name: "user2"
email: "email.com"
profile_name: "user"
password: "pass"
password_confirmation: "pass"
user_test.rb:
user.profile_name = users(:name).profile_name
Upvotes: 2
Views: 2712
Reputation: 35349
has_secure_password
depends on BCrypt, which is used to hash passwords. You should have access to BCrypt inside fixtures. You can also use ERB. Use this technique to create password hashes for a known password.
homer:
first_name: "Homer"
...
password_digest: <%= BCrypt::Password.create('donuts', cost: 4) %>
Instead of manually setting the password_digest
into some unknown value in your fixtures, use BCrypt to create a password digest for a password of your choice.
Now, in your tests, you can do this:
test "homer logs in with correct password" do
user = users(:homer)
get '/login'
assert_success :response
post_via_redirect '/login', username: user.username, password: user.password
assert_equal '/profile', path
assert_not_nil session[:user_id]
assert_equal user.id, session[:user_id]
end
The cost
affects the speed of encryption, and the fastest is 4. This is good for fast tests.
You get an error because password
and password_confirmation
are virtual attributes added by has_secure_password
, and are not mapped to the database. The password_digest
column stores a salted and encrypted version of the password (called digest, or hash). Fixtures map attributes to database columns, so if you insert an attribute that does not map to a column you will get an SQL error like you found out.
Upvotes: 3
Reputation: 1219
I assume you are following the Treebook example by teamtreehouse, the fixture suggested in the video can't work as there are no columns named password or password_confirmation in the database, they are fields used by devise to create encrypted_password.
So to make the fixture correct, you have to populate an encrypted_password field like this:
name:
first_name: "Boat"
last_name: "Love"
profile_name: "Supahlovar"
email: "[email protected]"
encrypted_password = "$2a$10$8uCZ9wCTsFoqa0aIfpssne4qtchcpqhepdU5WylZwh4GBAkgFWEYe"
I think you can use any value for the encrypted password, but that is what an encrypted password look like when you retrieve it from the database.
Upvotes: 2
Reputation: 6485
Until an update I'm gonna say:
rake db:migrate
(also, if you don't even have the test database, maybe you should run rake db:test:prepare
first)
Upvotes: -1
Reputation: 25039
It doesn't say User has no password attribute, it says your users table in the database has no password column (and this is correct, it shouldn't.)
Without seeing the rest of your code (or knowing the structure of your users table, please add those to your question), I'm guessing you're missing a has_secure_password
line in your model.
Upvotes: 0