35

In my development and test environments, I want to seed the database with a bunch of users. I'm using Ruby on Rails v3.2.8 and the latest Devise. So I added this line in my db/seeds.rb file:

User.create(email: 'test@example.com', encrypted_password: '#$taawktljasktlw4aaglj')

However, when I run rake db:setup, I get the following error:

rake aborted! Can't mass-assign protected attributes: encrypted_password

What is the proper way to seed users?

at.
  • 50,922
  • 104
  • 292
  • 461

14 Answers14

51

You have to do like this:

user = User.new
user.email = 'test@example.com'
user.encrypted_password = '#$taawktljasktlw4aaglj'
user.save!

Read this guide to understand what mass-assignment is: http://guides.rubyonrails.org/security.html

I am wondering why do have to directly set the encrypted password. You could do this:

user.password = 'valid_password'
user.password_confirmation = 'valid_password'
Arun Kumar Arjunan
  • 6,827
  • 32
  • 35
  • 4
    If you were seeding a bunch of real users, and you had their email addresses which you were also seeding, would you also seed their password like that and let them change it once they sign on? or how would you do it? – BrainLikeADullPencil Jan 18 '13 at 19:11
  • The idea of storing the encrypted password there is that other developers do not know the actual password. It is a (weak) form of protection against accounts being compromised after the project's source code would be leaked. – Qqwy Sep 02 '17 at 22:08
30

Arun is right. It's easier just to do this in your seeds.rb

user = User.create! :name => 'John Doe', :email => 'john@gmail.com', :password => 'topsecret', :password_confirmation => 'topsecret'
George
  • 658
  • 5
  • 12
  • 3
    if you were seeding a bunch of real users, and you had their email addresses, would you also use that password and let them change it once and if they log on? – BrainLikeADullPencil Jan 18 '13 at 19:11
16

The skip_confirmation method will only work if you have confirmable module in your user model, otherwise remove it.

  user = User.new(
      :email                 => "admin@xxxxx.xxx",
      :password              => "123456",
      :password_confirmation => "123456"
  )
  user.skip_confirmation!
  user.save!
Shark Lasers
  • 441
  • 6
  • 15
Muhammad Sannan Khalid
  • 3,127
  • 1
  • 22
  • 36
8

This is an old question but here is an example with an admin user (from cancancan):

User.create!([
  {email: "testadmin@mvmanor.co.uk", password: "testadminuser", password_confirmation: "testadminuser", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-02-06 14:02:10", last_sign_in_at: "2015-02-06 14:02:10", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", admin: true},
  {email: "testuser@mvmanor.co.uk", password: "testuseraccount", password_confirmation: "testuseraccount", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-02-06 14:03:01", last_sign_in_at: "2015-02-06 14:03:01", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", admin: false},
  {email: "testcustomer@customer.co.uk", password: "testcustomeruser", password_confirmation: "testcustomeruser", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-02-06 14:03:44", last_sign_in_at: "2015-02-06 14:03:44", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", admin: false}
])
Veger
  • 37,240
  • 11
  • 105
  • 116
Koxzi
  • 1,021
  • 1
  • 10
  • 21
8

If you're using the devise confirmable module you need to do something like:

user = User.new(
  email: 'user@domain.com', 
  password: '123456789', 
  password_confirmation: '123456789'
)
user.skip_confirmation!
user.save!

The skip_confirmation! call just tell to devise that you don't need to confirm this account.
Other option is just set the confirmed_at user attribute as Time.now.utc before save.

Victor
  • 5,043
  • 3
  • 41
  • 55
4

To seed the users table:

User.create(
        email: "example@gmail.com",
        password: "12345678"
    )

With devise installed, the :password will be automatically hashed and saved to :encrypted_password

doncadavona
  • 7,162
  • 9
  • 41
  • 54
4

I don't know if it may help but actually I'm doing this to create a default Admin user in my Rails 5 app but without sharing the password in plain text in my GitHub repository.

Basically the logic for this is:

  • Generate a secure random password for the default user when seeded.
  • Go to ".../admins/sign_in" and click on "Forgot your password?" link to RESET it.
  • Get the reset password link in that default email account.
  • Set a new password.

So in the db/seeds.rb append this:

