Chapters 3 through 5 focus on a little bit of theory before we get to building the tutorial application.
Chapter 3 jumps into explaining MVC. It’s a pretty simple concept. MVC stands for Model, View, and Controller. The model is responsible for the state of the application, often the data you store in a database. It’s also more than data; it enforces the business rules that apply to your data. The model is both a gatekeeper and a data store. The view is responsible for generating some type of user interface. The view’s job is done once the data is displayed. Multiple possible views of the same data are a common case. The controller orechestrates the application. Controllers receive events from the outside world, interact with the model, and display the appropriate view. The book provides a simple diagram:
There’s a fine introductory article on Wikipedia if the concept is new to you. One of the main advantages is that each concept or action can be expressed in a single, well-known place. Like many modern web frameworks, Rails is designed with MVC in mind. Rails first sends your request to a router, which then maps it to a method of a controller (called an action), and then the action looks at data in the request to decide how to interact with the model and ultimately it prepares information for the view, which renders the result.
The request contains a path (/line_items?product_id=2
) and a method
(GET, POST, PUT, PATCH, DELETE). By default rails takes the first part of
the path, line_items
, as the controller name and the product_id
as the
ID of a product, which it passes to the create()
method of a
LineItemsController
if we assume this is a POST request. Different types
of request are routed to different methods of the controller.
Rails handles a lot of the low level details of an MVC app, so you can focus
on the core application logic. One example of this is in its ORM (object-
relational mapping) libraries which map database tables to classes. If you
have a class called Order
, you know it maps to a database table called
orders
. The Order
object has methods to set all the data fields in the
orders
table. The Rails classes also wrap our database tables with
class-level methods that perform table-level operations. For example, you
might want to look up an Order
by ID. Code to do so might look like:
order = Order.find(1)
puts "Customer #{order.customer_id}, amount=$#{order.amount}"
Or you could have a class level method that searches by a where clause and returns a collection of objects:
Order.where(name: 'dave'.each do |order|
puts order.amount
end
In addition to accessing field values, you can set values via the object and then save it to the database:
Order.where(name: 'dave').each do |order|
order.pay_type = "Purchase order"
order.save
end
So an ORM layer maps tables to classes, rows to objects, and columns to attributes of those objects. Class methods are used to perform table-level operations, and instance methods perform operations on individual rows. Active Record is the ORM layer provided by Rails. It relies on convention over configuration and starts with sensible defaults to minimize manual configuration by developers.
Action Pack is the part of Rails that supports the views and controllers. At its simplest, the view is a chunk of HTML code that displays some static content, but you normally want dynamic content generated by templates. Rails offers templates in three flavors:
The controller acts as the logical center of an application, coordinating interaction among the user, the views, and the model. It’s responsible for routing URLs to actions, it manages caching, it manages helper modules, and it also manages sessions. The way Rails handles most of the interaction behind-the scenes makes controller code easy to develop and maintain.
All of Chapter 4 is focused on a quick review of Ruby. I’ld recommend
a refresher at learnxiyminutes
if your Ruby is a little rusty or checkout the
zenspider quickref.
The one thing those don’t cover that is
relevant is YAML (YAML Ain’t Markup Language). YAML is used to define
configuration of things in Rails.
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
Indentation is import in YAML, and the above snippet defines four key-value pairs.
Chapter 5 focuses on the design of the application that is being built in the upcoming tutorial chapters. We’re going to build a basic bookstore, based upon the Pragmatic Bookshelf website. It approaches the problem from a mindset of incremental development and starts out from basic back-of-the-napkin style sketches of functionality. It points out that Ruby on Rails shines for this style of development, because it doesn’t heavily penalize changing your mind about something mid-development. It also points out that we’ll be building tests as we go. Yay!
To start with, we want an outline of how the application will work at a high level. We identify two roles: the buyer and the seller. The buyer browses for products, selects some to purchase, and creates an order. The seller uses the application to maintain a list of products to sell, to determine order awaiting shipment, and to mark orders shipped. Here is a first sketch of the buyer flow:
It’s a pretty traditional and simple flow. There’s also the seller flow:
In both cases, we’re not overspecifying things we are unsure about, like details of the shipping method or payment methods. We also need to think about what the data is going to look like:
There’s obviously some questions left, like what goes in cart, but this is enough to get started, and we can figure out the other details once we’re in a better position of knowledge later after we’ve started. With these diagrams in hand to get us started and an imaginary customer to show our progress, we’re ready to get started on the book’s tutorial application.