MarkUs Blog

MarkUs Developers Blog About Their Project

Ruby on Rails Tutorial: Ch1-5 Summary

with 3 comments

The Ruby on Rails Tutorial: Learn Rails by Example book by Michael Hartl teaches Rails web application development by working through development of a sample microblog application. While going through the tutorial myself, I found it easy to get lost in the details of the sample application, rather than distilling and retaining key ideas needed to work on Markus. This post is a summary of those points extracted from the book, in order to act as a companion to the book.

Quicklinks within this post

Text beside each chapter number are key ideas from chapter, not the chapter’s actual title (which I find don’t tell much about what is taught in each chapter)

Chapter 1 Setup: Ruby, Ruby Gems, how to start rails server.
Chapter 2 Use Rails commands to quickly generate demo app. Also introduces MVC & Rail’s ApplicationController and ActiveRecord classes.
Chapter 3 HTTP Requests, HTTP Response codes, Layouts, Rspec
Chapter 4 Ruby Language Fundamentals
Chapter 5 Partials, Layout links, Rails Routes



Chapter 1: From Zero to Deploy


This chapter goes through development environment setup, it briefly discusses IDE, then moves on to Ruby, RubyGems, Rails and Git. The book suggests installing Ruby using the Ruby Version Manager (RVM), but personally I had trouble getting Markus to work until I abandoned RVM and set up Ruby following the Markus Development Environment Setup Guide.

Bundler & Gems

Bundler is used to install Ruby packages, including Rails, called gems. The Gemfile located at the application root lists the required Gems, and their versions. Gem version updates can cause “confusing breakage”, so explicit version numbers are recommended although not required. Be careful of installing multiple versions of gems, a Gemfile.lock exists in addition to the Gemfile. The Gemfile.lock automatically contains the last version numbers of gems installed that worked, which caused db:migrate and tests to fail on Markus even though the Gemfile contained the correct Gem version numbers. This was solved by un-installing all gems, and replacing Gemfile.lock with the version from markus-upstream. Running $ bundle install will then install required gems.

rails server

$ rails server or $ rails s will start a local web server visible on the local machine only, at http://localhost:3000 or http://0.0.0.0:3000.

MVC: Model View Controller (MVC)

Rails applications are structured using MVC, the app directory has 3 subdirectories, models, views and controllers. The model consists of “domain logic” (usually the data model, or data base), the controller receives requests from web browsers, which than interacts with the model before sending a view (HTML) back to the browser.

Version Control with Git & Github

See How to use git with MarkUs.

Deployment with Heroku

Markus doesn’t use Heroku.


Chapter 2: A Demo App


This chapter demonstrates rapidly creating a web application using rails commands. The chapter starts off by using $ rails new demo_app to generate an application skeleton. In the process, the chapter discusses two Rails library classes, ApplicationController and ActiveRecord::Base, how Rails uses the MVC pattern, the REST architecture and basic Rails routing.

Resources & MVC

Resources

A resource is both a data model and the web interface (resource objects can be created, read, updated and deleted) through the HTTP protocol. Rail’s scaffold command can be used to generate resources: $ rails generate scaffold User name:string email:string will generate a resource named User containing two attributes, name and email, both of type string. An attribute of “ID” is automatically generated by Rails as the primary key of the table in the database. When a change is made to the data model, the database must be migrated using rake ($ rake db:migrate). Rake is the Ruby make utility.

The scaffold generator not only makes the database table for the resource, but creates a number of pages for manipulating the resource. For example /users lists all users, /users/1/ shows the user with id=1, /users/new creates a new user and /user/1/edit edits user with id=1. (The messages are accomplished using the “flash” see sec 8.3.3).

MVC

When the user hits any those pages, the browser sends off a HTTP request, and the rails router dispatches the associated controller action for the URL. The code to create the mapping is done in routes.rb, and the actions are defined in the resource controller. There are more actions than pages because some actions don’t render pages (create, update, destroy). In this example the controller is UsersController, which inherits from ApplicationController (Class UsersController < ApplicationController). All controllers in Rails inherits from ApplicationController. This class confers the ability to manipulate model objects, filter inbound HTTP requests and render views as HTML.

