Week 13: Ruby on Rails

This week we continue from our look at the Ruby language with an examination of the Ruby on Rails framework.

What is Ruby on Rails?

Ruby on Rails is a framework which allows easy development of web applications using the Ruby language. The key feature of Ruby on Rails is that a lot of the common web development tasks are "wrapped up" in the framework, so you can develop code which queries or modifies a database with very little effort.

The Model/View/Controller architecture

Ruby on Rails is based on a common software development architecture known as Model/View/Controller. Under Model/View/Controller, the application is broken down into three components:

  1. The model: the code which represents the actual application data. In Ruby on Rails, the model typically "wraps" a database, allowing the application to query the database using Ruby code rather than SQL queries. An example of model code might be a Hit class which represents a song on HitTastic!
  2. The view: how the data is presented to the user and gathered from the user. In a Ruby on Rails application, this is a web page with embedded sections of Ruby code within it, rather like a page consisting of a mixture of HTML and PHP in a PHP web application.
  3. The controller: the interface between the model and the view, which queries the model for data and presents it to the user in the view, or, alternatively, reads in user data from the view and uses it to modify the model.

Model-View-Controller

More on controllers

In Rails, a controller represents a particular entity or "thing" such as a song, a user or a person. Controllers contain a set of methods or actions which do certain things to that "thing", and each action maps to a URL. Therefore, the controller is the entry point to the application from the web browser. For example, for a controller called hits, representing a hit (song) in the HitTastic! database:

Controllers in Rails

Building some basic Rails applications

Rails is a bit different from most server side scripting techniques in that a lot of code is pre-generated for you. You can easily create a basic application to read and modify a database without writing a single line of code!

A simple Rails application

Here are some step by step instructions to generate a basic Rails application. The first example does not involve a database, but it will allow us to examine the structure of a Rails application.

A database driven Rails application - HitTastic! on Rails!

The example above was designed to get you used to the layout of the various files which make up a Rails application, in particular the controller and views. However a real Rails application is likely to talk to a database. The InstantRails environment we are using comes with a MySQL database.

Setting up a basic framework

Explanation of the code

To help you understand what's going on with Rails code, we'll go through one of the controller methods, namely the show method of the hit controller.

Writing our own controller method

If you play around with our pre-generated HitTastic! application, you'll find you can do quite a few things: you can add new hits, you can edit hits, you can delete hits and you can list all hits. However we might want to add one or two extra items of functionality. In the HitTastic! application we might wish to:

We are going to add two new controller methods to allow our users to do this, one for buying a song, and another for re-stocking a song. These will have URLs of this form:
http://localhost:3000/hits/buy/1
http://localhost:3000/hits/restock/1
Note once again the descriptive, REST-style URLs.

Carry out the following steps:

Error handling

OK, that works, but it would be nice to display an error message if the selected hit is out of stock. How do we do that? First return to the model and modify the buy method so that it looks like the following:

def buy
    if self.quantity > 0
        self.quantity = self.quantity - 1
        save
        return true
    else
        return false
    end
end
Note how the buy method of the Hit class is now returning true if the hit was bought successfully, or false if it is out of stock. We can take advantage of this in the controller, as we will do in a moment: we can react differently depending on the value that the buy method returns.
  • Return to the hits_controller.rb file. Modify the buy controller method as follows:
    def buy
        @hit = Hit.find(params[:id])
        if @hit.buy==true
            flash[:notice] = 'Hit successfully bought'
        else
            flash[:notice] = 'Out of stock'
        end
        redirect_to :action => 'list'
    end
    
    What we are doing here is calling the find method of the Hit class in the model, and testing if it returns true or false. If it returns true, we set up a flash message (see below) indicating that the hit was successfully bought. This will be displayed in the view, see below (remember that all displaying must be done in the view, not in the controller or the model). If not, we bring up a similar message indicating that it's out of stock.
  • We've done the model and the controller for our buy action. We don't actually need a specific 'buy' view, because buying a hit is an action which doesn't require an associated web page: it simply buys the hit by reducing the quantity by 1. However we do wish to display a message to the user to indicate whether the hit is bought successfully or not, so we need a view of some kind. Recall from above that we redirect to the 'list' action when the buy operation is done. So, logically our flash message should be displayed in the 'list' view. It turns out however that the 'list' view will automatically display any flash messages set up in the controller that called it.... which means that we're done!
  • Another action: restocking a hit

    The do_restock action

    We've created a restock action which is associated with a view allowing the user to enter an amount to increase the stock by. However now we need a do_restock action which actually restocks the hit, i.e. increases its quantity in the database. If you go back to the view for the restock action, note how the form posts to do_restock already, so all we need to do is write the code for the do_restock action.

    Summary of the architecture of a Rails application

    A Rails application contains: