33

Update 3: It seems like this is specific to fixtures in a .yml.erb - even if I have no templated code, it seems like fixtures in a yml.erb file doesn't get loaded. Having a plain .yml file works. This likely has nothing to do with devise per se.

Note: see Update 3 annotations for relevant changes

I need to generate Devise users in my rails app. I notice that clearing the database and loading the fixtures loads all other fixtures, except the Devise users (Update 3: which is in a .yml.erb file).

I have seen this other thread, but I tried all the options there and still doesn't seem to load the fixtures.

# ../fixtures/users.yml.erb
user1:
  email: user1@mysite.com
  name: user1
  encrypted_password: <%= Devise.bcrypt(User, 'passw0rd!') %>
  # also tried encrypted_password: User.new(password_salt: '$2a$10$PoBe1MvkoGJsjMVTEjKqge').send(:password_digest, 'somepassword')
  admin: true

And from the console:

To clear the test db:

$ bundle exec rake db:schema:load RAILS_ENV=test

To load the fixtures into test db:

$ bundle exec rake db:fixtures:load RAILS_ENV=test

Run rails console in test (no users found, but other model fixtures, like App, are being loaded):

$ rails c test
Loading test environment (Rails 4.1.5)
irb(main):001:0> User.first
  User Load (0.1ms)  SELECT  "users".* FROM "users"   ORDER BY "users"."id" ASC LIMIT 1
=> nil
irb(main):002:0> App.first
  App Load (0.1ms)  SELECT  "apps".* FROM "apps"   ORDER BY "apps"."id" ASC LIMIT 1
=> #<App id: 953336129,...>

Update 1: Also tried passing in encrypted password generated from console, still no user records are found:

admin:
  email: user1@mysite.com
  name: user1
  encrypted_password: $2a$04$DR0.2yfWwD8AZlyeXx0gEuk2Qh.cNLF4cir0ZUB1iW7hwQhK/IfcC
  admin: true

Update 2: It works when I rename fixtures file to users.yml. Renaming to users.yml.erb seems to be the culprit. BTW, the same behavior is seen (that is, it works with .yml, but not with yml.erb) on the console and from rake test

Community
  • 1
  • 1
Anand
  • 3,690
  • 4
  • 33
  • 64

4 Answers4

38

You should pass the password in plain text too. I am sure there is a User model validation errors preventing your fixture users from being created. Here's an example from my users fixture which works:

tom:
  first_name: Tom
  last_name: Test
  email: test@example.org
  password: 123greetings
  encrypted_password: <%= User.new.send(:password_digest, '123greetings') %>

If it still fails, please check the log/test.log file for errors and check for missing required fields or other validation rules you set in your User model.

Update: It turns out that author found the issue himself - used .yml.erb file extension rather than .yml which made rails bypass that fixtures file. ERB works in yml fixtures as rails runs the fixture file through ERB before parsing it.

kroky
  • 1,266
  • 11
  • 19
  • Thanks, I have updated the question and details based on further investigation - seems like this is related to .yml.erb fixture files not loading, not specific to devise. See my updates in the question title and details. – Anand Oct 30 '14 at 07:54
  • Yes, you don't need the .erb extension, erb is working in fixtures even if they are just .yml files because rails processes them via erb before loading. – kroky Oct 30 '14 at 07:57
  • Yes, that is it! I am new to fixtures, and assumed that it needed an erb extension, just like view files containing erb code. Thanks! Please update the response with this, and I'll give you all the good karma I can :-) – Anand Oct 30 '14 at 08:04
  • @Anand, thanks but you found the answer, so I think you deserve the goodies :) – kroky Oct 30 '14 at 08:10
  • thanks! I have accepted your answer, since your comment confirmed my suspicion. BTW, wouldn't it be nice if the fixtures system accepted .yml.erb extension for consistency? – Anand Oct 30 '14 at 08:54
  • Yes, you can suggest that to ActiveRecord maintainers, it should be an easy fix to fixtures.rb file here: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/fixtures.rb – kroky Oct 30 '14 at 09:08
  • This is an odd way to do it. Create a new instance? Just use `Devise::Encryptor.digest(User, "123greetings")` <--- version 3.5.1 – sixty4bit Feb 23 '16 at 02:44
  • If you add column 'password', you'll still get the same error message. `tom: first_name: Tom last_name: Test email: test@example.org encrypted_password: <%= User.new.send(:password_digest, '123greetings') %>` works – rocLv Oct 11 '16 at 03:58
  • No need for `password`(there are no such column in DB). Fixtures go straight to DB without validation. @Jian Weihang answer works perfectly – Foton Dec 04 '19 at 10:09
14
<% 100.times do |n| %>
user_<%= n %>:
  email: <%= "user#{n}@example.com" %>
  encrypted_password: <%= Devise.bcrypt(User, 'password') %>
<% end %>

It's an alternative way to do the same thing, you don't have to new an instance.

# lib/devise/models/database_authenticatable.rb:147
def password_digest(password)
  Devise.bcrypt(self.class, password)
end

edit:

Thank @sixty4bit for pointing out deprecated usage, the updated answer would be:

<% 100.times do |n| %>
user_<%= n %>:
  email: <%= "user#{n}@example.com" %>
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
<% end %>
Weihang Jian
  • 7,826
  • 4
  • 44
  • 55
9

Since all of these answers were fairly confusing or out of date, the newest answer is that you need to use Devise::Encryptor.digest to create the encrypted_password.

Example:

# ../fixtures/users.yml.erb
user1:
  email: user1@mysite.com
  name: user1
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
  admin: true

user2:
  email: user2@mysite.com
  name: user2
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
  admin: false

Hope that helps!

Kyle Krzeski
  • 6,183
  • 6
  • 41
  • 52
-1
admin:
 id: 1
 first_name: admin
 last_name: tukaweb
 email: 'admin@email.com'
 encrypted_password: <%= User.new.send(:password_digest, 'admin@123') %>
 phone: 9541555660

regular:
 id: 2
 first_name: vidur
 last_name: punj
 email: 'vidur.punj@hotmail.com'
 encrypted_password: <%= User.new.send(:password_digest, 'punj@123') %>
 phone: 9541555660
vidur punj
  • 5,019
  • 4
  • 46
  • 65