The controller action then interacts with the model in some way, and the model responds with a list which is captured by the controller in a variable prefixed by the "@" symbol (an instance variable), which is passed to the view. The view uses Embedded Ruby to render the page as HTML, which is passed by the controller to the browser. The Rails ActiveRecord library defines methods such as .all that returns all records in that resource.

That application objects, or resources, can be acted upon by HTTP actions, or request methods, POST, GET, PUT and DELETE follows the REpresentational State Transfer (REST) development style. REST helps developers decide which controllers and actions to write.

Validations

Constraints are implemented in Rails using "validations", for example the length validation: validates :content, :length => { :maximum => 140 } within a class that inherits from ActiveRecord::Base renders an error message for any record with the content attribute longer than 140 characters.

Data model Associations

Data models in Rails can be associated to each other using has_many and belongs_to in model rb classes that inherit from ActiveRecord::Base. This will create a foreign key column in the model that belongs_to another model. ActiveRecord::Base gives ability to communicate with the database and to treat database columns as Ruby attributes.

Rails Console

The $ rails console is a useful too for interacting with Rails applications, that can be invoked from the command line at the application path.


Chapter 3: Mostly Static Pages

Chapter 3 introduces testing with Rails using Rspec, HTTP basic operations, HTTP response codes, the "Don't Repeat Yourself Principle", instance variables and embedded ruby.

Static Pages with Rails

Rails can render HTML files to send to the web browser, it displays any HTML files in the public directory directly. Rails actions are a powerful way to define URLS, they come bundled together inside controllers. Conversely, controllers are sets of actions related by a common purpose. rails generate is a script for making controllers, it takes the controller's name and an optional lit of actions. These can also be added later. Controller generation automatically updates routes file (config/routes.rb) Rails uses this file to find URL-page correspondence, ie. get "pages/home" maps the url /pages/home to the home action in the Pages controller. A controller is a class (defined by a "class" key word in a .rb file) that inherites from ApplicationController class (< denotes class inheritance):
class PagesController < ApplicationController def home end end

HTTP Requests (HTTP Verbs):

HTTP defines 4 basic operations between the client machine and the server. These are the same machine in dev. environments but different in general. The 4 operations are:

  1. GET - most common used for reading data ("get a page")
  2. POST - next most common, used to post a form, create objects in Rails
  3. PUT - update
  4. DELETE - destroy

The last two actions act on things on remote server, many browsers are unable to send these requests natively by Rails can.

The home action in Rails:
-inherites from ApplicationController.

HTTP Response Codes:

Cilent web browsers sends HTTP requests to server, and server respondes with code numbers indicating the HTTP status/response. For example, 200 for success and 301 for permanent redirect.

Instance Variables and Embededed Ruby:
The "Don't Repeat Yourself" (DRY) principle is to avoid code duplication.

Istance variables are prefixed by "@" symbols, eg. @title = "Home" is an istance variable assignment. Instance variables in Rails are used to link actions and views. Any instance varaibles defined in an action is also avaiable in a view.

Embedded Ruby (ERb) is the primary mechanism by which dynamic content is included into web pages, it is done by surrounding lines of Ruby within .html.erb pages with <%= ... %>. The <% %> indicates to Rails, as it is rendering the view to use ERb to render that section of code instead of presenting HTML directly; and the equals sign ensures that the results of evaluating the expression are inserted at that exact point.

Layouts:

Pages that are identical in structure benefit from extracting out common elements into a global layout, with body contents inserted on a per-page basis.
The /layouts/application.html.erb is such a global layout structural skeleton. The line <%= yield %> places the contents of each page into the layout. Such that visiting a certain page will convert that page into HTML, before insertion into application.html.erb at the point of the call to yield. The exact meaning of yeild is beyond the scope of the book, besides stating that it is yielding the contents to a block.

The <%= csrf_meta_tag %> is a Rails method that prevents cross-site request forgery (CSRF), a type of web attack. Use to keep application secure.

Testing

