Ruby on Rails Beginner Adventures: Simple Blog Application

Coding Bootcamp Week 3: ALPHA Camp (Singapore)

Previous: Week 1 And Week 2
This week, we started learning Ruby on Rails!

Mission ahead: Learning Ruby on Rails (RoR).

I was initally unclear about the basic definitions so let define it here.

Ruby is a programming language whereas Rails is a gem, or a Ruby library. Specifically, Rails is a web framework that helps make web applications by providing classes for saving to the database, handling URLs and displaying HTML (along with a webserver, maintenance tasks, a debugging console and much more).

So, Ruby on Rails = using Ruby language on the Rails framework.

The Rails philosophy includes 2 guiding principles:

DRY: Don’t repeat yourself.
Convention over Configuration.

Setup for our first project from the terminal (already installed Ruby and other necessary tools like RVM):

  1. $ rvm gemset create project_name
  2. $ rvm gemset use project_name
  3. $ rvm gemset list
    #to check if project_name is the gemset being used
  4. $ gem install rails
  5. $ gem install bundler
  6. $ rails new project_name
  7. $ cd project_name
  8. Create .ruby-gemset
    #open file and use the name of the project as the name of the gemset
  9. Create .ruby-version
    #open file and specify the verison of Ruby to use and save
  10. $ bundle install
    #to install all the ruby gems required
  11. $ rails server
    #to get server up and running on http://localhost:3000.

This is the display on the browser if nothing goes wrong:

http://localhost:3000/

Rails Console. IRB is the interactive Ruby console. Rails has a special IRB console to access the web app as it is running (excellent for live debugging). It can be accessed from the terminal with the command $ rails console or $ rails c.

Class and table names are important. Rails has certain naming conventions. Rails has a pluralization engine to figure out what object maps to what table. Model class name is singular whereas database table names are plural.

Example 1
Model Class: Cat
Table name: cats

Example 2
Model Class: Person
Table Name: people

Also, for names with two words, the model naming uses CamelCase whereas the table name uses snake_case (all lowercase):

Example 3
Model class: ViewCounter
Table Name: view_counters

Understanding The Model-View-Controller Architecture

Rails function on the MVC pattern. The underlying concept: to separate the data, logic, and display layers of the program. This splits functionality cleanly.

MVC Web Architecture for Ruby on Rails

Current best practices include:

The week’s assignment would be to create a simple blog application.

Simple Blog Application (Manual method)

I will approach this by first drafting a story outline which covers all CRUD operations. Then, I will create the necessary based on the story flow.

In total, we need:

  1. 7 Routes
  2. 1 Controller with 7 actions defined
  3. 4 View templates (new, show, index, edit)
  4. 1 Model (Article) with associated migration and schema files

First, to configure the Rails router (config/routes.rb). Rails has aresources method which can be used to declare a standard REST resource:

resources :articles

resources :articles

We can enter $ rake routes in the Terminal to view the 7 routes generated:
#index, #create, #new, #edit, #show, update, #destroy

$ rake routes

Next, we need to generate the controller:
$rails generate controller Articles

app/controllers/articles_controller.rb

ArticlesController is a class that inherits from ApplicationController. CRUD (Create, Read, Update, Destroy) methods will then subsequently be defined to perform CRUD operations.

Create Views (in app/views/articles):

  1. new.html.erb
  2. show.html.erb
  3. index.html.erb
  4. edit.html.erb

To allow the user to key in an article entry, we need to add a form into the new.html.erb page. We can use a Rails helper method called form_for:

form added in app/views/articles/new.html.erb
Corresponding #new action.

Inside the block for the form_for method, the FormBuilder object - represented by f - is used to build three labels and three text fields, one each for the title, author and text of an article.

Finally, a call to submit on the f object will create a submit button for the form, which will send a POST request via the articles_path (specified at the top by indicating url:articles_path) and this is mapped to the create action.

When the form is submitted, the fields of the form are sent to Rails as parameters. These parameters can then be referenced inside the controller actions. For the createmethod above, Article.new creates an instance of the class Article which takes in article parameters. This instance is saved into an instance variable prefixed with @ . We do this because Rails will then be able to pass instance variables to the View.

