Rails, MVC, and the Most Frequently Used Rails Commands

Katherine
The Startup
Published in
10 min readSep 29, 2020

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.

Model layer

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.

Controller layer

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.

View layer

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.

Run bundle install after adding all the necessary gems into the Gemfile.

Initialize the database: rails db:create

Start the Rails server: rails s. Use if you want to access your application through a web browser: http://localhost:3000

Rails Generate

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:

  • Migrations
  • Models
  • Controllers
  • Resources

Migration Generators

Migration

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]
def change
add_column :painters, :portrait, :string
end
end

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 string.

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]
def change
remove_column :painters, :portrait, :string
end
end

After running 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

Model Generators

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 name, bio, and 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 name, genre, and bio.
  • A model file that will inherit from ApplicationRecord (as of Rails 5)

And let’s create another model Painting which belong_to Painter:

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 thePainting.

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)

Controller Generators

Running this commandrails g controller will provide you with a controller file (for adding an appropriate action) and corresponding views folder.

rails g controller paintings

Resource Generators

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 name and 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 ApplicationController
  • A view directory, but no view template files
  • A view helper file
  • A Coffeescript file for specific JavaScripts for that controller
  • A scss file for the styles for the controller
  • A full resources call in the routes.rb file

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.

Routes

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.

Scaffold generator

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

Conclusion

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. 🙂

Sources:

📖 https://3rd-edition.railstutorial.org/book?fbclid=IwAR1fzija85b5ZoBuP1DNWeSH27tJHanivbn3pnMBleGtsfY2M1-cUWh18Qc

📖 https://api.rubyonrails.org/

📖 https://guides.rubyonrails.org/getting_started.html

📖 https://guides.rubyonrails.org/command_line.html

📖 https://api.rubyonrails.org/classes/Rails/Generators.html

📖 https://learn.co/tracks/web-development-immersive-2-0-module-two/rails/introduction-to-rails/rails-application-basics

📖 https://learn.co/tracks/web-development-immersive-2-0-module-two/rails/introduction-to-rails/rails-mvc

📹 https://www.youtube.com/watch?v=KKQ8lpEyw2g&ab_channel=Learn.co

--

--