Test-Driven Development (TDD), writing tests before application code, is an increasingly common approach to development, which the book uses. The test framework used in the book is Rspec, a domain-specific language used for describing the behaviour of code to verify for the desired behaviour. The TDD way is to write tests that fail, write application code that that then cause the code to pass. Subsequent refactorings of the code will allow the use the same tests as regression tests.

If rails generate rspec:install was used then tests ("specs") would have been generated for each controller. The describe line is a description for human readers to know what te test is for. The "GET 'home' line actually submits a HTTP GET request to /pages/home/; it acts like the brwoser actually went and hit the page. The response.should be_success declares the desired HTTP response code. To run the test use rspec spec/ in the command line. Try rake db:migrate or bundle exec rspec spec/ or uninstalling and reinstalling the rspec gem if the test does not work.

The Spork section is optional.


Chapter 4: Rails-Flavored Ruby


Ruby language fundamentals are presented in this chapter, especially parts of the lanaguage that would be most helpful in building Rails applications.

Helper functions

Helper functions, defined in app/helpers/ are functions designed for use in views. They can be called in pages using ERb (<%= functionName %>), note the absence of an "@" symbol means that it is not an instance variable. Controllers have corresponding helper files (eg. app/helpers/pages_helper.rb); if helpers are sepcific to a controller then the helper should go in the controller's helper file.

Style Sheets

CSS is used to style web pages. The lines
<%= stylesheet_link_tag 'blueprint/screen', :media=>'screen' %>
<%= stylesheet_link_tag 'blueprint/print', :media=>'print %>

uses the built in Rails helper stylesheet_link_tag to include stylesheets. The first line includes a style sheet for the screen, and the second line includes one for printing.

Rails Console

$ rails console is a command line tool for interacting with Rails applications that is built onto of interactive Ruby (irb), has access to the full power of Ruby, and starts within a development environment. Use ctrl+C or ctrl+D to exit the rails console.

Comments

Comments starts with # symobl, extend for the line. Include 1 space after the #.

Strings

