Ok, I am finally back from vacation.
This is the third post in a series that covers certain features of Issue Tracker sample app (view, source)Â that I added to the Flex RoR SDK.
The first post explained how to set up the application.
The second post covered how you can get WebORB for Rails to return typed objects to Flex using the [RemoteClass] metadata tag.
This post covers how to use ActiveRecord Associations with WebORB.
What is an ActiveRecord?
For those of you who are new to Rails, let’s start with a quick discussion of ActiveRecords and ActiveRecord Associations. The ActiveRecord class in Rails is an implementation of Martin Fowler’s Active Record design pattern. Martin defined an Active Record as:
An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
The Rails ActiveRecord class obviously does a lot more than this, but for this tutorial all you need to know is that an ActiveRecord is an object that wraps a table in a database.
What is an ActiveRecord Association?
So, what is an ActiveRecord Association? Well, as you can probably guess, it is association between ActiveRecord objects, or in other words it is an association between tables in a database.
Rails Conventions
To understand how ActiveRecord associations work we need to cover a couple of Rails conventions. As you might know, part of the power of Rails framework is that it favors convention over configuration. This means that if you adhere to Rails conventions it will take less code to get your apps up and running.
Here are two Rails conventions that are relevant to this discussion:
A tables primary key column should be named id.
Foreign keys should be named <class>_id.
For example, in the Issue ActiveRecord class in the Issue Tracker Sample App there is a attribute named project_id. This attribute contains the value in the id attribute for the project that the issue belongs to.

Types of Associations
There are several different types of relationships that you can create between tables using ActiveRecord Associations. They include:
has_one – one to one
has_many or belongs_to  - one to many
has_and_belongs_to_many – many to many
You can use ActiveRecord Associations to quickly create complex relationships. For example,
has_many :contributors, :through => :contributions, :uniq => true
This tutorial focuses on the has_many association.
Creating an Active Record Association
To see how to create a has_many association between to two ActiveRecord objects, open up the Project class. The class file is located in C:\rails\rails_issue_tracker2\app\models.
Inside the Project class file you will see the following:
class Project < ActiveRecord::Base
has_many :issues, :dependent => :delete_all
end
This tiny piece of code does a couple of things. The first half (has_many :issues) creates a has_many association between the Project ActiveRecord and the Issue ActiveRecord. The second half (:dependent => :delete_all) states that the issues associated with a project are dependent on that project and that they should be deleted if the project is deleted. In other words, if you a delete a given project, this piece of code tells Rails that all the issues associated with the project should be deleted also.
Now, to see how we can put this association to work, open up the ProjectService class. The ProjectService class file is located in C:\rails\rails_issue_tracker2\app\Services.
In the ProjectService class you will see the following method:
def getProjects(user_id)
projects = Project.find(:all, :include => [:issues],
:conditions => ['user_id = ?', user_id])
end
Pay special attention to this bit of code: :include => [:issues]. This argument tells the find method that for each project it finds, it should also go out and get all of the issues that are associated with that project. Rails knows how to do this because of the conventions that I discussed above. For each project that the find method returns, Rails inspects the value in the id column, then it goes out and finds all of the issues that have this value in the project_id column. Now each project will have an attribute named issues that contains an array of all the issues that are a part of that project.
So, now with this code in place, when you run the Issue Tracker Sample App and log in, the GetProjectsCommand gets executed on the Flex side of the app. This command calls the getProjects method in Rails. The getProjects methods finds all of the projects where the value in the user_id column equals the user_id for the current user. At the same time, the find method goes out and finds the issues for each project and packs them up into an array. WebORB wraps all of this up and returns the projects to Flex as ProjectVOs using the [RemoteClass] metadata tag.
By default, WebORB takes objects that are typed as arrays in Rails and sends them to Flex as arrays. So, the issue array that is part of each project ActiveRecord instance in Rails is sent to Flex as an array. This is fine for most purposes, but if you want to be able to do databinding then you need to use a collection of some sort (e.g., ArrayCollection, XMLCollection, etc). My simple solution to this problem was to write a setter function that takes the issues array and stores it in a ArrayCollection named issuesCollection. Now you can bind your components to the issueCollection and they will be automatically updated when the collection is updated.
package com.rxr.issuetracker.vo
{
import com.adobe.cairngorm.vo.IValueObject;
import mx.collections.ArrayCollection;
[Bindable]
[RemoteClass(alias="com.rxr.issuetracker.vo.Project")]
public class ProjectVO implements IValueObject
{
public var id : int;
public var user_id : int;
public var title : String;
public var issueCollection : ArrayCollection = new ArrayCollection();
public function set issues ( value : Array ) : void
{
issueCollection = new ArrayCollection(value);
}
}
}
ActiveRecord Association in Action
When you run the Issue Tracker Sample App and log in the Flex app runs the GetProjectsCommand, which calls the getProjects method in the ProjectsService (see above) in Rails. Now that there is a has_many association between the Project ActiveRecord and the Issue ActiveRecord, this single service call returns all of the projects for a given user, and all of the issues associated with each project. So now you can take the result of this single service call (see below) and cache it on the client, which will significantly reduce the number of calls that you have to make to server for the rest of the session.

As always, drop me a line if any of this is unclear or incorrect.