Home arrow Ruby-on-Rails arrow Page 3 - Delving Deeper into the Active Record with Ruby-on-Rails
RUBY-ON-RAILS

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


In addition to allowing on-the-fly schema mapping, the Active Record provides a variety of services helpful to complicated table situations. Keep reading to learn more.

Author Info:
By: A.P.Rajshekhar
Rating: 5 stars5 stars5 stars5 stars5 stars / 6
November 28, 2006
TABLE OF CONTENTS:
  1. · Delving Deeper into the Active Record with Ruby-on-Rails
  2. · Relationship Mapping
  3. · Acts As Mapping
  4. · Mapping and Rails in the Real World

print this article
SEARCH DEVARTICLES

Delving Deeper into the Active Record with Ruby-on-Rails - Acts As Mapping
(Page 3 of 4 )

The Relationship Mapping previously discussed provides mapping that is in one-to-one correspondence with the underlying database. In most cases, such a mapping is all that is required. However, this is simple in terms of variation in data structures. There are situations where data may be required to be presented in a different way. This is where Acts As Mapping plays a key role.

Acts As Mapping is built on top of a has_  relationship. Active Record provides two types of  Acts As Mapping: Acts As List and Acts As Tree. As the name suggests the former provides List data structure and the later provides Tree data structure.

Acts As List

In a has_ relationship, if acts_as_list is declared in a class representing a child (the many end of the one-to-many relationship), the class representing the parent can view the child like a list. In other words, it gives the child list-like behavior. It facilitates the parent to traverse the children around in a list as well as remove the children from the list.

To implement such a behavior, the child table needs a column called position. Here again convention takes precedence. If the column is named position, Active Record will automatically use it. Active Record uses this column to record the position of the child. An example will make the concept more clear. For brevity I will be using tables named PARENTS and CHILDREN. Here are the DDL:

 

create table parents (

id int not null auto_increment,

primary key (id)

);

create table children (

id int not null auto_increment,

parent_id int not null,

name varchar(20),

position int,

constraint fk_parent foreign key (parent_id) references parents(id),

primary key (id)

);

  

The following are the corresponding classes:

 

class Parent < ActiveRecord::Base

has_many :children, :order => :position

end

 

class Child < ActiveRecord::Base

belongs_to :parent

acts_as_list :scope => :parent_id

end

               

The Parent class has one extra argument to the has_many declaration:  :order. It ensures that the array is fetched from the database in the correct order. In the Child class, acts_as_list is declared and the scope is that of the parent_id or  in other words, ensures that the children are placed in the corresponding parent's list instead of a global list. Now let's set up some test data - three children named One, Two and Three for a parent as follows:

 

parent = Parent.new

%w{ One Two Three}.each do |name|

parent.children.create(:name => name)

end

parent.save

 

The following statements show how the children display behavior akin to that of a list:

 

#A simple method to let us examine the contents of the list.

 

def display_children(parent)

puts parent.children.map {|child| child.name }.join(", ")

end

 

display_children(parent) #=> One, Two, Three, Four

puts parent.children[0].first? #=> true

 

two = parent.children[1]

puts two.lower_item.name #=> Three

puts two.higher_item.name #=> One

 

parent.children[0].move_lower

parent.reload

display_children(parent) #=> Two, One, Three, Four

parent.children[2].move_to_top

parent.reload

display_children(parent) #=>

 

The various move operations update the position. The parent must know this change immediately, hence the reload operation is called after the move_lower or move_higher operation.

Acts As Tree

The other kind of data structure that is commonly used is Tree. There are scenarios where the rows of a table need to be represented in the form of a tree structure. For this Active Record provides the Acts As Tree mapping. To use this, the corresponding table needs to have one additional column -- parent_id  -- which is a foreign key reference back into the same table, linking child rows to their parent row. The pictorial representation would be as follows:

 

 

The best example of such a scenario is the previously discussed CATEGORIES table. Each category may have a sub-category and each sub-category may have its own sub-category. To make matters simple, let's create a CATEGORIES table having id, name and parent_id. So here is the DDL:

 

create table categories (

id int not null auto_increment,

name varchar(100) not null,

parent_id int,

constraint fk_category foreign key (parent_id) references categories(id),

primary key (id)

);

 

Next, in the corresponding class, the declaration acts_as_tree has to be declared.

 

class Category < ActiveRecord::Base

acts_as_tree :order => "name"

end

 

The parameter :order tells the framework that the children of a particular node must be displayed according to the value of the name column. The following statements set up the test data as one would populate a tree:

 

root = Category.create(:name => "Books")

fiction = root.children.create(:name => "Fiction")

non_fiction = root.children.create(:name => "Non Fiction")

non_fiction.children.create(:name => "Computers")

non_fiction.children.create(:name => "Science")

non_fiction.children.create(:name => "Art History")

fiction.children.create(:name => "Mystery")

fiction.children.create(:name => "Romance")

fiction.children.create(:name => "Science Fiction")

 

Now let's see how to access the data:

 

display_children(root) # Fiction, Non Fiction

sub_category = root.children.first

puts sub_category.children.size #=> 3

display_children(sub_category) #=> Mystery, Romance, Science Fiction

non_fiction = root.children.find(:first, :conditions => "name = 'Non Fiction'")

display_children(non_fiction) #=> Art History, Computers, Science

puts non_fiction.parent.name #=> Books

 

Here I have used the display function created previously. So creating a tree structure using application code cannot get any simpler than this.

That brings us to the end of this section. In the next section I will develop an application that utilizes the types of mapping just discussed.


blog comments powered by Disqus
RUBY-ON-RAILS ARTICLES

- Ruby-on-Rails Faces Second Security Flaw in ...
- Ruby 2.0 Prepped for February 2013 Release
- Why LinkedIn Switched from Ruby on Rails
- Adding Style with Action Pack
- Handling HTML in Templates with Action Pack
- Filters, Controllers and Helpers in Action P...
- Action Pack and Controller Filters
- Action Pack Categories and Events
- Logging Out, Events and Templates with Actio...
- Action Pack Sessions and Architecture
- More on Action Pack Partial Templates
- Action Pack Partial Templates
- Displaying Error Messages with the Action Pa...
- Action Pack Request Parameters
- Creating an Action Pack Registration Form

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2018 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials