Ruby-on-Rails
  Home arrow Ruby-on-Rails arrow Page 2 - Delving Deeper into the Active Record with...
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Moblin 
JMSL Numerical Library 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
RUBY-ON-RAILS

Delving Deeper into the Active Record with Ruby-on-Rails
By: A.P.Rajshekhar
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 2
    2006-11-28

    Table of Contents:
  • Delving Deeper into the Active Record with Ruby-on-Rails
  • Relationship Mapping
  • Acts As Mapping
  • Mapping and Rails in the Real World

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Delving Deeper into the Active Record with Ruby-on-Rails - Relationship Mapping


    (Page 2 of 4 )

    In real world applications, tables never exist in isolation. They are related at the database level using relationships based on the foreign key concept. One table can be related to another table through one-to-one, one-to-many or many-to-one relationships. Active Record bases its object-to-object relationship on how the corresponding tables are related at the database level. On the basis of types of database level relationships, there are three types of basic mapping in Active Record:

    • One-to-one Mapping
    • One-to-many Mapping
    • Many-to-many Mapping

    Each of these are mapped using two-way mapping. That means the classes on both sides of relationships know how they are related to the other class.

    In one-to-one mapping, a foreign key in one row of a table references at most a single row of another table. For example, let's take two tables - INVOICES and ORDERS. The following diagram shows the relation between the tables:

    To map tables with a one-to-one relationship, Active Record provides two declarations that have to be added to the corresponding classes. They are  belongs_to and has_one. The belongs_to declaration appears in the class/model for the table that contains the foreign key, whereas has_one is declared in the class which is on the other end i.e. the one whose primary key is acting as the foreign key. To map the classes according to the relationship between INVOICES and ORDERS, the addition to the classes would be:

    class Order < ActiveRecord::Base

    has_one :invoice

    . . .

    class Invoice < ActiveRecord::Base

    belongs_to :order

    Since for each Order there is at most one Invoice, the Order class contains the has_one declaration connecting it to the object of the Invoice class. Similarly, the Invoice class contains the belongs_to declaration to map it with the Order class, more specifically the object of Order class.  

    In a One-to-many relationship, a primary key in one row of a table references or is associated with an arbitrary number of rows in another table. For example, the relationship between ORDERS and LINE_ITEMS is that of one-to-many. The DDL of the tables will make it more clear:

    DDL for ORDERS

    create table orders (

    id int not null auto_increment,

    name varchar(100) not null,

    /* ... */

    primary key (id)

    );

    DDL for LINE_ITEMS

    create table line_items (

    id int not null auto_increment,

    order_id int not null,

    quantity int not null default 0,

    unit_price float(10,2) not null,

    constraint fk_items_order foreign key (order_id) references orders(id),

    primary key (id)

    );

             

    An order can be associated with any number of line-items. To map such a relationship, one must use the declarations has_many and belongs_to. The declaration has_many must be declared in the class representing the table at the "one" end of a one-to-many relationship, whereas belongs_to is declared in the class representing the table at the "many" end of the relationship. To illustrate further, below are the classes corresponding to the ORDERS and LINE_ITEMS tables with the mapping declaration embedded:

    class Order < ActiveRecord::Base

    has_many :line_items

    . . .

    class LineItem < ActiveRecord::Base

    belongs_to :order

    Using the has_many declaration, the Order class is associated with the line_items class and tells the framework that one instance/object of the Order class is associated with many instances of the Line_Items class. The belongs_to declaration works in the same way as it works in one-to-one relationship mapping.

    When many records of one table are associated with many records of another table, then the tables have a many-to-many relationship. To implement such a relationship, a link/join table needs to be used. The join table contains a foreign key for each of the tables its linking, so each row in the join table represents a linkage between the two tables. For example, PRODUCT and CATEGORIES have a many-to-many relationship. To implement the relationship, a link table has to be introduced: CATEGORIES_PRODUCT. It contains foreign key references to both tables. Here are the DDL of all three tables:

    DDL for PRODUCTS

    create table products (

    id int not null auto_increment,

    title varchar(100) not null,

    /* . . . */

    primary key (id)

    );

     

    DDL for CATEGORIES

     

    create table categories (

    id int not null auto_increment,

    name varchar(100) not null,

    /* ... */

    primary key (id)

    );

    DDL for CATEGORIES_PRODUCTS

    create table categories_products (

    product_id int not null,

    category_id int not null,

    constraint fk_cp_product foreign key (product_id) references products(id),

    constraint fk_cp_category foreign key (category_id) references categories(id)

    );

    The conventional way of mapping a many-to-many relationship would contain a declaration for the join/link table too. But that is not done with Active Record. Only the main tables are required to be mapped. It assumes that the join table is named after the two tables it joins (with the names in alphabetical order). To map the main tables, the classes corresponding to them must have the following declaration: has_and_belongs_to_many. This declaration links them both through the join/link table which is taken care by the Active Record.

     

    class Product < ActiveRecord::Base

    has_and_belongs_to_many :categories

    . . .

    class Category < ActiveRecord::Base

    has_and_belongs_to_many :products

     

    In the above example there is a mention of the link/join table. The reason is that once Active Record sees the declaration has_and_belongs_to_many in both  tables, it checks for the link table categories_products automatically. Thus "Convention-over-Configuration" works here too.

    More Ruby-on-Rails Articles
    More By A.P.Rajshekhar


       · In this discussion I have focussed on the advanced mapping techniques in Active...
       · I think the first sentence of the last paragraph should read asIn the above...
     

    RUBY-ON-RAILS ARTICLES

    - Iterating and Incrementing Strings in Ruby
    - Comparing and Manipulating Strings in Ruby
    - Strings in Ruby
    - Ruby On Rails: Making Your First Dynamic Site
    - Ruby on Rails: Beginning Rails
    - Ruby: Modules, Mixins, Fixins, and Rails
    - Controlling Information Access with the Rail...
    - URLs, Filters and the Rails Action Controller
    - Flash and the Rails Action Controller
    - Rails Action Controller
    - Dropping and Sorting with AJAX and script.ac...
    - Drag and Drop with script.aculo.us and Rails
    - Introducing script.aculo.us
    - Ruby Classes and Objects
    - Ruby Loops






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 1 hosted by Hostway
    Stay green...Green IT