About this entry




Building a RESTful Ruby on Rails Application from the Ground up with a Site-wide Layout

In the following introductory article, I will build a stripped-down application to store a basic social graph for a person (a very fashionable subject nowadays). The steps to building the application will illustrate how to create a Rails application, configure it to connect to a MySQL database, generate resource scaffolding, use database migrations, and associate models. It will serve as a basis for later articles to illustrate more complex aspects of Rails development.

Liked it? !

Index

  1. Generating a Basic Application
  2. Creating and Configuring the Database
  3. Generating the Scaffold Resources
  4. Customizing the Database Migrations
  5. Associating the Models
  6. Setting up a Single Layout for all Controllers
  7. Making the Views User-friendly
  8. Optimizing the Application
  9. Testing the Application
  10. Related Articles
  11. Coming Soon

 

Generating a Basic Application

The first step is to generate the skeleton of the application. Run this command on your workspace folder:

rails social_graph

This will create folder called social_graph, and the whole rails structure of a new project under it.

Creating and Configuring the Database

Next, create the database that the application will use and the user that will access it. Assuming you are using mysql, you would run a sequence of commands similar to these:

mysql -u mysql-root-user -p
mysql> create database social_graph_development;
mysql> GRANT ALL PRIVILEGES ON social_graph_development.* TO 'rubyuser'@'localhost' IDENTIFIED BY 'rubypassword';

Configure the database and user set up above by updating the development section of social_graph/config/database.yml:

development:
  adapter: mysql
  database: social_graph_development
  username: rubyuser
  password: rubypassword
  host: localhost

Generating the Scaffold Resources

Now that we have laid the ground-work, we can start coding the actual application. The application will track two kinds of data: acquaintance and type of relation. For each of this, we will just generate their RESTful controllers to immediately have the basic code for creating, reading, updating, and deleting their records.

ruby script/generate scaffold_resource relation title:string description:text
ruby script/generate scaffold_resource acquaintance name:string relation_id:integer description:text

This will automatically create the views, models, controllers, and migrations to the two types of data. All of these will require some tweaking.

Customizing the Database Migrations

I prefer to work with the MyISAM engine database engine (since it supports fulltext searches) and I also want to make sure that the character encoding is set to utf8. So I will add an some options to create_table in social_graph\db\migrate\001_create_relations.rb. I will also pre-populate it with three values: friend, neutral person, and enemy. The self.up method will then look something like this:

def self.up
  create_table :relations, :options => 'ENGINE=MyISAM, CHARACTER SET=utf8 COLLATE=utf8_general_ci' do |t|
    t.column :title, :string
    t.column :description, :text
  end
end

I will also add these options to the create_table method for acquaintances in social_graph\db\migrate\002_create_acquaintances.rb. The create_table section will look something like this:

create_table :acquaintances, :options => 'ENGINE=MyISAM, CHARACTER SET=utf8 COLLATE=utf8_general_ci' do |t|
  t.column :name, :string
  t.column :relation_id, :integer
  t.column :description, :text
end

Now its time to create those tables by running the migrations:

rake db:migrate

Associating the Models

Now lets tweak the models by setting the relationship between acquaintances and relations. Since for each acquaintance we have to specify what kind of relationship it is, we included a relation_id in the table of acquaintances when creating the resource scaffold above. Using the association vocabulary, each acquaintance belongs to a relation (i.e. a person can belong to the category "friend") and each relation has many acquaintances (the category "friend" has many people it it). To reflect this association in the code, update social_graph\app\models\acquaintance.rb to

class Acquaintance < ActiveRecord::Base
  belongs_to :relation
end

and social_graph\app\models\relation.rb to

class Relation < ActiveRecord::Base
  has_many :acquaintances
end

Setting up a Single Layout for all Controllers

Now for the tweaking of the views. Each resource scaffold we created came with its own layout. We really don't need a layout per controller in this application. For all controllers to share the same layout will suffice. In order to do this, rename social_graph\app\views\layouts\acquaintances.rhtml to application.rhtml. Then substitute the title line:

<title>Acquaintances: <%= controller.action_name %></title>

to this more generic line:

<title><%= "#{controller.controller_name.capitalize}: #{controller.action_name}" %></title>

You can safely remove social_graph\app\views\layouts\relations.rhtml, leaving application.rhtml as the only file under the social_graph\app\views\layouts folder. All controllers from this point onward will use application.rhtml as their layout.

Making the Views User-friendly

When displaying the acquaintance info, it is pointless for the end-user if we display the relation id, as this means nothing to him. Instead we should display the title of the relation. Under social_graph\app\views\acquaintances\index.rhtml, change the line displaying the relation_id:

<td><%=h acquaintance.relation_id %></td>

to this:

<td><%=h acquaintance.relation.title %></td>

Do the same for social_graph\app\views\acquaintances\show.rhtml. Change the line displaying the relation_id:

<%=h @acquaintance.relation_id %>

to:

<%=h @acquaintance.relation.title %>

Finally for the edit, we should allow the user to choose the kind of relation he has to an acquaintance from a drop down list, rather than asking him to enter the relation_id. First we need to have all relations available from the edit view. In order to do this we need to get them from the acquaintance controller. Update the new and edit methods in social_graph\app\controllers\acquaintances_controller.rb to include the fetching of the relations:

# GET /acquaintances/new
def new
  @acquaintance = Acquaintance.new
  @relations = Relation.find(:all)
end

# GET /acquaintances/1;edit
def edit
  @acquaintance = Acquaintance.find(params[:id])
  @relations = Relation.find(:all)
end

Change the line in both the new and edit views (social_graph\app\views\acquaintances\new.rhtml and social_graph\app\views\acquaintances\edit.rhtml) from the text box asking for the relation_id:

<%= f.text_field :relation_id %>

to a dropdown list asking to select the relation from the list of titles:

<%= f.select('relation_id', @relations.collect {|r| [h(r.title), r.id] }, { :include_blank => false }) %> (<%= link_to 'New relation', new_relation_path, { :target => '_blank' } %>)

Optimizing the Application

Such a simple application does not really make use of sessions since we are not really tracking anything. To disable sessions, update the session line from social_graph\app\controllers\application.rb from

session :session_key => '_social_graph_session_id'

to

session :disabled => true

Testing the Application

We are all done with the first stage of creating a functioning application! Test it out by running the development server like this:

ruby script/server

and opening the browser to:

http://localhost:3000/acquaintances/new

Related Articles

This first article was the starting point for a series of articles describing more advanced topics. Later articles that have built on top of the social_graph application are:

  • Theme support. Suppose that your Ruby on Rails application is a generic one designed to be run customized to the look and feel of each of your client's taste. You can easily make it run in several places, each instance with its own customized stylesheets, javascripts, images, layouts, and views by adding theme support to it. In this article I will show you how.
  • Follow-up on theme_support and integration with rxml templates. This article gives a brief intro to rxml templates and proposes fixes to the theme_support plugin for better integration.
  • View Translation - Globalizing a Ruby on Rails Application by Adding Multilingual Support to the Views. Using the globalize plug-in for Ruby on Rails out-of-the-box makes it easy to add support for various languages. It can handle the management of translated terms and translation of views (displaying the messages on each page in the selected language). This article gives a brief introduction about to how to implement view translation with globalize in an actual application.

Coming Soon

  • Support for languages using complex scripts, such as Chinese, Tibetan, and Dzongkha. Globalize is great, but it falls short when the languages you want to support require specific fonts and font sizes or use Unicode ranges that may not be interpreted correctly by the browser. In this article I will show how to extend globalize to easily support these special cases.
  • User management. Here I will illustrate how to implement a full login support with roles and privileges. Depending on the type of user, he will be allowed to perform certain actions.

Stay tuned!

Liked it? !

Posted on October 27th | 4 comments | Filed Under: Ruby on Rails