In this article series, we will make, step by step, a fully functioning web application to learn Ruby on Rails. I always found it more helpful to make something "real" while learning something new. This series' goal is to do just that: help me (and you, if you end up reading it) learn Rails faster and better. So, now that we know why I'm trying this, here comes the question: what do we create?
I chose to make an online shop. This application will sell sneakers. I've almost created something along those lines in the past, in a different stack, but it ended up as a missed opportunity. This time, it's just for the sake of learning how to use Rails. Let's jump right into it!
Before we start writing some code, we need to make sure we have all the tools at our disposal. To get started, we will need three things: Ruby ( the language behind the Rails framework ), Rails ( well, obviously...) and git ( to deploy our application and keep track of our changes ).
If you know you already have those tools, you can skip this and go to the Setup section.
For windows users, you can visit the following link. Click the download button and chose the first link under WITH DEVKIT. Download, follow the steps and open a terminal window to check your ruby version:
>ruby -v ruby 2.5.3p105 (2018-10-18 revision 65156) [x64-mingw32]
On MacOS, depending on the one you have, you probably have Ruby installed already. Check in your terminal with
ruby -v. If that's not the case, install Homebrew and run
brew install ruby in your terminal. After that, run
ruby -v and you should see something resembling this:
>ruby -v ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
Now that we have Ruby, we need to get the Rails framework. In Ruby, we call a package a gem. To install a gem, you use the command gem install [packageName]. The gem command is provided by the package manager RubyGems. So, in our case, open a terminal window and run: gem install rails. Just like before with Ruby, you can check if Rails has been installed by checking its version:
rails -v Rails 5.2.1
Note: For the rest of the series, I will use this Rails version
Finally, we need to install git. Git is a popular version control system (VCS). A VCS makes it easy to collaborate with others, share and backup your code.
For Windows users, you can download Git from this page. Install and follow the steps with the defaults and all should be good. After that, run the command
git in your terminal and you should see something like this:
>git usage: git [--version] [--help] [-C <path>] [-c <name>=<value>] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] <command> [<args>] These are common Git commands used in various situations: start a working area (see also: git help tutorial) clone Clone a repository into a new directory init Create an empty Git repository or reinitialize an existing one work on the current change (see also: git help everyday) add Add file contents to the index mv Move or rename a file, a directory, or a symlink reset Reset current HEAD to the specified state rm Remove files from the working tree and from the index examine the history and state (see also: git help revisions) bisect Use binary search to find the commit that introduced a bug grep Print lines matching a pattern log Show commit logs show Show various types of objects status Show the working tree status grow, mark and tweak your common history branch List, create, or delete branches checkout Switch branches or restore working tree files commit Record changes to the repository diff Show changes between commits, commit and working tree, etc merge Join two or more development histories together rebase Reapply commits on top of another base tip tag Create, list, delete or verify a tag object signed with GPG collaborate (see also: git help workflows) fetch Download objects and refs from another repository pull Fetch from and integrate with another repository or a local branch push Update remote refs along with associated objects 'git help -a' and 'git help -g' list available subcommands and some concept guides. See 'git help <command>' or 'git help <concept>' to read about a specific subcommand or concept.
On MacOS, we can use Homebrew to install Git. We already installed it because we needed it to install Ruby. So, we can run
brew install git to install the VCS. You should see the same text above when you run
git in a terminal command.
Now that we have all the tools we need, we can start setting up our new application. In this section, we will create a new bare Rails application and quickly explore what we have to work with. To create a new Rails app, we use the
rails new myAppName command. So, move to a directory where you want to create your app and run
rails new sneakers_store. After creating a whole bunch of new files, you should see something like:
Bundle complete! 16 Gemfile dependencies, 77 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.
Now, you can move into the Rails application directory with
cd sneakers_store and open it in your favorite editor to take a peak!
As you can see, there are a LOT of files and folders there. We won't go into the details of each one right now, because it's not necessary. We'll tackle them when we will need them. But you already have a functional application ( that doesn't do much yet ;) ) Let see some of the files and folders we have:
gem 'rails', '~> 5.2.1'
This means that my app is allowed to use a Rails version superior to 5.2.1 but inferior to 5.3.0. Basically, it will only get minor patches for this gem. If you want an exact version, you can remove the ~>.
The config directory contains the application configuration. This is where you are going to find our router for example.
No surprises here, this is where our application's tests will be written.
Bundler is the tool that manages your application's gems. Earlier, I explained that the ~> syntax in your Gemfile is about what gem versions we allow in our app. Well, Bundler handles managing those dependencies to make sure our development environment is stable. Bundler will install the exact gem versions we need to make sure our application runs smoothly.
When you run rails new, the command
bundle install is run automatically. Each time you make changes to your Gemfile ( adding a new gem, changing a gem's version ), make sure to run
bundle install to take the changes into account.
For the sake of argument, let's just say that I want my rails version to be exactly 5.2.1. I don't wan't any minor patches updates. So, I'll replace the following line in my Gemfile:
gem 'rails', '~> 5.2.1'
gem 'rails', '5.2.1'
You remove the ~> and that indicates you wish an exact version for the gem. Another syntax you might encounter is the following:
gem 'rails', '>= 5.2.1'.
>= means: take the latest version of this gem, as long as this version is greater or equal than the version number provided. In our case, we ask bundle to get the latest rails gem version, as long as the gem version is greater or equal to 5.2.1.
bundle install. Bundle will install new gems and/or update gems if necessary. It's possible that you are asked to run
bundle update first. If that's the case, run
bundle update then
So, whenever we are making a change to our Gemfile, make sure to run
Because we ran
rails new, we already have a application we can run. We run a Rails application with
rails server. Something like this should appear in your terminal:
> rails server => Booting Puma => Rails 5.2.1 application starting in development => Run `rails server -h` for more startup options Puma starting in single mode... * Version 3.12.0 (ruby 2.5.1-p57), codename: Llamas in Pajamas * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://0.0.0.0:3000 Use Ctrl-C to stop
Great! Your application is running on port 3000 now. If you visit http://localhost:3000 in your browser, you will see:
Awesome, everything is ready for us to start coding. But before that, we'll go though a little more of high level theory to understand Rails better.
The Rails framework follows the model-view-controller architectural pattern. The model is responsible for the application's data and its logic. The model represents the the universe in which the application lives. It defines what the user informations are for example, or updates the database. The view is what you see on the browser. The view uses the model and display an interface. Finally, the controller acts as an intermediary between the view and the model. It handles the user's actions and changes the model and view's data.
When you load localhost:3000, a request is sent. That request is sent to the controller. Depending on the code written, the controller might immediately render a view, or interact with a model. After interacting with the model, which can fetch data from the database from example, the controller renders a view with the data gathered.
This calls for a very simplistic schematic representation:
As you can see, the controller sits in the middle of everything. If you look inside tour app/ folder, you have the distinctions between the three types of modules ( controllers/, models/, and views/ ). Let's create our first controller.
To follow the ancient traditions of our people, we have to create an application that say "Hello World!" at some point. Let's do just that. In our controllers folder, let's create a new file called firstcontroller_controller.rb. Let's put the following code inside:
class WelcomeController < ApplicationController protect_from_forgery with: :exception def greeting render html: "Hello World!" end end
Note: Controllers file names should end with _controllers.rb and classes end with Controller.
Don't worry to much about the syntax right now. We created a class called WelcomeController that inherits from the ApplicationController. Inside a controller, you can define actions. An action is a public method on the controller, and it is automatically accessible to the web server. Here, I just created an action called greeting. Because Ruby reads almost like English, you can guess what this action does: it renders some HTML: "Hello World!". But that is not enough yet to render our HTML string to a view. For that, we need to modify the router.
The router can be found in config/routes.rb. Open that up and replace the file's content with the following:
Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html root "welcome#greeting" end
We want to make sure the root route uses our new controller. If you follow the link above, you can see the documentation to configure the root route. The syntax is the following:
Our controller name is welcome and our action name is greeting. Save the file and refresh your browser:
Great! This is a good start. Now, let's deploy our application!
The first thing we need to do is to create our git repository. Navigate to the root of the sneakers_store directory and run
git init. You should see something like:
➜ sneakers_store git:(master) ✗ git init Reinitialized existing Git repository in /Users/Damien/Desktop/ruby/sneakers_store/.git/
git add . followed by
git commit -m 'first commit'. The first command will add all the current files to your repository and place them in a staging area. This is pretty much pending changes, the second command indicates the we are sure we want to keep the changes, so we commit them, with a message.
We are going to deploy our application with Heroku. This step is optional but I find it easier to deploy early and often.
Heroku uses the PostgresQL database. So, this means that we can't use the default sqlite3 we have at the moment. This means we need to change our Gemfile. Here is how it should look like:
Notice that we removed the sqlite3 gem from the first list to include it in the group :development, :test. The gem pg ( for PostgresQL ) is included in the :production group. Rails lets you specify which gems you need for the different environments. The first list being the gems that are always loaded in each environment.
Now, because we changed our Gemfile, we need to run Bundle again. But, this time, we will add a flag to prevent the installation of the production gems in our local environment:
bundle install --without production
This will not install the pg gem.
git add . . Then run
git commit -m 'Updated Gemfile for production'.
➜ sneakers_store git:(master) ✗ heroku --version heroku/7.0.52 darwin-x64 node-v10.1.0
heroku login and enter your credentials. Then, run
Now, we can create a place on Heroku for our application by running
➜ sneakers_store git:(master) ✗ heroku create Creating app... done, ⬢ aqueous-peak-82306 https://aqueous-peak-82306.herokuapp.com/ | https://git.heroku.com/aqueous-peak-82306.git
This is the subdomain just for your application. Of course, it will have a different name than mine.
To deploy on Heroku, run
git push heroku master. You'll see a bunch of stuff appear in your terminal. When it is done, you can go to your Heroku account dashboard and see your application's subdomain name. Click on it, then click Open app on the top right. And this is what you'll see:
Congratulations! You just deployed your first Rails application on Heroku and you learned how to make your first controller!