Several ways to declare/build:
" " - creates string literals, or literal strings
+ - concatenation operator (eg. "foo" + "bar")
#{} - string interpolation (eg. "#{first_name} Hartl", where first_name is a variable containing a name)
puts " " - prints a string, operates as a side effect. Returns nil and appends new line \n at end of line.
print " " - same as puts but does not append \n
' ' - also creates a string, but interpolation is not allowed on these strings, they are "more" literal than string literals in that \n does not need to be escaped (it's not converted into a line break).

Objects and Message Passing

Everything (even nil) is an object. Objects can take messages which are usually methods defined on the objects. For example, "foobar".length passes the message length, a method, to a string, which returns 6. Another method defined on strings is .empty? which returns a boolean. Booleans are useful for control flow and can be used with the logical operators && (and), || (or) and ! (not). The to_s method is defined on virtually all objects, and convert even nil to a string. Methods can be chained as such: nil.to_s.empty? which will return true.

For control flow, the "unless" keyword works the same way as if: eg. puts "The string '#{string}' is non-empty" unless string.empty?

Method Definitions

Methods are defined using def/end:
def methodName(arguementlist)
# code here
end

Methods have implicit return: it returns the last evaluated statement, but also has the option to use explicit return using the return keyword.

Arrays and Ranges

Arrays

Arrays are 0 offset by default. Square brackets are used for array access. Synonyms exist for commonly accessed array elements, array.first, array.second and array.list. Negative array indices access the array from the bottom up. Methods defined on arrays include .length, .sort, .reverse, .shuffle, << (push). .split(delimiter) splits a string into an array on the supplied delimiter, the default is white space. Meanwhile, .join(delimiter) converts an array to a string.

Ranges

Defines a range of integer or characters. (0..9).to_a returns a length 10 array filled with the numbers from 0 to 9. Use %w to make a string array. Ranges are useful for pulling out entire sections of array elements.

Blocks

Vertical bar symbols around a variable name, like |i| is Ruby syntax for a block variable; and curly braces {} such as {|i| puts 2 * i} indicates a single lined block while do..end indicate multi-line blocks.

Both arrays and ranges have methods that take blocks as arguments, it is up to these methods to know what to do with the block. For example, the .each method of a range takes a block with a single local variable and executes the block for each value in the range. Meanwhile, the map method returns the result of applying the given block to each element in the array or range.

Hashes and Symbols

Hashes are associative arrays (hash maps), and are unordered sets. Hash indices are keys, and can be either Strings or any object. Hashes are allocated with curly braces and key value pairs: {"key" => "value", "key2" => "value"}.

Symbols are variables prefixed by a colon, eg. :name. These are the same as string variables, however no methods are defined on them. They are commonly used as hash keys instead of strings. Hash values can be virtually any object, even other hashes (nested hashes). Nested hashes are heavily used by Rails, will see in section 8.2 of the tutorial.

Ruby Classes

Classes are instantiated to create objects, as in other object oriented languages. They are defined using the class keyword:


class Word
def palindrome?(string)
string == string.reverse
end
end

The .class method is defined on most objects, and returns the name of the class the object belongs to. Objects of a class can be created using the new constructor.


s = String.new("foo")
a = Array.new([1,2])
h = Hash.new(0)

Class inheritance is accomplished by the "<" operator in the class definition. Ruby allows built in classes to be modified, simply by redefining a class with the same name. This does not cause a namespace error, instead you are allowed to add methods to the class. For example, Rails adds the .blank? method to the string class, which works like the Ruby built in method .empty? except that .empty? returns false for strings of whitespace; while .blank? returns true. Classes can be declared in the rails console or in their own .rb files. In order to create getter and setter methods use attr_accessor, such that:
attr_accessor :name, :email
would create methods that allow @name and @email instance variables to be retrieved (get) and assigned (set).

The initialize method is called when the .new constructor is used, and takes a list of attributes that is by default an empty hash. Using keys, this list can be used to set instance variables. Initializing objects using a hash argument is common in Rails applications.

Controller Class

Controller actions are just methods. They don’t have to be instantiated by .new, this is done using “Rails magic”, because as mentioned before controllers inherit from ApplicationController and as such has all the functionality built into ApplicationController. Controller actions also don’t have return values, their purpose is to render web pages not to evaluate expressions.


Chapter 5: Filling in the Layout

This chapter goes through partials, named Rails routes and linking to named routes using the link_to function. It also talks about HTML/CSS, but they are not about Ruby on Rails in particular so are not covered in this summary.

Partials

Partials are a convenient Rails facility that are named by a leading underscore, such as _stylesheets.html.erb, and are parts of pages that con be inserted into a full page using render. For example, the partial app/views/layouts/_header.html.erb can be placed into application.html.erb using <%= render 'layouts/header %>. Partials can contain HTML and ERb themselves.

Layout Links

Links can be hardcoded as in normal HTML but the “Rails Way” is to use “named routes” instead, like <%= link_to "About", about_path %> instead of About. This has the benefit of allowing the URL of about_path be felixible, such that a change to that variable will cause it to change everywhere in the application.

Rails Routes

As noted in Section 3.1.2, Rails uses config/routes.rb for URL mappings. The line match '/about', :to=>'pages#about' matches the url '/about' and routes it ao an about action in the PageController. match automatically creates named routes for cotrollers and views, about_path (relative path) and about_url (absoulte url). Rails has special instructions for the root URL that does not use match: root :to => "welcome#index". These named routes can be used in the linked_to method, <%= link_to "Home", root_path %>.

Written by Christine

March 19th, 2012 at 12:59 am

Posted in Developer Essentials

Tagged with

3 Responses to 'Ruby on Rails Tutorial: Ch1-5 Summary'

Subscribe to comments with RSS or TrackBack to 'Ruby on Rails Tutorial: Ch1-5 Summary'.

  1. Very informative blog for basic learners of Ruby on Rails. It will be an added advantage if you put these notes using PDF format to download.

  2. Aw, this was an extremely good post. Taking the time
    and actual effort to generate a really good article… but what can I say… I procrastinate a lot and don’t manage to
    get nearly anything done.

  3. very good

    ???? ????

    17 Dec 14 at 7:22 am

Leave a Reply