In my previous blog I was talking about Active Record magic. I mentioned one useful command but there are quite a few of them so I decided to write about the most frequently used rails commands in this post.
The creator, David Heinemeier Hansson, was making web applications with Ruby and noticed that he was just copy pasting common parts from previous apps into his new work. As a developer, he (and all of us) loved solving hard problems. The only way to get to solving the hard problems that are unique to the domain you are working in is to go up a layer of abstraction. The nitty-gritty of basic web apps should be removed from your head. With Rails, you are able to focus on the hard bits and let the repetitive work melt away. Rails commands are magical but it’s important to understand what each command is responsible for and how to write them.
What is Rails? 🛤
Rails is a web-application framework that includes everything needed to create database-backed web applications according to the Model-View-Controller (MVC) pattern.
MVC divides your application into three layers: Model, View, and Controller, each with a specific responsibility.
A schematic representation of the model-view-controller (MVC) architecture.
The Model layer represents the domain model (such as Account, Product, Person, Post, etc.) and encapsulates the business logic specific to your application. In Rails, database-backed model classes are derived from
ActiveRecord::Base. Active Record allows you to present the data from database rows as objects and embellish these data objects with business logic methods. Although most Rails models are backed by a database, models can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as provided by the Active Model module.
The Controller layer is responsible for handling incoming HTTP requests and providing a suitable response. Usually this means returning HTML, but Rails controllers can also generate XML, JSON, PDFs, mobile-specific views, and more. Controllers load and manipulate models, and render view templates in order to generate the appropriate HTTP response. In Rails, incoming requests are routed by Action Dispatch to an appropriate controller, and controller classes are derived from
ActionController::Base. Action Dispatch and Action Controller are bundled together in Action Pack.
The View layer is composed of “templates” that are responsible for providing appropriate representations of your application’s resources. Templates can come in a variety of formats, but most view templates are HTML with embedded Ruby code (
ERB files). Views are typically rendered to generate a controller response, or to generate the body of an email. In Rails, View generation is handled by Action View.
Create a New Rails App
To start with let’s build an application from scratch. Before we continue, please make sure that you have Ruby, RubyGems, and Bundler installed on your system.
Open a terminal navigate to a directory where you have rights to create files.
The first thing we’ll want to do is to create a new Rails application by running the
rails new <project name> command after installing Rails.
To create an API-only Rails build from scratch, include the
--api after the name of the Rails application name upon creation:
rails new <my_app_name> --database=postgresql --api (Postgresql makes it easier to deploy your app, don’t forget to install it before running this command, you can find steps for installation here). For example,
rails new Gallery --database=postgresql --api
By using the
--api flag, Rails will remove a lot of default features and middleware, mostly related to the browser, since it won't be needed. Controllers will inherit from
ActionController::API rather than
ActionController::Base and generators will skip generating views.
No changes are required when setting up resources for an API-only Rails build.
bundle install after adding all the necessary gems into the Gemfile.
Initialize the database:
Start the Rails server:
rails s. Use if you want to access your application through a web browser: http://localhost:3000
A primary goal of the Rails team was to make it efficient to build core application functionality. The Rails system has a number of generators that will do some of the manual work for us.
As nice as it is to use the generators to save time, they also provide some additional extra benefits:
- They can set up some basic specs for an application’s test suite. They won’t write our complex logic tests for us, but they will provide some basic examples.
- They are set up to work the same way each time. This helps standardize your code and enables your development to be more efficient since you don’t have to worry as much about bugs related to spelling, syntax errors, or anything else that can occur when writing code manually.
- They follow Rails best practices, which includes utilizing RESTful naming patterns, removing duplicate code, using partials and a number of other best of breed design patterns. (If you don’t know what all of these are, don’t worry — we will cover them shortly.)
However, certain generators create quite a bit of code. If that code is not going to be used, it will needlessly clutter the application code and cause confusion for future developers. So when is the right time to use a generator? Let’s take a closer look. 🧐
All of the Rails generators are entered as commands into the terminal and will follow this syntax:
rails generate <name of generator> <options> --no-test-framework
--no-test-framework is a flag that tells the generator not to create any tests for the newly-generated models, controllers, etc. When you're working on your own Rails applications, you don't need the flag — it's quite helpful for quickly stubbing out a test suite.
For efficiency’s sake, Rails aliased the
generate method to
g, so the CLI command above could be shortened to:
rails g <name of generator> <options> --no-test-framework
Different types of generators
Below are the main generators that Rails offers. We’ll go through examples of each:
Rails has a great set of migration generators with conventions that can help make managing the database schema very efficient. After drawing the domain model we can proceed.
Let’s start using database migrations in our case gallery application and update the
painters table. To add a new column called
portrait, we can use the following command:
rails g migration add_portrait_to_painters portrait:string --no-test-framework
In the terminal you will see it creates a migration file for us:
20200928055457_add_portrait_to_painters.rb. Since migration file names need to be unique, the generator prepends a timestamp before the file name. Ready to see something pretty cool? Open up the file it created, which you can find in the
db/migrate directory. It should look something like this:
class AddPortraitToPainters < ActiveRecord::Migration[6.0]
add_column :painters, :portrait, :string
Notice what the generator did? It automatically knew that we wanted to add a new column and built out the
add_column method call. How did this happen? It turns out that the way that you name the migration file is very important. By prepending the
add_ text to the name it gave a signal to the migration generator that the purpose of this schema change will be to add a column(s) to the table. How did it know the table we wanted to add to? By appending the
_painters text to the end of the migration name it tells Rails that the table we want to change is the
painters table. Lastly, by adding the
portrait:string text at the end of the command tells the generator that the new column name will be
portrait and the data will be of type
To update the database schema you can run
rails db:migrate and the schema will reflect the change.
To remove the column you can run another migration:
rails g migration remove_portrait_from_painters portrait:string
If you open up this migration file, you will see the following code:
class RemovePortraitToPainters < ActiveRecord::Migration[6.0]
remove_column :painters, :portrait, :string
rails db:migrate our schema will be updated. This command is used every time when we need to run any pending migrations.
rails db:migrate:reset: This will drop the database information, runs migration on a fresh one and reloads the seed data.
rails db:seed: Loads the data from the file: db/seeds.rb into the database. It’s a very useful way of populating a database with the initial data needed for a Rails project.
rails db:rollback: rollback the last migration performed. This undoes the last migration, you can then edit the file, and run
rails db:migrate again. NOTE: Be VERY careful with this command in production, it’s destructive and you could potentially lose data. Make sure you absolutely understand what will happen when you run it
This is a generator type that gets used regularly. It does a great job of creating the core code needed to create a model and associated database table without adding a lot of bloat to the application. Usually, you should include the name of the Model (in singular and first letter capital), and the parameters of the model. Let’s add a new model to the app called
Painter with columns
genre, we can use the model generator with the following CLI command:
rails g model Painter name:string genre:string bio:text
If the data type is a string, you don’t need to specify their type following the column name as it is the default data type. So it would look like this:
rails g model Painter name genre bio:text
At a high level, this has created:
- A database migration that will add a table and add the columns
- A model file that will inherit from
ApplicationRecord(as of Rails 5)
And let’s create another model
Painting which belong_to
rails g model Painting name image painter:belongs_to
Remember to first generate the ones with
has_many macros on them; then only the ones with
belongs_to — this will be helpful when running migrations because otherwise you may get this error:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "<some table name>" does not exist
Running this generator will create the following files for us: a migration file and a model for
Painter and the
This particular generator creates a few different pieces of functionality with a single command, and it does it with minimal code bloat.
Then, go to your models to ensure that appropriate relationships (has_many, belongs_to) are set up.
Next, create a migration:
rails db:create and
rails db:migrate to migrate your tables.
You can test the connection in the console, just run
rails c and try to create a few instances, both correct and incorrect to test validations; then, test associations(e.g.
Painter.all.first.paintingwould check for the painting of the first painter)
Running this command
rails g controller will provide you with a controller file (for adding an appropriate action) and corresponding views folder.
rails g controller paintings
If you are building an API, using a front end MVC framework, or simply want to manually create your views, the
resource generator is a great option for creating the code. Let’s build Painting resource, Painting belongs_to Painter:
rails g resource Painting name image painter:belongs_to
We didn’t write the data type for
image so by default it will be a string. Adding
painter:belongs_to specifies the relationship between your two tables and sets up a column for
painter_id in our
paintings table. Or you could write the above command using
references(the result will be the same):
rails g resource Painting name image painter:references
This is just another example of writing the same command for a different model:
rails g resource Answer content correct_answer:boolean question:belongs_to
So what does our app have now due to the generator? Below is a summary:
- A migration file that will create a new database table for the attributes passed to it in the generator
- A model file that inherits from
ApplicationRecord(as of Rails 5; see Note above)
- A controller file that inherits from
- A view directory, but no view template files
- A view helper file
scssfile for the styles for the controller
- A full
resourcescall in the
resource generator is a smart generator that creates some of the core functionality needed for a full featured resource without much code bloat. Looking over the files I can't find one file that I need to remove, so that's a good sign.
The last item that was added may not look familiar to you.
resources :paintings is considered a 'magic' route that entails the full set of RESTful routes needed to perform CRUD in an application. So what does
resources :paintings translate into?
There’s an easy way to find out. Let’s run
rake routes with a filter so it only shows us the routes for paintings:
rake routes | grep painting
resources automatically creates each of these routes and makes them available to the controller. If you open up the
paintings_controller.rb file you may notice something interesting: none of the actions shown in the route list are even there! However, I actually like this because it creates the minimal amount of code possible and then lets me add only the features that the app needs.
Scaffolding is great for prototypes but I wouldn’t rely too heavily on it: http://stackoverflow.com/a/25140503
rails g scaffold User username:string
I hope this blog will help you to understand the magic of Rails, what MVC is and how to implement the commands. The right command can create all the useful files for you, set up routes or even set up some of your macros! For deeper understanding I included some resources below. I hope you will enjoy Rails. 🙂