Rails Migrations were introduced to be a convenient way to alter the database in a structured and organized manner, and effectively bring great consistency over time on a project.
Sass is a preprocessor scripting language that is interpreted or compiled into Cascading Style Sheets. SassScript is the scripting language itself. Sass consists of two syntaxes. Thanks for reading this article. I'd love to stay in touch and share more tips on programming and side projects with you. Sign up and I'll send you my articles straight to your email, you'll also get a free copy of the light themed version of my Git cheat sheet.
Sublime Cheat Sheet for Ruby & Ruby on Rails Icicle is a Web & Mobile consulting company focusing on Start ups, Digital Agencies & Enterprises. We create beautiful & engaging UX, clean Front Ends, scalable Applications and manage them on Cloud. Rails4 Model&Migration Generator (WorkInProgress) Cheat Sheet. A cheatsheet for rails 4 model and migration generator. 16 Dec 15, updated 13 May 16. Cheat Sheet Conventions. Bold words are what is really important e.g. The command and concept shown in the usage category. In the code usage and example columns these highlight the main part of the concept, like this: generalstuff.concept.In the same columns italicwords mark the arguments/parameters of a command/method. However italic words in the descriptions or general.
As Ruby on Rails developers (I’m assuming you are too 😘), we should be pretty familiar with Rails Migrations and the Rails generator. But while the most common migrations are no-brainers, some of them are not -or not clearly- covered in the manual. At work at Forest Admin it’s our job to handle every possible DB schema, in Rails, NodeJS and others, which means we’ve come across a few variations already. So let’s walk through 9 tricks for generators and migrations gathered from experience (and Stack Overflow 🙊).
List of tips (Level of expertise):
I’m starting with a basic that’s actually in the docs before getting to the tougher ones:
Rails automatically generates this kind of migrations thanks to the command line generator:
The migration file generated will contain the following line:
For instance:
Gives:
Which would remove the field/column 'name' from the Merchant table after running rake db:migrate
.
🌲 When using Forest Admin, for every new migration the server should be restarted and the webpage refreshed (🍎+R) for the new schema to be displayed correctly.
The Rails magic isn’t always enough: since this brutally throws away quite a lot of data at a time, there is no one line generator to drop entire tables. We need to generate a migration (important to get the timestamp that keeps everyone’s database synced), and manually add the deletion inside.
This will generate the empty .rb file in /db/migrate/ that still needs to be filled to drop the “Merchant” table in this case.
A Quick-and-Dirty™ implementation would look like this:
It’s “correct” as it shows that the migration is one-way only and should not/cannot be reversed. But in order to make a truly clean job in case these modifications were to be reversed we need to have a symmetrical migration (assuming we could recover the lost data), which we can do by declaring all the fields of our table in the migration file:
This can be long if the model is complex, but it ensures full reversibility.
Here again, changes will enter effect as usual after running rake db:migrate
.
It’s generally not a good idea to do that as migrations are made to ensure consistency over projects, environments, and time, and reverting one migration breaks the chain. However in some cases and for debugging, we can rollback the migration with the corresponding timestamp with this command:
Which will revert the corresponding migration file: dbmigrate20170815201547_create_merchants.rb
(where “create_merchants” does not play a role, as the only identifier is the timestamp).
Once again: ⚠️ This migrates down onlythis specific file, and not up to this specific file.
A better idea is to revert all migrations up to a certain point in time. In this case we can use the same command with the “STEP” argument defining the number of migration files we want to chronologically roll back:
As you probably know, to rollback only the last migration we can simply ommit the STEP argument:
Edit: as reported by MCAU, as of Rails 5.2 (and maybe some earlier versions), this is not actual anymore. Default values set in the active record migrations will apply not only to the database columns, but also when instantiating with Model.new()
. The hereunder recommendation can still apply in the case you would want to have some computed “virtual” attributes being setup upon instantiation.
Defining default values in ActiveRecord only works part of the time, in particular it won’t work when calling Model.new()
, as it won’t call anything from ActiveRecord.
Instead of “enforcing” the default values with a migration, writing an after_initialize
callback in our model will let us set the default values we need, and even associations:
This allows to have one flexible and easily editable place to initialize our models.
Overriding initialize
can also work, but let’s not forget to call super
to avoid breaking the init chain.
What’s the difference between string
and text
? And when should each one be used? Quite simply, the difference relies in how the symbol is converted into its respective column type in query language: for instance with MySQL :string is mapped to VARCHAR(255).
When should each be used?
As a general rule of thumb, use :string
for short text input (username, email, password, titles, etc.) and use :text
for longer expected input such as descriptions, comment content, etc. However, performance requirements can come into play.
With MySQL, we can have indexes on varchars, but we can’t have any on text. ➡️ Use :string when indexes are needed.
With POSTGRES, we should use :text wherever we can, unless there is a size constraint, since there is no performance penalty for text V/S varchar.
While creating a Migration
as for renaming a column, Rails 4 generates a change
method instead of up
and down
as mentioned in the above answer. The generated change
method is as below :
which will create a migration file similar to this :
It’s not always easy to find the right name for each model in advance. When I choose a poor name for a model, I sometimes resolve to changing it for the greater good, despite the work involved. Here is how to proceed;
Rails doesn’t quite have a ready to fire command line for that, but we can write it ourselves quickly. Let’s create a migration: Ulead movie factory 3 download.
Which we can then fill in with “rename_table”:
We will still have to go through and manually rename the model in all our files (And not forget to check for capitalized and pluralized versions of the model).
To fully delete and rebuild our database, we can either:
Which will reset the database and reload the current schema, or:
Which will destroy the DB, create a new one and then migrate the current schema.
⚠️ All data will be lost in both cases.
Just to compare the different dropping and migrating commands:
rake db:schema:load
- Creates tables and columns within the (existing) database following schema.rb. db:schema:load is used when you setup a new instance of your app.rake db:reset
Clears the database (presumably does a rake db:drop
+ rake db:create
+ rake db:migrate
) and runs migration on a fresh database.rake db:migrate
runs (single) migrations that have not run yet. Typically, you would use db:migrate after having made changes to the schema of an existing DB via new migration files.rake db:create
creates the databaserake db:drop
deletes the databaserake db:setup
does db:create, db:schema:load, db:seedrake db:reset
does db:drop, db:setuprake db:seed
runs the seeds task to populate the database with preliminary dataSometimes you need to make a perfect copy of a record, changing only one or a few values, such as for an association.
⛔️ Using the clone method will result in a shallow copy of the record, including copying the frozen state and the ID. No callbacks will be called either, which is probably not the effect we’ll be expecting for practical purposes.
✅ The dup method will duplicate the record calling after initialize hooks, clearing associations and IDs. A duped record will return true for new_record? and be 'saveable':
(Asked in the comments)
Example: If you have a User Model and you Add a status field
How would existing User record be updated with a value of status
after the migration?
(Response)
First, if you need all your users to have a status value, you would better specify a default value for new users to ensure it is not nil. This can be added as a parameter in the migration that adds the column, or later in another migration, as such:
Download mp3 hits of kishore kumar. Or with the one-liner:
To update the existing records, it’s a best practice to do it too through a migration, so that all the versions of the database will be up to date automatically (as opposed to running some code manually on each one of them).
The right way to do that is to create a one-way new migration where you will write the update code:
The migration should be one-way and not blindly set values back to nil in the down direction to avoid losing data if you were to roll it back.
Depending on your project, you could merge both migrations into one.
⚠️⚠️ Remember to only use raw Ruby+Rails logic in your migrations and never use anything except attributes coming from your own models.
If you need to use any kind of more advanced logic in your migration, define the methods you need in your migration and call them from there.
Using methods coming directly from your models can seem like a good idea at first to DRY your code, but with time and commits your model will change. The method you are calling in this migration might not run the same way, or exist anymore, which will prevent any new-comer to your project to run the migration set of the project smoothly.
Working with Rails’ JSON store is remarkably easy and convenient, but requires great care to make migration reversible to prevent frustration.
Consider the following case, where the chronology is important:
Our migration will then fail with an unintuitive error message:
What is happening is that the line declaring the hstore is still present in our model at this point. When Rails tries to run the migration, the model is called, and this line throws an error, as this same DB column we’re trying to create is supposed to be already available for use by the hstore; but does not exist yet.
Quick Fix
A quick fix is to remove the hstore declaration in the model and to migrate, then re-add it.
Better solution
In general, making hstore migrations fully reversible is not obvious. A migration allowing for model evolutions (if this hstore disappears a year from now and a newcomer needs to migrate their DB to the latest), and for data population at the same time (for instance if you are renaming an hstore or some of its attributes) will require 3 successive migration files, where hstore declarations should happen inside the migration files.