Ruby on Rails

Flowchart of a Standard Rails Application

rails-flowchart

1 comment - What do you think?  Posted by A. Chatzopoulos - July 10, 2010 at 00:50

Categories: Ruby on Rails   Tags: , ,

Modelling a Database in Ruby on Rails: ActiveRecord and Migrations

All database-driven web applications have to have an approach to the issue of database interaction. A common approach in larger applications, powered by relational databases, is to make use of a framework which adds a corresponding abstraction layer to the existing database tables. In other words, they work by creating a model of the database for the rest of the application to use. This is usually referred to as Object Relational Modelling (ORM), a method which Wikipedia defines as “a programming technique for converting data between incompatible type systems in relational databases and object-oriented programming languages”, the purpose of which to create a “virtual object database” which can be used from inside the application.

Different languages and platforms uses different ORMs. For example, in the world of Java, Hibernate is a common ORM library while ADO.NET and LINQ to SQL is common solutions while developing in .NET. For the same purpose, Ruby on Rails uses ActiveRecord which is an integral part of this framework. It is an implementation of the device: “An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data”.

Rails uses model objects to represent tables in the database. The work of ActiveRecord is to place wrappers around each table together with business logic for accessing the data. This approach works in conjunction with so-called migrations, short programs that lets you modify the database schema incrementally.

The workflow to accomplish this looks as follows:

To introduce a new object class in the system, one starts with issuing:

script/generate model product

Essentially, this does two things:

  1. Creates a model class in /app/models. This is a ruby class which will be used by the system at runtime for creating the appropriate objects.
  2. Creates a new migration (a program snippet located in /db/migrate). Essentially, this is a script for subsequent modification of the underlying database. Each script/generate-command creates a new migration (with a timestamp for incremental purposes).

A few words about Rails conventions that are used in this context:

  • Model names are capitalized and CamelCased.
  • Names of database tables are pluralized (thus, the naming of the model to Product renders the corresponding database name Products).
  • Underscores (_) are used to separate words.
  • Name of foreign keys columns are composed of the singular form of the name of the foreign table followed by “_id”. Thus, if a company has many products, each product will have a foreign key by the name of “company_id” representing the id of the corresponding company.

The generated migrations contains no column definitions to start with. The desired columns can be added to the migration program in preparation of the creation of database table. Like so:

class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.column :name, :string
      t.column :price, :integer
      t.column :company_id, :integer
      t.timestamps
    end
  end
  def self.down
    drop_table :events
  end
end

Now, the actual migration can be utilized by issuing the command:

rake db:migrate

This will modify the database according to the above migration script. Now, if one prefer a rollback to the earlier state of the database, this can be accomplished with the command:

rake db:rollback

These two steps, model generation and migration, now lands us with a system with an adequate database (assuming you have specified the necessary columns in the migration script) and corresponding object representation of the tables in the database. In effect, we have created ourself an ORM.

Relationships

To complete the model of the database, we have to define the relationships between objects (if any). As we saw, this is specified in the database (in the usual way with foreign key-connections). However, Rails cannot alway determine object relations by itself, based on these database connection. Therefore, we have to tell the system how the objects are related. This is easy done in the model files (app/models):

company.rb

class Company < ActiveRecord::Base
  has_many :products
end

products.rb

class Product < ActiveRecord::Base
  belongs_to :company
end
That is all there is to it! We now have a fully functional model that reflects the relational structure of the database like so:
relations.png

Be the first to comment - What do you think?  Posted by A. Chatzopoulos - July 8, 2010 at 23:42

Categories: Ruby on Rails   Tags: , , ,

Ruby on Rails: Getting a basic site up and running

It’s been a while since I last built a site in Ruby on Rails, being that .net-development has taken up all of my time of lately. However, in the planning of this new project of mine, I have decided to take a fresh look on Rails and compare it to my recent endavours with .net-development.

Just as I remembered it, starting up of a new Rails project is a breeze: just navigate to the designated project directory and issue rails project_name and instantly you will have a new directory with the Rails standard directory structure created for you. I really do like this standardized way of doing things, it saves you all trouble of figuring out a suitable directory structure for yourself and let you focus on the actual development of the application at hand.

The next step is to import this file structure to my favourite editor, TextMate. This is done by creating a new project in TextMate and importing (drag-and-drop) the newly created files. This may be a minimalistic IDE compared to Visual Studio, but I just love the simplicity of it. With this workpace up and running, it is time to take a look at the directory structure and which files that are supposed to go where:

As I remember, the heart of a rails project is the app-folder. This folder contains the appropiate subdirectories of models, views and controllers, reflecting the inherent MVC structure of Rails applications. This, I must say, is a pure joy to witness after spending months in a .net-environment with cluttered entanglement of visual code and application logic. Sure enough, you have the .net MVC framework which looks very promising, but the  standard .net-way of doing things is most lacking in this regard. Rails, on the other hand, is designed from the ground up to separate business logic from presentation logic.

Now, the rails commando issued previously has already generated a fully functional website for us. To start it up, all we have to do is to make use of the command script/server which fires up a local web server for site testing. A visit to localhost:3000 now presents us with this welcoming view:

welcome.png

Apparently, we now have a fully functional web application up and running, and all this with minimal effort.

Now, the next step is to connect it to a database of some sort. For this purpose I am using a previously configured MySQL-database. In each Rails application, database connection details are to be found in the file config/database.yml. In my newly created project, this database file looks like so:

development:
  adapter: mysql
  database: pp_development
  username: root
  password: xxxxx
  pool: 5
  timeout: 5000

test:
  adapter: mysql
  database: pp_test
  username: root
  password: xxxxx
  pool: 5
  timeout: 5000

production:
  adapter: mysql
  database: pp_production
  username: root
  password: xxxxx
  pool: 5
  timeout: 5000

For the project, I have created three different databases: One for development, one for testing and one for production. This is the Rails standard way of doing things and is a highly recommended approach. Next, I will go into more detail about Rails modelling of this configured database with the power of Rails migration-feature.

 

 

 

 

 

Be the first to comment - What do you think?  Posted by A. Chatzopoulos - at 19:53

Categories: Ruby on Rails   Tags: , ,