Devise gem, rails 3, adding first record to db - ruby-on-rails

This may be my most stupid question yet:
I've implemented this tutorial on my Rails 3 app to get Devise up and running with CanCan. What is the right way to enter the first record in your development database, when only admins are allowed to enter a record and a null record isn't allowed? Do you just hack away some of the code to reduce permissions, then put it back again?
Update: to add to the answer, if you put this in seeds.db it works, even though there's no password field in the User table:
User.create(:email => 'me#mysite.com',:password => 'secret')

Use db/seeds.rb to write the code for your admin record. And call rake db:seed to execute that. Make sure you check whether the initial records are already created, so that running rake db:seed won't duplicate the data.

Related

Manually modifying data in Ruby on Rails without user input

Rails newbie here. I have a little question about Rails. I'd like to know if there's a way to modify values in the database by writing a piece of code somewhere in the app to change something without any user input or doing console commands. For example, let's say you have a users controller and wish to set a particular user's attributes to user ID number 1 every time you start your app.
For example, something like this gets set up on server start:
user ID: 1 username: 'User' pass:'Userpass' etc...
Thanks !
You should use seed.
Open db/seed.rb and just write required code to create the object. In your case:
User.create!(username: "myusername", password: "mypassword"...)
Then just hit following command from terminal which will persist a new user to your db and you can use that user anytime even after re-starting your application:
rake db:seed # Need to run only once while application setup.
More info is available under Migrations and Seed Data in Rails Guide

What is the best current practise to insert default/initial data into a ruby on rails database?

I have a new rails app with a fresh database and I want to add some default entries, like admin with default password etc.
How should I proceed?
I know of two possibilities, that both have drawbacks:
Use ruby code in migration: User.create!(:email => "admin#example.com", :password => "abc")
Use SQL code in migration: INSERT INTO users (id, email, password) VALUES (1, 'admin#example.com', 'abc')
The first alternative can break if I alter my code in later versions. The second is somewhat DBMS dependent.
As I do not plan to change my database, I would go with SQL code, but are there better alternatives?
Personally I'd use seed data
http://railscasts.com/episodes/179-seed-data
One advantage of this is that rake db:setup calls rake db:seed after it has created the database. Which is perfect for new machines.
The best way is to use Ruby code in db/seeds.rb.
The comment at the start of that file says:
This file should contain all the record creation needed to seed the
database with its default values. The data can then be loaded with
the rake db:seed (or created alongside the db with db:setup).
This is preferred over putting initialization code in the migration files.
I use the seed_fu gem, I haven't run into anything yet that it couldn't handle for me:
https://github.com/mbleigh/seed-fu

Factory Girl missing methods with schema fiddling?