randomPassword = Devise.friendly_token.first(8)
mainAdminUser = Admin.create!(email: "me@gmail.com", password: randomPassword, name: "Username")

And if you are using devise confirmable feature just skip confirmable option by doing this:

mainAdminUser = Admin.new(
    email: "me@gmail.com",
    password: randomPassword,
    password_confirmation: randomPassword,
    name: "Username"
)
mainAdminUser.skip_confirmation!
mainAdminUser.save!

And your good to go!

Now you have a default user but you are not sharing a default password! I hope it could be useful for somebody.

alexventuraio
  • 8,126
  • 2
  • 30
  • 35
2

Don't try create the encrypted password, devise handles that for you. This will work, just make sure the password is a minimum 6 characters long.

User.create(
        email: "test@test.com",
        password: "123456"
    )

Even better, in your terminal:

$bundle add faker

Then:

User.create(
            email: test@test.com,
            password: "123456"
        )
10.times do
  User.create(
              email: Faker::Internet.email,
              password: "123456"
           )
end

Just make sure you set at least one email in your seeds that you can remember. Hence retaining the 'test' email.

jfgilmore
  • 73
  • 8
1

Use your db/seeds.rb file to initiate your first user:

User.create!(email: 'palo@alto.com', 
             password: '123456789', 
             password_confirmation: '123456789')
aloucas
  • 2,967
  • 1
  • 19
  • 15
1

For devise users in seeds.rb file, what worked for me was to use a generic password upon saving the new user. Then update the encrypted password and save the model again. This was a hacky way.

user = User.new(
    :email                 => "admin@xxxxx.xxx",
    :password              => "fat12345",
    :password_confirmation => "fat12345"
)
user.save!
user.encrypted_password="ENCRYPT.MY.ASS!!!KJASOPJ090923ULXCIULSH.IXJ!S920"
user.save

UPDATE others have posted and this is better way to do it:

user = User.new(
    email: "foo@bar.com", 
    password: "foob1234", 
    password_confirmation: "foob1234"
)
user.skip_confirmation! #only if using confirmable in devise settings in user model.
user.save!
lacostenycoder
  • 10,623
  • 4
  • 31
  • 48
0

I Did something same in one of my requirements so just pasting my snippet

def triggerSeedUsers
      p "Starting Seeding Users..."
      p   "Deleting all users"..
      User.destroy_all
      normal_users = [{:email => 'abc@domain.com', :login => "abc_demo", :name => 'abc Demo'}]
      admin_users = [{:email => 'admin@domain.com', :login => 'abc_admin', :name => 'abc Admin'}]

      [normal_users,admin_users].each do |user_type|
        user_type.each do |user|
          User.create!(:name => user[:name],
            :login => user[:login],
            :email => user[:email],
            :first_login => false,
            :password => 'P@ssw0rd',
            :password_confirmation => 'P@ssw0rd'
            )
        end
      end
      User.where('name LIKE ?', '%demo%').update_all(:is_admin => 0)
      User.where('name LIKE ?', '%admin%').update_all(:is_admin => 1)
     end
AnkitG
  • 6,438
  • 7
  • 44
  • 72
0

with email confirmating in db:seed :

User.create!( name: 'John', email:'john@hotmail.com', password: '123456', password_confirmation: '123456',confirmed_at: '2018-08-04 04:51:43', current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1")
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
vidur punj
  • 5,019
  • 4
  • 46
  • 65
0

Just add :password attribute rest, devise will do password_encrypt for you

user = User.new({ email: 'test@example.com', password: 'EnterYourPassword'})
user.save!
flash[:notice] = 'User Created'

#or for extra logic

        #if user.save
          #ExtraCredentialsOrLogic

        #elsif user.errors.any?
          #user.errors.full_messages.each do |msg|
            #puts msg
          #end
        #else
          #puts "****NOT VALID****"
    #end

and now run 'rake db:seed'

Bilal A.Awan
  • 290
  • 3
  • 7
0

This allows you to run a seed multiple times without errors:

User.where(email: "you@email.com").first_or_create.update_attributes(nome: "Your Name",
    email: "you@email.com",
    password:              "password#123",
    password_confirmation: "password#123")
Leonel Sanches da Silva
  • 6,972
  • 9
  • 46
  • 66