rake function in ruby-on-rails - ruby-on-rails

I am very new in ruby-on-rails. I have doubt in rake. create function is create a new db. After that, we want to run some commands like
rake db:load
rake db:data:load
rake db:schema:load
rake db:migrate
rake db:seed
But why we want to run this cmds after create the db and what function of the about cmd.
Thanks for your advice.

You can use rake -T to get the description of each task:
$ rake -T | grep db
rake db:create # Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)
rake db:drop # Drops the database for the current Rails.env (use db:drop:all to drop all databases)
rake db:fixtures:load # Load fixtures into the current environment's database.
rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false).
rake db:migrate:status # Display status of migrations
rake db:rollback # Rolls the schema back to the previous version (specify steps w/ STEP=n).
rake db:schema:dump # Create a db/schema.rb file that can be portably used against any DB supported by AR
rake db:schema:load # Load a schema.rb file into the database
rake db:seed # Load the seed data from db/seeds.rb
rake db:setup # Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the db first)
rake db:structure:dump # Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql
rake db:version # Retrieves the current schema version number
I this what you were asking about?
EDIT:
You can read more about what migrations are for here: http://guides.rubyonrails.org/migrations.html
EDIT 2:
rake db:migrate allows you to update the DB schema in a "sane" way: you can create a new migration (read the guides!) and add a new column for example, add an index, rename a column, etc. - migrations allow you to "travel" back and forth in "time" - you can run the migration and rollback it later.
When you generate a new migration:
$ rails g migration add_new_column_to_some_table you will be able to run rake db:migrate later on to apply to changes you want (of course you have to write the body of this generated migration).
I STRONLY advise you to read the guides though :)
EDIT 3:
add_column :users, :price, :float, for example, will add price column to the users table, the type of the column will be float (float isn't a best idea to store money related things BTW!). This column will be NULL by default.
EDIT 4:
Information about which migrations were run is stored in schema_migrations table: running migration for the first time will add a new record in this table with version of this migration (date + some random numbers from the name of the file). Rollbacking a migration will remove this record. Running a migration twice will not have any effect.

Simply put, db:migrate doesn't destroy existing data you have in your database. so running migrations and that rake task allows your data to exist from changes you make.
Workflow in words
You create an empty data base.
You will want to add a table of data for your first model into the database. This is done by editing a file in db/migrate
Now you want a second model, so you create your model and edit the migration file in db/migrate that was created for you
The easiest way to update your database without destroy any of the existing data, is to run bundle exec rake db:migrate. This adds the contents of the second migration file into the db and won't hurt existing data.
Example workflow after creating a project:
bundle exec rake db:create:all
bundle exec rails generate scaffold Users name:string email:string
bundle exec rake db:migrate
At this stage, bundle exec rails s and go to localhost:3000/users/new and create a new user.
bundle exec rails generate scaffold Posts title:string body:text
bundle exec rake db:migrate
Back in your browser go to localhost:3000/users and you should still see the user you created.

Related

How to completely delete a DB on Ruby on Rails?

I have a small Ruby on Rails app, and I made a mistake creating a model and so on.
How can I fully delete its database? Not reseting migrations or dropping its tables, but to delete all db related files? (schema.rb, etc)
To drop database
rake db:drop
Then for creating database
rake db:create
For migrations
rake db:migrate
For seed
rake db:seed
Deleting these files will not remove the database from your system. You should never delete your schema.rb because it holds the structure of your database. (And not the database records themselves.) If you simply created a new model, Rails does not automatically create a database table (that's what migrations do).
If you still want to drop your entire database (the structure and data), this is the command you need (found when calling rake -T)
rake db:drop # Drops the database from DATABASE_URL or
# config/database.yml for the current RAILS_ENV
# (use db:drop:all to drop all databases)
By default, RAILS_ENV is not set. If you called rake db:drop during this state, all databases associated with this app will be dropped. In order to drop, say, only development:
export RAILS_ENV=development
rake db:drop
You can do the same with test and production environments.

Rails: How to delete a pending migration

I'm currently following the ruby on rails tutorial: http://guides.rubyonrails.org/getting_started.html.
I am trying to save data into the database. However, when I run: rails server I get the following error:
Migrations are pending. To resolve this issue, run: bin/rake db:migrate RAILS_ENV=development
I've looked at the other articles and when I run:
bin/rake db:migrate
I get a rake aborted!
After running:
rake db:abort_if_pending_migrations....
I see that:
You have 1 pending migration:
20150805200129 CreateDatabases
SQLite3::SQLException: table "databases" already exists:
and it just tells me to run rake db:migrate to start again.
It seems that it already exists. Is there a way to cancel the pending migration?
Sometimes, even dropping a local development database is not a good idea.
There are better ways to delete/destroy a specific migration in your Rails application.
You could use rails d migration command to destroy a particular migration:
rails d migration MigrationName
To undo the changes corresponding to a particular migration, you can use db:migrate:down method like this:
rake db:migrate:down VERSION=XXX
Sometimes, things could get more messy and in those situation another handy thing is to take a look at the schema_migrations table in your database which has all the migrations with their version saved in it.
You can delete a particular migration from this table like this:
delete from schema_migrations WHERE version = VERSION;
if you don't want that migration to be present anymore.
Your migration may have failed midway (so it created the table, but didn't finish).
You are just using development environment, so it's okay to just drop the database and rebuild it from scratch:
rake db:drop # THIS WILL DELETE YOUR DATABASE
rake db:create
rake db:migrate
If you are like me and maintain your database structure outside of Rails, you can just delete the migration file from db/migration. I got the error in the OP's question when I used the rails generate command to create a model class, forgetting that it also creates a migration file.
Do not use this method if you rely on Rails to maintain your database structure!
I keep my Rails structure file up to date by building it from the database using:
bundle exec rake db:structure:dump
I do not encourage to drop the database and start from the beginning especially when you already have the data inside the database.
My approach to this will be migrate first, then rollback. After that you can safely delete the migration file. So the procedure is as following.
rails db:migrate
rails db rollback
rm db/migrate/your_last_migration_file.rb
You can recreate database and run all migrations in your development environment with such command
rails db:migrate:reset
If you want to revert the wrong migrations, You can drop the whole db using this:
rake db:drop
Then remove the migrations file manually(This wont corrupt the db when you recreate as the Schema migrations would be dropped as well).
Then run
rake db:migrate
And if there is data to be seeded, then run this as well
rake db:setup

how to run schema.rb?

I'm trying to run db:migrate.
This fails however because one of the tables that one of the migrations is trying to update does not exist. I searched the codebase and this table is created in db/schema.rb.
How can I run schema.rb before db:migrate??
Use the schema load task:
rake db:schema:load
From rake -T (expurgated version):
rake db:schema:dump # Create db/schema.rb file usable with any AR-supported DB
rake db:schema:load # Load schema.rb file into DB

How to revert all migrations at once in Ruby on Rails 3?

I tried to run:
rake db:migrate VERSION=0
It reverts all migrations except the last one.
Then I tried to run:
rake db:migrate:down VERSION=<timestamp_of_last_migration>
but it didn't revert either. Why ?
Is there a command that runs all down methods at once ?
If your database only related to this project, and you are trying to undo everything in your migrations, I'd simply drop the database, and then run rake db:create.
Then you have an empty database ready to go.
Or is there another reason you're trying to run the down scripts?
You could check this list.
Maybe this could help you
rake db:create[:all]: If :all not specified then create the database defined in config/database.yml for the current RAILS_ENV. If :all is specified then create all of the databases defined in config/database.yml.
rake db:fixtures:load: Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y
rake db:migrate [VERSION=n]: Migrate the database through scripts in db/migrate. Target specific version with VERSION=n
rake db:migrate:redo [STEP=n]: (2.0.2) Revert the database by rolling back "STEP" number of VERSIONS and re-applying migrations.
rake db:migrate:reset: (2.0.2) Drop the database, create it and then re-apply all migrations. The considerations outlined in the note to rake db:create apply.
rake db:reset: Drop and re-create database using db/schema.rb. The considerations outlined in the note to rake db:create apply.
rake db:rollback [STEP=N]: (2.0.2) Revert migration 1 or n STEPs back.
rake db:schema:dump: Create a db/schema.rb file that can be portably used against any DB supported by AR
rake db:schema:load: Load a schema.rb file into the database
rake db:sessions:clear: Clear the sessions table
rake db:sessions:create: Creates a sessions table for use with CGI::Session::ActiveRecordStore
rake db:structure:dump: Dump the database structure to a SQL file
rake db:test:clone: Recreate the test database from the current environment's database schema
rake db:test:clone_structure: Recreate the test databases from the development structure
rake db:test:prepare: Prepare the test database and load the schema
rake db:test:purge: Empty the test database
there is another way:
rake db:rollback STEP=100
this will revert last 100 migrations
taken from http://guides.rubyonrails.org/migrations.html#rolling-back
try:
rake db:migrate:down VERSION=<timestamp_of_first_migration>
this will run the self.down for your first migration, essentially wiping everything out. at least, it just did for me!

Purge or recreate a Ruby on Rails database

I have a dev Ruby on Rails database full of data. I want to delete everything and rebuild the database. I'm thinking of using something like:
rake db:recreate
Is this possible?
I know two ways to do this:
This will reset your database and reload your current schema with all:
rake db:reset db:migrate
This will destroy your db and then create it and then migrate your current schema:
rake db:drop db:create db:migrate
All data will be lost in both scenarios.
On Rails 4, all needed is
$ rake db:schema:load
That would delete the entire contents on your DB and recreate the schema from your schema.rb file, without having to apply all migrations one by one.
I use the following one liner in Terminal.
$ rake db:drop && rake db:create && rake db:migrate && rake db:schema:dump && rake db:test:prepare
I put this as a shell alias and named it remigrate
By now, you can easily "chain" Rails tasks:
$ rake db:drop db:create db:migrate db:schema:dump db:test:prepare # db:test:prepare no longer available since Rails 4.1.0.rc1+
Update: In Rails 5, this command will be accessible through this command:
rails db:purge db:create db:migrate RAILS_ENV=test
As of the newest rails 4.2 release you can now run:
rake db:purge
Source: commit
# desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
task :purge => [:load_config] do
ActiveRecord::Tasks::DatabaseTasks.purge_current
end
It can be used together like mentioned above:
rake db:purge db:create db:migrate RAILS_ENV=test
Depending on what you're wanting, you can use…
rake db:create
…to build the database from scratch from config/database.yml, or…
rake db:schema:load
…to build the database from scratch from your schema.rb file.
From the command line run
rake db:migrate:reset
In Rails 6 there is a convenient way for resetting DB and planting seeds again:
rails db:seed:replant # Truncates tables of each database for current environment and loads the seeds
https://weblog.rubyonrails.org/2019/3/15/this-week-in-rails-security-fixes-bulk-insert-and-upsert-seeds-replanting/
Use like
rake db:drop db:create db:migrate db:seed
All in one line. This is faster since the environment doesn't get reloaded again and again.
db:drop - will drop database.
db:create - will create database (host/db/password will be taken from config/database.yml)
db:migrate - will run existing migrations from directory (db/migration/.rb)*.
db:seed - will run seed data possible from directory (db/migration/seed.rb)..
I usually prefer:
rake db:reset
to do all at once.
Cheers!
Just issue the sequence of the steps: drop the database, then re-create it again, migrate data, and if you have seeds, sow the database:
rake db:drop db:create db:migrate db:seed
Since the default environment for rake is development, in case if you see the exception in spec tests, you should re-create db for the test environment as follows:
RAILS_ENV=test rake db:drop db:create db:migrate
In most cases the test database is being sowed during the test procedures, so db:seed task action isn't required to be passed. Otherwise, you shall to prepare the database:
rake db:test:prepare
or
RAILS_ENV=test rake db:seed
Additionally, to use the recreate task you can add into Rakefile the following code:
namespace :db do
task :recreate => [ :drop, :create, :migrate ] do
if ENV[ 'RAILS_ENV' ] !~ /test|cucumber/
Rake::Task[ 'db:seed' ].invoke
end
end
end
Then issue:
rake db:recreate
You can manually do:
rake db:drop
rake db:create
rake db:migrate
Or just rake db:reset, which will run the above steps but will also run your db/seeds.rb file.
An added nuance is that rake db:reset loads directly from your schema.rb file as opposed to running all the migrations files again.
You data gets blown away in all cases.
You can use this following command line:
rake db:drop db:create db:migrate db:seed db:test:clone
To drop a particular database, you can do this on rails console:
$rails console
Loading development environment
1.9.3 > ActiveRecord::Migration.drop_table(:<table_name>)
1.9.3 > exit
And then migrate DB again
$bundle exec rake db:migrate
On rails 4.2, to remove all data but preserve the database
$ bin/rake db:purge && bin/rake db:schema:load
https://github.com/rails/rails/blob/4-2-stable/activerecord/CHANGELOG.md
You can use
db:reset - for run db:drop and db:setup or
db:migrate:reset - which runs db:drop, db:create and db:migrate.
dependent at you want to use exist schema.rb
According to Rails guide, this one liner should be used because it would load from the schema.rb instead of reloading the migration files one by one:
rake db:reset
Because in development , you will always want to recreate the database,you can define a rake task in your lib/tasks folder like that.
namespace :db do
task :all => [:environment, :drop, :create, :migrate] do
end
end
and in terminal you will run
rake db:all
it will rebuild your database
3 options, same result:
1. All steps:
$ rake db:drop # deletes the database for the current env
$ rake db:create # creates the database for the current env
$ rake db:schema:load # loads the schema already generated from schema.rb / erases data
$ rake db:seed # seed with initial data
2. Reset:
$ rake db:reset # drop / schema:load / seed
3. Migrate:reset:
$ rake db:migrate:reset # drop / create / migrate
$ rake db:seed
Notes:
If schema:load is used is faster than doing all migrations, but same result.
All data will be lost.
You can run multiple rakes in one line.
Works with rails 3.
I think the best way to run this command:
**rake db:reset** it does db:drop, db:setup
rake db:setup does db:create, db:schema:load, db:seed
Simply you can run
rake db:setup
It will drop database, create new database and populate db from seed if you created seed file with some data.
I use:
rails db:drop to delete the databases.
rails db:create to create the databases based on config/database.yml
The previous commands may be replaced with rails db:reset.
Don't forget to run rails db:migrate to run the migrations.
I've today made quite a few changes to my rails schema. I realised I needed an additional two models in a hierarchy and some others to be deleted. There were many little changes required to the models and controllers.
I added the two new models and created them, using:
rake db:migrate
Then I edited the schema.rb file. I manually removed the old models that were no longer required, changed the foreign key field as required and just reordered it a bit to make it clearer to me. I deleted all the migrations, and then re-ran the build via:
rake db:reset
It worked perfectly. All the data has to be reloaded, of course. Rails realised the migrations had been deleted and reset the high-water mark:
-- assume_migrated_upto_version(20121026094813, ["/Users/sean/rails/f4/db/migrate"])
TL;DR - I use this rake script during development to blow away everything, including the schema file, then rebuild directly from migration scripts. It rebuilds both dev and test databases simultaneously. It's the only way I've found to guarantee everything lines up the way I expect. Been using it for years without a problem.
# lib/tasks/db_rebuild.rake
require 'fileutils'
namespace :db do
desc "Create DB if it doesn't exist, then migrate and seed"
task :build do
Rake::Task["db:create"].invoke
Rake::Task["db:migrate"].invoke
Rake::Task["db:seed"].invoke
end
desc "Drop database and rebuild directly from migrations (ignores schema.rb)"
task :rebuild do
raise "Task not permitted in production." if ENV["RAILS_ENV"] == "production"
puts "*** Deleting schema.rb"
system "rm -f #{Rails.root.join("db", "schema.rb")}"
puts "*** Deleting seed lock files"
system "rm -f #{Rails.root.join("db", ".loaded*")}"
puts "*** Recreate #{ENV['RAILS_ENV']} database"
begin
Rake::Task['environment'].invoke
ActiveRecord::Base.connection
rescue ActiveRecord::NoDatabaseError
# database doesn't exist yet, just create it.
Rake::Task["db:build"].invoke
rescue Exception => e
raise e
else
Rake::Task["db:environment:set"].invoke
# https://github.com/rails/rails/issues/26319#issuecomment-244015760
# ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] = '1'
Rake::Task["db:drop"].invoke
Rake::Task["db:build"].invoke
end
Rake::Task["db:retest"].invoke
end
desc "Recreate the test DB"
task :retest do
system("rake db:drop db:build RAILS_ENV=test")
end
end
Rationale - The problem with all the provided solutions is that native Rake tasks provided by Rails rely on schema.rb. When I am doing heavy data modeling, I make changes directly to the migration files; only after they've been committed upstream do we treat them as immutable. But if I make changes to the migration file, they aren't reflected in schema.rb.
The other problem is the distinction between dev and test environments. Rails db tasks handle them independently, but in my experience dev and test databases should always maintain parity, which means I had to run lots of duplicative database cleanup when developing.

Resources