Often when I begin a project, I find myself rolling back migrations, dropping the database, renaming tables and columns whilst I figure out the shape of the model. If I need to rename a column, I’ll just update or delete the corresponding migration.
However, it is possible to change a column’s name in a migration.
Say, I have a table tasks and I want to change the name of the title column to name. First I ask Rails to generate the migration:
class RenameTitleToNameInTasks < ActiveRecord::Migration[6.0]
def change
end
end
I then remove change and add the up and down migration like so:
class RenameTitleToNameInTasks < ActiveRecord::Migration[6.0]
def up
rename_column :tasks, :title, :name
end
def down
rename_column :tasks, :name, :title
end
end
rename_column takes three arguments. The first is the table name. The second is the existing column name. The third is the new name.
Above, I have defined the up and down migration. That is, the up migration does the renaming bit when we migrate the database. The down migration runs when we roll back the migration – in this instance, it reverts the column’s name back to the original.
Before I run the migration, I give the schema a quick check.
Of course, five minutes later, I might decide that the new name probably isn’t the best and I can run rails db:rollback. On doing so, I can see that the column name has reverted to title.
A customer can have many green pencils. But, as far as the customer is concerned, these are just pencils. It makes sense for me to call the relationship that.
I first establish that a green pencil belongs to a customer.
I’m telling Rails that a Customer has many pencils, the associated class is GreenPencil and that this relationship is the other side of GreenPencil’s relationship with a customer that I established at the start.
Rails usually sets inverse_of on all associations itself. However, because the class name differs from the association name, we need to specifiy it explicitly.
Rails will infer the inverse relationship if we set foreign_key but I think inverse_of is clearer to the reader.
Sometimes it’s desirable to update one model’s attributes through an associated parent. Say, I might provide a form that asks a user for their name and email address but the user’s name is stored in the users table and their email address is recorded in another.
Rails provides the accepts_nested_attributes_for macro.
Ruby is a better Perl and in my opinion is an essential language for system administrators. If you are still writing scripts in Bash, I hope this inspires you to start integrating Ruby in to your shell scripts. I will show you how you can ease in to it and make the transition very smoothly.
I’ve learnt a few things from the article:
Debug output, and anything that does not belong in the output of the application should go to STDERR and only data that should be piped to anothe application or stored should go to STDOUT
There’s ARGF in addition to ARGV.
I can ask the user for a password without the password being echoed back to the terminal:
#!/usr/bin/rubyrequire'io/console'# The prompt is optionalpassword=IO::console.getpass"Enter Password: "puts"Your password was #{password.length} characters long."
I can check for return codes and errors via the $? object.
I can trap interrupt signals with Signal.trap().
#!/usr/bin/rubySignal.trap("SIGINT"){puts'Caught a CTRL-C / SIGINT. Shutting down cleanly.'exit(true)}puts'Running forever until CTRL-C / SIGINT signal is recieved.'whiletruedoend