In order to ensure that our form receives only parameters which we expect to receive (non-malicious content), we have to whitelist our controller parameters to prevent wrongful mass assignment. In this case, we use require (for the model) and permit (model attributes of :title, :author and :text) like so:

@article = Article.new(params.require(:article).permit(:title,:author,:text))

With that, Action Controller parameters are forbidden to be used in Active Model mass assignments until they have been whitelisted. This is a security practice to help prevent accidentally allowing users to update sensitive model attributes. In addition, with require, parameters flow through a predefined raise/rescue flow that will result in a 400 Bad Request being returned if not all required parameters are passed in.

Also, this whitelisting method is often factored out into its own private method so it can be reused by multiple actions in the same controller, for example create and update.

#create action

After a user clicks on the create/save button, the #create action leads to the article being saved into the database. Then, a GET request is sent to redirect to the show page (articles/:id) which shows the user the specific article he/she just entered.

This requires a model to be first created in order to save the article entry into the database:

$ rails generate model Article title:string author:string text:text

Models in Rails use a singular name, and their corresponding database tables use a plural name. With that command we told Rails that we want an Article model, together with a title attribute of type string, author attribute of type string and a text attribute of type text. Those attributes are automatically added to the articles table in the database and mapped to the Article model. A database migration file inside the db/migrate directory is also created (file is named according to date and time created):

Corresponding database migration file created with the specified Article attributes.

In the migration file, a method named change will be called when we run the migration. This will create the table with the table field we specified. The change method is reversible. Meaning if we migrated changes and would like to undo it, it is possible. The t.timestamps attributes is a Rails sensible default. It actually represent 2 attributes: updated_at and created_at.

Rails Migration is a set of database instructions that allows us to use Ruby language (rather than the database lanaguage SQL) to “migrate” the database from one state to another (e.g. create and modify database tables by adding new columns). Each migration is a new ‘version’ of the database.
In order to create the articles table columns in the database, we run this command:

$ rails db:migrate

The articles table is created.

Moving on, we now require the show action + show.html.erb andindex action +index.html.erb.

#show method.

Article.find finds the article of interest using params[:id] and is then assigned to an instance variable. Lets say for example, the article :id is 1 (URI pattern: articles/1). When we use it in the Views (show.html.erb), we reference to it using: <%=@article.title%> and this will display article 1’s title.

show.html.erb

Now, we will need a way to list all our articles. We do this by creating an index action and then creating an index.html.erb page.

articles#index action
index.html.erb page to show a list of all articles + a link_to ‘Show’ page at the end.

The <%= link_to <text>, <path_name> %> generates an anchor tag in the html.erb file.

Lets see how things look for now:
A user can enter the URL via articles/new to key in a new article:

new.html.erb shows form for user to input via GET request
Able to key in text_fields and save.

After hitting the ‘Save Article’ button, the user can view the article:

View: show.html.erb. URI: articles/:id

The user can then view a list of all articles via theindex.html.erbpage:

index.html.erb

So far so good. We have the #index, #create, #new, #show actions. Now to add #edit, #update and #destroy.

#edit and #update actions
edit.html.erb

The edit view will contain a form similar to the one we used when creating new articles. The difference lies in the routing URL and HTTP request method. The first parameter of form_for can be an object, say, @article which would cause the helper to fill in the form with the fields of the object. Passing in a symbol (:article) with the same name as the instance variable (@article) also automagically leads to the same behavior.

The new method, update, is used when you want to update a record that already exists.

Lastly, #destroy.

#destroy

We don’t need to add a view for this action since we’re redirecting to the index action.

“Destroy” will first show a confirmatory dialog before deleting.

We add a ‘Destroy’ link at the index page for each article. But we will uselink_to in a different way. The method:and data:options are used as HTML5 attributes so that when the link is clicked, Rails will first show a confirm dialog to the user, and then submit the link with method delete. This is done via the JavaScript file rails-ujs which is included in your application's layout (app/views/layouts/application.html.erb). Without this file, the confirmation dialog box won't appear.