I made a standard Active::Record class with a user_id field on it, and sure enough, the requirements changed. Turns out I needed to nix the 'user_id' column, and put on an 'email' column instead. I figured I would just manually replace the field in the migration file and then do a quick 'rake db:migrate down/up' on that version to make the update. I even ended up updating db/schema.rb as well.
No Dice:
Failure/Error: ss = Factory(:model)
undefined method `email=' for #<Model:0xb2cc288>
I can use email getter/setter methods in the console, or in the service fine -- but factory girl doesn't seem to get the hint. Is it caching a method list somewhere? (Hint: mysql table looks good too)
Firstly, in the future, try really hard not to change existing migration files. You will mess up more than just FactoryGirl, namely you will mess up your teammates' setups. Requirements change and that's OK, you just make a new migration that drops the user_id column and adds an e-mail column. This way, the evolution of the data model will be recorded in the migrations.
For your specific problem, though, you probably want to run rake db:test:prepare or, if that doesn't work, drop your test database completely and rebuild it.

Authlogic causing all rails tests to fail

I'm building an app in Rails 3 using Authlogic for authentication. I have a User model with a database table and a user_session model without one
All of my tests fail, whether I run
Error:
test_the_truth(UsersControllerTest):
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table:
user_sessions: DELETE FROM "user_sessions" WHERE 1=1
It's expecting user_session to have a table even though it inherits from Authlogic. Does anybody know how to fix this?
I was having the same problem and this took me a while to discover... the thing is Authlogic has no table in the database. When we create the sessions with Rails generate, this is creating also automatically a fixture, which of course will fail later since there is no table to fill data in. Solution: delete the fixture of user_sessions.
Read more about the problem here
Ensure you have defined properly test database in config/database.yml, then try rake db:test:prepare or rake db:migrate RAILS_ENV=test.

How (and whether) to populate rails application with initial data

I've got a rails application where users have to log in. Therefore in order for the application to be usable, there must be one initial user in the system for the first person to log in with (they can then create subsequent users). Up to now I've used a migration to add a special user to the database.
After asking this question, it seems that I should be using db:schema:load, rather than running the migrations, to set up fresh databases on new development machines. Unfortunately, this doesn't seem to include the migrations which insert data, only those which set up tables, keys etc.
My question is, what's the best way to handle this situation:
Is there a way to get d:s:l to include data-insertion migrations?
Should I not be using migrations at all to insert data this way?
Should I not be pre-populating the database with data at all? Should I update the application code so that it handles the case where there are no users gracefully, and lets an initial user account be created live from within the application?
Any other options? :)
Try a rake task. For example:
Create the file /lib/tasks/bootstrap.rake
In the file, add a task to create your default user:
namespace :bootstrap do
desc "Add the default user"
task :default_user => :environment do
User.create( :name => 'default', :password => 'password' )
end
desc "Create the default comment"
task :default_comment => :environment do
Comment.create( :title => 'Title', :body => 'First post!' )
end
desc "Run all bootstrapping tasks"
task :all => [:default_user, :default_comment]
end
Then, when you're setting up your app for the first time, you can do rake db:migrate OR rake db:schema:load, and then do rake bootstrap:all.
Use db/seed.rb found in every Rails application.
While some answers given above from 2008 can work well, they are pretty outdated and they are not really Rails convention anymore.
Populating initial data into database should be done with db/seed.rb file.
It's just works like a Ruby file.
In order to create and save an object, you can do something like :
User.create(:username => "moot", :description => "king of /b/")
Once you have this file ready, you can do following
rake db:migrate
rake db:seed
Or in one step
rake db:setup
Your database should be populated with whichever objects you wanted to create in seed.rb
I recommend that you don't insert any new data in migrations. Instead, only modify existing data in migrations.
For inserting initial data, I recommend you use YML. In every Rails project I setup, I create a fixtures directory under the DB directory. Then I create YML files for the initial data just like YML files are used for the test data. Then I add a new task to load the data from the YML files.
lib/tasks/db.rake:
namespace :db do
desc "This loads the development data."
task :seed => :environment do
require 'active_record/fixtures'
Dir.glob(RAILS_ROOT + '/db/fixtures/*.yml').each do |file|
base_name = File.basename(file, '.*')
say "Loading #{base_name}..."
Fixtures.create_fixtures('db/fixtures', base_name)
end
end
desc "This drops the db, builds the db, and seeds the data."
task :reseed => [:environment, 'db:reset', 'db:seed']
end
db/fixtures/users.yml:
test:
customer_id: 1
name: "Test Guy"
email: "test#example.com"
hashed_password: "656fc0b1c1d1681840816c68e1640f640c6ded12"
salt: "188227600.754087929365988"
This is my new favorite solution, using the populator and faker gems:
http://railscasts.com/episodes/126-populating-a-database
Try the seed-fu plugin, which is quite a simple plugin that allows you to seed data (and change that seed data in the future), will also let you seed environment specific data and data for all environments.
I guess the best option is number 3, mainly because that way there will be no default user which is a great way to render otherwise good security useless.
I thought I'd summarise some of the great answers I've had to this question, together with my own thoughts now I've read them all :)
There are two distinct issues here:
Should I pre-populate the database with my special 'admin' user? Or should the application provide a way to set up when it's first used?
How does one pre-populate the database with data? Note that this is a valid question regardless of the answer to part 1: there are other usage scenarios for pre-population than an admin user.
For (1), it seems that setting up the first user from within the application itself is quite a bit of extra work, for functionality which is, by definition, hardly ever used. It may be slightly more secure, however, as it forces the user to set a password of their choice. The best solution is in between these two extremes: have a script (or rake task, or whatever) to set up the initial user. The script can then be set up to auto-populate with a default password during development, and to require a password to be entered during production installation/deployment (if you want to discourage a default password for the administrator).
For (2), it appears that there are a number of good, valid solutions. A rake task seems a good way, and there are some plugins to make this even easier. Just look through some of the other answers to see the details of those :)
Consider using the rails console. Good for one-off admin tasks where it's not worth the effort to set up a script or migration.
On your production machine:
script/console production
... then ...
User.create(:name => "Whoever", :password => "whichever")
If you're generating this initial user more than once, then you could also add a script in RAILS_ROOT/script/, and run it from the command line on your production machine, or via a capistrano task.
That Rake task can be provided by the db-populate plugin:
http://github.com/joshknowles/db-populate/tree/master
Great blog post on this:
http://railspikes.com/2008/2/1/loading-seed-data
I was using Jay's suggestions of a special set of fixtures, but quickly found myself creating data that wouldn't be possible using the models directly (unversioned entries when I was using acts_as_versioned)
I'd keep it in a migration. While it's recommended to use the schema for initial setups, the reason for that is that it's faster, thus avoiding problems. A single extra migration for the data should be fine.
You could also add the data into the schema file, as it's the same format as migrations. You'd just lose the auto-generation feature.
For users and groups, the question of pre-existing users should be defined with respect to the needs of the application rather than the contingencies of programming. Perhaps your app requires an administrator; then prepopulate. Or perhaps not - then add code to gracefully ask for a user setup at application launch time.
On the more general question, it is clear that many Rails Apps can benefit from pre-populated date. For example, a US address holding application may as well contain all the States and their abbreviations. For these cases, migrations are your friend, I believe.
Some of the answers are outdated. Since Rails 2.3.4, there is a simple feature called Seed available in db/seed.rb :
#db/seed.rb
User.create( :name => 'default', :password => 'password' )
Comment.create( :title => 'Title', :body => 'First post!' )
It provides a new rake task that you can use after your migrations to load data :
rake db:seed
Seed.rb is a classic Ruby file, feel free to use any classic datastructure (array, hashes, etc.) and iterators to add your data :
["bryan", "bill", "tom"].each do |name|
User.create(:name => name, :password => "password")
end
If you want to add data with UTF-8 characters (very common in French, Spanish, German, etc.), don't forget to add at the beginning of the file :
# ruby encoding: utf-8
This Railscast is a good introduction : http://railscasts.com/episodes/179-seed-data

Resources