Introduction To Rails
Now that you have finished learning Ruby and MVC, we have all the necessary knowledge to start coding in Rails.
Ruby on Rails is a popular framework started by DHH. Ruby on Rails stresses on the philosophy of convention over configurations. It's widely used by many companies such as Airbnb, Twitter and Github.
Rails is a perfect tool to create an API serving a web application or a mobile application. Developers have also created many Ruby libraries to assist Rails development. Some libraries are particularly designed for Rails.
To start a new project in Rails, it's amazingly easy.
$ rails new app_name
Here,
app_name
is a placeholder.
You will see that many files will be generated for you.
$ rails new app_name
create
create README.md
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/assets/config/manifest.js
create app/assets/javascripts/application.js
create app/assets/javascripts/cable.js
create app/assets/stylesheets/application.css
...
create vendor/assets/javascripts
create vendor/assets/javascripts/.keep
create vendor/assets/stylesheets
create vendor/assets/stylesheets/.keep
remove config/initializers/cors.rb
run bundle install
Fetching gem metadata from https://rubygems.org/
Fetching version metadata from https://rubygems.org/
Fetching dependency metadata from https://rubygems.org/
Resolving dependencies.....................
Installing rake 11.3.0
...
Using rails 5.0.0.1
Using sass-rails 5.0.6
Bundle complete! 15 Gemfile dependencies, 62 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
run bundle exec spring binstub --all
* bin/rake: spring inserted
* bin/rails: spring inserted
In GUI, you will see the following folder structure with files generated by Rails.
This is what rails new
does. It creates all the necessary files and folder structures in one command, so that you can start developing immediately. This is also the approach of convention over configurations, where all Rails projects will likely have the same folder structure.
There are many options for rails new
. To learn about proper usage, options, descriptions and examples, you can run $ rails new --help
Usage:
rails new APP_PATH [options]
Options:
-r, [--ruby=PATH] # Path to the Ruby binary of your choice
...
Some notable options are:
rails new -B
: Don't run bundle installrails new -T
: Skip test files
After you have created the project, make sure you have
cd
into the app's project folder. Check your current folder using$ pwd
and make sure you are inside theapp_name
folder.
So, we are actually now ready to turn on the server because Rails is this easy to begin. Just 1 line of command to kick start.
When you run the server on your computer while you are developing, we say that we are running in development environment.
To start the server, run $ rails server
or, in short, $ rails s
.
~/app_name $ rails s
=> Booting Puma
=> Rails 5.0.0.1 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.6.2 (ruby 2.3.1-p112), codename: Sleepy Sunday Serenity
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
Started GET "/" for ::1 at 2016-11-25 15:47:07 +0800
Processing by Rails::WelcomeController#index as HTML
Parameters: {"internal"=>true}
Rendering
...
Completed 200 OK in 34ms (Views: 15.3ms | ActiveRecord: 0.0ms)
Since the server is running inside the instance of your terminal tab, you will need to open another terminal tab if you want to run other commands.
Alternatively, if you want to shut down the server on the current tab, you can do that by doing ctrl + c in the Terminal to stop the Rails server.
So, if you see the above in your terminal, the server is already running. Reading through it, we know that we can try to access the website on http://localhost:3000, which is a local URL since your computer will be acting as both client and server.
Let's try accessing http://localhost:3000 on Chrome.
This is the welcome page by Rails. It was designed for you to see this welcome page after 1 line of command to make you feel happy. Software development can indeed be easy and fun.
Now, let's examine some of the files Rails has helped us generate and understand the pre-defined folder structure.
Gemfile
Gemfile is the place where all libraries and dependencies are defined for your applications. Libraries are codes that are written by other developers and free to use. We call them Open Source Software. We use libraries because we don't want to re-invent the wheel every time we build something. When our application depends on certain libraries to work, we call them dependencies. Most modern web applications rely on open-source libraries. To give you an example, Rails is an open-source library.
Why would someone work on software and open source it for free? Why do people make open source software?
The existing dependencies you see in Gemfile
are default ones set by Rails. We call a library written in Ruby a gem. Therefore, the name Gemfile means a file of gems (or a file of Ruby libraries).
In Gemfile
,
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.0', '>= 5.0.0.1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
...
group :development, :test do
...
end
group :development do
...
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
Gemfile can be used in all Ruby projects, so it's not unique to Rails. You can see gem 'rails', '~> 5.0.0', '>= 5.0.0.1'
where Rails is being specified as a requirement because it is essentially just a Ruby library.
The format to define a library dependency looks like this:
gem <library name>, <version>
So, what does the symbols in front of the version numbers mean?
>= 2.2.0
means greater or equal to version 2.2.0< 3.0
means under version 3.0~> 2.2
means>= 2.2.0
and< 2.3.0
Semantic versioning boils down to:
- PATCH 0.0.x level changes for implementation level detail changes, such as small bug fixes
- MINOR 0.x.0 level changes for any backwards compatible API changes, such as new functionality/features
- MAJOR x.0.0 level changes for backwards incompatible API changes, such as changes that will break existing users code if they update
Back to Gemfile
, we can see that sqlite3
, a relational database, will be used for database. And, puma
, a web server engine, will be used as the web server.
There are different environments. The environment on your local computer is called development
because it's used while you are developing. When you run automated tests, the environment is called the test
environment. When you deploy your app for the world to use and access anytime, that environment is called the production
environment.
Gemfile
enables you to specify different gems / libraries for different environments.
config
folder
Inside the config
folder,
Being self-explanatory, the config
folder is designed for configurations and settings for the Rails app. The folder is not meant to be frequently modified. However, there is one file inside this folder that is one of the most frequently edited file in Rails.
That file is routes.rb
, which is for defining routes, where each route should include the expected URL and controller/methods the router should pass onto.
Let's see the generated routes.rb
which currently has no route defined.
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
We can try to define a route for the homepage. The homepage would be located at the path /
. When a request is sent to get the homepage, the request will be passed onto the static_pages
controller and handled by the index
method. A homepage should be used for retrieving information, so we use the HTTP method GET
.
The whole thing will look like the following:
Rails.application.routes.draw do
# the format to define a route looks like the following:
# <METHOD> <PATH>, to: '<CONTROLLER>#<METHOD>'
get '/', to: 'static_pages#index'
end
Why do we use the name index
for this method?
All websites are a collection of files in folders. Loading a page is essentially picking out the file you want to display in the browser then loading it. Historically, the "index" page is a list of all the webpages. We now usually call the index page the homepage.
Alternatively, if you want to define a route for creating a Tweet, you can do
Rails.application.routes.draw do
post '/tweets', to: 'tweets#create'
end
Why "post" instead of "get"? Because the POST method is for creating data. The GET method is for retrieving data.
app
folder
The app
folder contains a majority of code for the MVC framework. This is where you define model, views and controllers, as you can see the folders named as models
, views
and controllers
.
Let's try to replace the default homepage with a page that says "Hello World".
Step 1:
Make sure you have defined the route in config/routes.rb
get '/', to: 'static_pages#index'
Step 2:
The controller static_pages
doesn't exist yet. So, we should create it. To create a controller, Rails has generously provided a command to do it (yet again)!
Run
$ rails generate controller static_pages
create app/controllers/static_pages_controller.rb
invoke erb
create app/views/static_pages
invoke test_unit
create test/controllers/static_pages_controller_test.rb
invoke helper
create app/helpers/static_pages_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/static_pages.coffee
invoke scss
create app/assets/stylesheets/static_pages.scss
The important file we care about here is app/controllers/static_pages_controller.rb
, which currently looks like
class StaticPagesController < ApplicationController
end
It's empty. So, we should define the method that matches the one we defined in the route, which is index
.
class StaticPagesController < ApplicationController
def index
end
end
Now, in the index
method, we don't need to process anything yet. We don't need to interact with the database. All we want is to render the homepage.
class StaticPagesController < ApplicationController
def index
# when a request comes to the route '/', it will be directed to this method
# this is empty for now since we have nothing to process for homepage
# so, we are going to respond with a webpage (defined in HTML)
render 'index'
end
end
The keyword render
in a controller method means to give back a response (similar to defining the output using return
for a function). render 'index'
will look for the template (the View in MVC) located at app/views/static_pages/index.html.erb
because Rails has this convention.
Remember, we often want to use templates when giving back a response, instead of making up on the fly, to minimize human errors.
The view file doesn't exist yet, so please create it. Inside the file, you can write "Hello World":
In app/views/static_pages/index.html.erb
,
Hello World!
Done, you have just defined the response, and everything should work.
- Start the server (if it hasn't yet)
- Go to localhost:3000
- The page should now say "Hello World!", instead of the default Rails homepage.