Ruby on Rails framework (RoR) is the dream of every developer. It does pretty much everything for you without much effort, and once you learn it and deeply understand it, you can build an entire website in a couple of hours (Of course, styling it is a different story). The hard part of rails is to understand the magic behind it.
For this article, I will assume that you have a strong foundation on Ruby (especially OOP), that you have rails installed on your machine (if you don't, just run:
gem install rails
on your terminal), and that you know what the MVC model is and how it works (This is a great reference to start if this is the first time you have heard of it or if you are not very familiar).
Since building a simple website using Ruby on Rails is so easy, it appears at the beginning almost like magic. You can just run on your terminal:
rails new blog
cd blog
rails g scaffold post title body:text
rails db:migrate
rails s
Now, go to localhost:3000/posts/new on your web browser.
With those five lines in your terminal, you will have a fully working web application that will allow you to Create, Read, Update, and Delete (C.R.U.D.) posts that have a title and a body. Without a single line of code! That is just how wonderful RoR is.
But how?! What just happened? How did RoR do that?! How can I have control over that? What is going on behind the scenes? Well, we will reveal all the secrets and answer all those questions right here and now.
When I started learning Ruby on Rails, I was following The Odin Project; the first project they ask you to build is a Blog app found on the Jumpstart website. It is a free and very well explained tutorial that guides you step by step, but what it fails to do is to clarify what is going on. We will be using it as a walkthrough during this article so that we can unveil the secrets of RoR, so let's get started!
The first thing that we will need to do is create our app, so go ahead and follow the tutorial, and I will meet you right after Creating the Article Model.
Ok, so what just happened? Well, you just created a migration that will create a MySQL table named Articles. If you have never heard about SQL, it is a relational database management system language. Wow, hold on! That sounds intimidating. You can read a little bit about SQL here, but don't dive in too deep, as far as you understand that a database is where we are going to store our users' information (including articles, posts, etc.) and that SQL is the language our app will use to communicate with it, you'll be fine for now.
There are many different SQL databases; we have PostgreSQL, MySQL, TSQL, and others. Rails default is SQLite, you can go to your root file directory and into Gemfile, and you should be able to see something like this right at the top:
source 'https://rubygems.org'git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.5'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.2'
# Use sqlite3 as the database for Active Recordgem 'sqlite3', '~> 1.4'
That last line is the gem that tells RoR which kind of database to use, and you can easily change it just by changing it to:
gem 'pg', '>= 0.18', '< 2.0'
To change it to a PostgreSQL database, but let's leave it as is for this article, I just wanted you to be aware that there are other options. RoR will create the database right in your machine; it will make the space, configure it, and leave it ready for you to add tables, add rows to tables, and create relationships amongst tables. Now move on through the Working with the database section, and I will meet you right after.
Ok, so let's dive a little bit deeper into what we just did. In our previous section, Creating the Article model we set up the foundation and prepared Rails to create a table in our local DB. In this section, we are making the migration to create that table.
We are specifying that we want to create a table called articles, with a column named title, and each value of that column is going to be a string and another column called body, which will have a text value. The difference between a string and a text is the number of chars that each one can handle. Text should be used when there are several lines and String when there are going to be only a few words or letters.
If you ever wish to add, delete, or change a column in your database, you can refer to this short article that describes the syntax or the official documentation for a much more detailed explanation.
We could have done all this in one step when we created the model using:
rails g model Article title body:text
We don't have to specify the string on title because it is the default value. Then we could have just run on the terminal:
rails db:migrate
To migrate our table to the database, but it was a good exercise to understand how to build a table and the syntax for how to specify the column names and type.
We have now finished creating our first table for our blog, the Article table. We can now add articles to the database manually (Since we don't have an interface yet to do that). To work with the database manually, we use the Rails Console.
It is an interface that will allow us to talk to the DB and the DB only! The most important instructions for using the console are:
Article.new
Creates a new Article, BUT IT DOESN'T SAVE IT TO THE DB.
Article.create( title: 'Sample Article Title', body: 'This is the text for my article, woo hoo!')
Creates a new Article, AND IT SAVES IT TO THE DB INSTANTLY.
You can also assign a new row of the DB table to a variable i.e.
a = Article.new
And you can then access the table columns:
a.title = 'Sample Article Title'
a.body = 'This is the text for my article, woo hoo!'
And then you can save that instance into the DB.
a.save
You can also read from your DB:
Article.all
Returns all the articles in your DB.
Article.first
Returns the article that was created first in the DB.
Article.last
Returns the most recently created article in the DB.
Article.find(1)
Should return the article with the id 1. The id is something we had not talked about here yet. Every element in the database has an identifier called by default NAME_OF_THE_TABLE_id in this case, article_id. This value is unique and is incremented by 1 for every new row saved in the database. You can access each specific row using this id, and it is what we will use to link elements from one table to another later on (For example, to know which articles belong to which user, we would add a column to articles called user_id which will contain the id of the user who wrote them. Since it is unique, it will never be unclear who wrote what).
Now that you know what the console is, what each instruction does, and what is in it, let's do the next two sections of the tutorial Working with a Model in the Console and Looking at the Model; and I will meet you right after.
Now, we are going to move to the Routs. You can think of the Routs as the boss in the MVC architecture; it is the one that will receive the instructions and send them to the correct place so that the user can get the request answered. If you ever need to change the way a request is interpreted or where it gets sent, you will have to talk to it. If you have forgotten our MVC model, here is a reminder:
For this section, we assume that you have a minimum knowledge of HTTP requests. If you do not, I strongly suggest you go through this tutorial first. The Home, Overview, Requests, and Methods sections are the most important ones to understand for now. A very brief summary of these parts that you should understand is that as our MVC model shows, a browser receives and sends "something" from/to other components. We call this the requests, and each request comes with a method. The two main methods are GET and POST.
GET is when the browser asks for something (For example, a sign_in form), and POST is when the browser sends something (For the same example, when it sends back the sign_in form filled out and the Controller has to do something with it). But hold on, How does RoR know where to send each request? I mean, I just said that once it has a sign_in form filled out, or a Post form filled out with a title and a body, how does it know what to do with it? Well, the routes are the ones that take care of this logic.
It can "read" the HTTP request that the browser sends and assign the correct Controller to work it with instructions included, just as a boss would send an order to get processed to the correct department.
The next section of the tutorial explains it better than I ever could, so let's move on, this is enough introduction for you to get a better grasp of the next section: Setting up the Router so go ahead and do that and I will meet you just before Creating the Articles Controller.
The Controller.
You can think of the Controller as the factory where the request is processed. Once the Routes receive the request from the browser, it reads it and assigns a Controller to process it. Then it will use the instructions from the Routes to go to the database to get the information it requested and process it to send it to the View.
As you saw in the previous section, the Routs read the HTTP address, and it knows which Controller to send the request. The Controller is where your magic will live; you will create the Database rows, save them, and apply any algorithm you need to them.
You will hear a lot about the CRUD actions; what CRUD stands for is:
And we are going to do that with almost anything we create on RoR. For the Articles we are working on, we are going to Create articles, allow users to Read articles (show the articles to them), Update (edit) them and Delete them. The Controller is the one that is going to be doing this for us. It is a Class, and we will create an instance of it on demand.
As with any class, it will have methods that can be public or private and instance variables. Now you are ready, go ahead and complete the Creating the Articles Controller and Defining the Index Action sections, and I will meet you just before Creating a Template.
The View is the end of our process, what we are going to render to our user, the articles the user asked for us to show, or to edit, or whatever the user asks us to do, ends with a view. Right now we are facing an error. Here is the MVC again:
We created the Model, we set up the DB and the Routs, we created our first action in the Controller, but we are missing the View, and that is what RoR is asking us for, it does not have a template. We are going to dive into some deep stuff, so get comfortable.
The browser is making a GET request (you can look at it on your address bar on your browser, http://localhost:3000/articles/ now, type on the terminal:
rails routes
Make sure you use a different terminal from the one that you are using to run your server. You will see that the /articles(.: format) is a GET request, it is read by the routes and sent to the appropriate Controller (Articles Controller), since that HTTP request specifically asks for a certain action (Again, go to your terminal, and you will see that the Controller#Action column is assigned for that HTTP request.
You can change this action if you want! That is beyond the scope of this tutorial and article, but keep in mind that you can, since it would be useful once you start dealing with sign_in, sign_out, and any action out of the CRUD ones. Can you guess where you would change that? If you guessed Routs you are correct! The Routs tell the Controller what action to perform, so you would have to change it there.), and then the Controller, by default looks for a view with the same name as the action it just performed.
Again, you can change this just by redirecting to the correct path you want it to go, but we will dive into that later. For now, I just wanted to make sure you were following the flow. Browser -> Request -> Routes -> Controller -> View. Before I set you free and let you complete sections 10 and 11, I want to introduce you to another concept you need to know and clearly understand. It is the params hash.
Params is a hash that transports information from the View to the Controller. Let me show you our MVC again:
You can see that View has a two-way street that connects to the Controller, but how do I send something from the view to the Controller? Well, that is the params hash! Go ahead and on what the params hash is and how it works. That is it; you are all set to complete the remaining of section 10 and section 11.
The next part is perhaps the most crucial part of any MVC project you aim to build, the associations. What an association is, is the way you will make the relations between 2 models. Remember that we just made a whole Articles MVC? Well, we are now going to add comments to it.
How are we going to be able to tell which comment belongs to which post? What if a post has many comments? Well, remember that we talked before about the id's and that we would use them to link two different models together? Well, now is the time. Before moving on to section 12, watch these videos:
Now, create a new account on lucidchart.com and try to make the ERD diagram of the Articles and Comments, where an article can have many comments, an author_name field, and a body field. What is going to be your primary key? What is going to be your foreign key?
What is the cardinality that you will have for the relationship? I built an ERD for this relationship for you in case you get stuck. Now that you have an idea of what it is that you want to build, let's move on to section 12 and create the MVC for Comments, and layout the associations. Please come back to this article before section 13.
Ok, so you have come a long way, congratulations! You have built a functional web app, and most importantly, you know how RoR is doing it! This next step is going to show us how to create advanced associations. So far you have built a one-to-many relationship where an article has many comments, but what happens when you have a many-to-many relationship?
Think about your Facebook friends.
You (the user) have many friends, but you are also a friend of many other users! A many-to-many relationship is precisely that. Think about how you would build it for a second (Don't spend too much time on it! It is a hard one to be your first approach to it). Go ahead and read this article.
Feel free to search for as much information about this as you need, this is one of the hardest-to-grasp and most important concepts about MVC, but don't get hung up on it since practice will be the best teacher. If you feel ready, go ahead and try to add this next association to your ERD diagram. We are going to create tags for our posts.
A post can have many tags and a tag could belong to many posts. A tag should have a name and should be related to articles through a Tagging helper table that should contain the ids of both, Articles and Tags tables. I will not provide you with a solution this time, but once you have an ERD that you feel comfortable with, go ahead and do section 13 of the tutorial. Once you finish, go back to your ERD and make the appropriate corrections if you feel you have some areas for improvement.
In conclusion, Rails is not pure magic; it just does a lot for us behind the scenes. The hardest parts to get the grasp of are the HTML requests since RoR uses some methods to communicate the browser with the Controller and it holds a lot of information (like params, cookies, session, etc.), the routes, and the associations.
I hope this article was helpful to you, and I hope you didn't try to do it all in 1 hour because some of these concepts require a lot from you to understand them and be able to apply them correctly.
You can always reach out to me through LinkedIn or Twitter if you get stuck somewhere, I will most likely have some more references to share with you to help you get through whatever difficulty you are facing, and I am always up to Zoom with any aspiring software developer who needs a hand.
See you on the other side! Happy coding!