Finally, we add relevant links to each page so to allow the User to navigate easily throughout.

Index page with links to “Show”, “Edit” and “Destroy”.

Final articles_controller.rb page:

articles_controller.rb with 7 actions defined.

And done!

Index page now:

Index page.

Edit page:

Edit page with existing previously typed information

Destroy confirmatory dialog:

Confirmatory dialog when user clicks on “Destroy”
Destroyed everything.

So that’s a wrap! A simple (ugly) but functional blog application with CRUD operations. Added a little bootstrap and it looks more presentable:

With a little Bootstrap styling

I tried the Scaffold method to create the simple blog application just to see what it does and here’s it:

Simple Blog Application (Scaffold method)

Our instructor pointed out that the Scaffold method creates a whole set of files, some of which we will not need and may not want. Also, as a beginner learning rails, I would want to learn the codes and build the app from scratch (above).

Nonetheless, here’s my experiment using the Scaffold method. A similar endpoint but a shortcut method. I created a new folder for this and decided to name it as Answers (because it seemed like a quick solution to the simple blog application haha).

Scaffold Method:
$ rails g scaffold Answer title:string author:string body:text

Terminal output:

$ rails g scaffold Answer title:string author:string body:text

This is done via the scaffold method. The entire scaffold available for Answer. This method created the Answer Model, answers controller, answers Views, answers Tests, answers Helpers, and answers Assets Files for javascript/coffescript and CSS. It also set up the answers routes, and database migrations.

db/migrate/20170831102439_create_answers.rb

Above is the Answers database migration file created with the fields I specified.

The next step would be to run the migration in the terminal:
$ rake db:migrate

$ rake db:migrate

This sets up the database for Answers. The database being used would be the default SQLite3 database for Rails. This database is not for major production applications, but it is suitable for testing and for the purpose of this simple blog application.

Next, we would need to set the root route to be the Answers index page. This is done in the config/routes.rb file. Add root “answers#index” under the resources :answers text in the config/routes.rb file to set the home page to the Answers index view. The view is found in views/answers/index.html.erb. (Pre-populated view by using the scaffold method).

In config/routes.rb: added root “answers#index”

We will next run the command: $ rails db:migrate

Run rails s in the terminal and go to localhost:3000 in the browser.

This is the view rendered in the browser:

Root page: http://localhost:3000/
Terminal output: GET request when viewing the answers index page.

Clicked on “New Answer” and a new page is rendered:

Terminal output: GET request when viewing the answers/new page.

Here, a GET request is made to render the new.html.erb page with a form for the user to enter posts. Subsequently, when “Create Answer” is clicked, it will trigger a POST request to record the data in the database and then a GET request to redirect the user to /answers/:id page.

POST request to record the data in the database followed by GET request to redirect to show page
/answers/:id page showing the specific post which was saved into the database.

Clicked on “Edit”:

GET request sent to render edit form.

This triggers a GET request from the broswer which is routed to the Answers controller and edit action. The edit.html.erb view is rendered with a form (with previous pre-populated post entry) to allow for editing.

Edit page and click “Update”:

http://localhost:3000/answers/1/edit
PATCH request sent and updated record in the database. Then redirected to /answers/1 via GET request

Back to Index page:

http://localhost:3000/ which is also http://localhost:3000/answers
When the “Destroy” button is clicked, a prompt is triggered.
DELETE request lead to deletion of record from the database.

$ rake routes

$ rake routes

Answers Controller action methods:

Answers Controller actions from scaffold method. Some json bits which i’m not familiar with at the moment.
Answers Controller actions from scaffold method (continued)
index.html.erb from scaffold method
new.html.erb from scaffold method
edit.html.erb from scaffold method
show.html.erb from scaffold method
_form.html.erb. Use of partials.

Legit! The scaffold method builds a simple blog application in 5 minutes. Keeping in view for future use.

That concludes the simple blog application assignment for the week and some of the basic Rails concepts covered. Much more to learn!

Software Developer at @thoughtworks | Marathon Runner | Ex-Pharmacist Writing on Coding, Technology and Running

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store