Every repository with this icon (
Every repository with this icon (
Working with RestfulX Models
Basic Operations
Displaying model instances in a List
<mx:List id="projectsList"
width="100%" height="100%"
dataProvider="{Rx.models.index(Project)}"/>
Creating a model instance
private function createProject():void {
var project:Project = new Project();
// set properties
project.name = nameTextInput.text;
project.notes = notesTextArea.text;
project.startDate = startDateDateField.selectedDate;
project.endDate = endDateDateField.selectedDate;
project.completed = completedCheckBox.selected;
project.user = User(userComboBox.selectedItem);
// create
project.create();
}
Updating a model instance
private function updateProject():void {
// set properties
_project.name = nameTextInput.text;
_project.notes = notesTextArea.text;
_project.startDate = startDateDateField.selectedDate;
_project.endDate = endDateDateField.selectedDate;
_project.completed = completedCheckBox.selected;
_project.user = User(userComboBox.selectedItem);
// update
_project.update();
}
Deleting a model instance
private function destroyProject():void {
_project.destroy();
}
Want a more feature complete example? Check out Pomodo On Rails
Example Configurations
| Configuration | Flex/AIR : Remote AR-like DS | AIR : SQLite | Flex/AIR : CouchDB | Flex : GAE |
|---|---|---|---|---|
| Primitive Attributes1 | + | + | + | + |
| Primary Relationships2 (BelongsTo, HasOne, HasMany) | + | + | + | + |
| Polymorphic Relationships3 | + | + | + | + |
| Tree-Like Structures/Self-Referential Relationships4 | + | + | + | + |
| Custom Key Relationships5 | + | + | + | + |
| Single Table Inheritance6 | + | + | + | + |
| Many-to-Many Relationships7 | + | + | + | + |
| Conditional Relationships8 (HasOne, HasMany, Many-to-Many) | + | + | + | + |
| Nested Relationships9 | + | – | – | + |
| Custom Methods10 | + | – | – | + |
| Model Path Prefixes11 | + | – | – | + |
| Nested Models12 | + | – | – | + |
Nested Relationships, Custom Methods, etc are not supported with SQLite because they are not relevant. They are specific to performance optimization when dealing with remote data sources.
If working with SQLite or CouchDB only you don’t need any servers running and by implication neither ActiveRecord, nor DataMapper, etc are necessary. RestfulX framework persists all of these configurations by itself. Only AS3 examples below are relevant when working with SQLite or CouchDB. If you are using CouchDB make sure to have your CouchDB database running of course.
Code Samples
1 Primitive Attributes
AS3
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="simple_properties")]
[Bindable]
public class SimpleProperty extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var amount:int;
public var price:Number;
public var quantity:Number;
public var available:Boolean;
public var deliveredOn:Date;
[DateTime]
public var soldOn:Date;
[DateTime]
public var createdAt:Date;
public function SimpleProperty() {
super(LABEL);
}
}
}
ActiveRecord Model
class SimpleProperty < ActiveRecord::Base
end
ActiveRecord Migration
class CreateSimpleProperties < ActiveRecord::Migration
def self.up
create_table :simple_properties do |t|
t.string :name
t.integer :amount
t.float :price
t.decimal :quantity
t.boolean :available
t.date :delivered_on
t.time :sold_on
t.timestamps
end
end
def self.down
drop_table :simple_properties
end
end
2 Primary Relationships (BelongsTo, HasOne, HasMany)
AS3
package restfulx.test.models {
import org.restfulx.models.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="projects")]
[Bindable]
public class Project extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[HasOne]
public var contractor:Contractor;
[HasMany]
public var tasks:ModelsCollection;
public function Project() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="contractors")]
[Bindable]
public class Contractor extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var address:String;
public var city:String;
[BelongsTo]
public var project:Project;
public function Contractor() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="tasks")]
[Bindable]
public class Task extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[BelongsTo]
public var project:Project;
public function Task() {
super(LABEL);
}
}
}
ActiveRecord Model
class Project < ActiveRecord::Base
has_one :contractor
has_many :tasks
end
class Contractor < ActiveRecord::Base
belongs_to :project
end
class Task < ActiveRecord::Base
belongs_to :project
end
ActiveRecord Migration
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :projects
end
end
class CreateContractors < ActiveRecord::Migration
def self.up
create_table :contractors do |t|
t.string :name
t.string :address
t.string :city
t.references :project
t.timestamps
end
end
def self.down
drop_table :contractors
end
end
class CreateTasks < ActiveRecord::Migration
def self.up
create_table :tasks do |t|
t.string :name
t.references :project
t.timestamps
end
end
def self.down
drop_table :tasks
end
end
3 Polymorphic Relationships
AS3
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="locations")]
[Bindable]
public class Location extends RxModel {
public static const LABEL:String = "lineOne";
public var lineOne:String;
public var lineTwo:String;
public var city:String;
[BelongsTo(polymorphic="true", dependsOn="Employee, Customer")]
public var owner:Object;
public function Location() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="employees")]
[Bindable]
public class Employee extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[HasOne]
public var location:Location;
public function Employee() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="customers")]
[Bindable]
public class Customer extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[HasOne]
public var location:Location;
public function Customer() {
super(LABEL);
}
}
}
ActiveRecord Model
class Location < ActiveRecord::Base
belongs_to :owner, :polymorphic => true
end
class Customer < ActiveRecord::Base
has_one :location, :as => :owner
end
class Employee < ActiveRecord::Base
has_one :location, :as => :owner
end
ActiveRecord Migration
class CreateLocations < ActiveRecord::Migration
def self.up
create_table :locations do |t|
t.string :line_one
t.string :line_two
t.string :city
t.references :owner, :polymorphic => true
t.timestamps
end
end
def self.down
drop_table :locations
end
end
class CreateEmployees < ActiveRecord::Migration
def self.up
create_table :employees do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :employees
end
end
class CreateCustomers < ActiveRecord::Migration
def self.up
create_table :customers do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :customers
end
end
4 Tree-Like Structures/Self-Referential Relationships
AS3
package restfulx.test.models {
import org.restfulx.models.RxTreeModel;
[Resource(name="categories")]
[Bindable]
public class Category extends RxTreeModel {
public static const LABEL:String = "name";
public var name:String;
[BelongsTo]
public var parent:Category;
public function Category() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="facebook_users")]
[Bindable]
public class FacebookUser extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[BelongsTo(referAs="friends")]
public var friend:FacebookUser;
[HasMany(type="FacebookUser")]
public var friends:ModelsCollection;
public function FacebookUser() {
super(LABEL);
}
}
}
ActiveRecord Model
class Category < ActiveRecord::Base
acts_as_tree
end
class FacebookUser < ActiveRecord::Base
belongs_to :friend, :class_name => 'FacebookUser'
has_many :friends, :class_name => 'FacebookUser'
end
ActiveRecord Migration
class CreateCategories < ActiveRecord::Migration
def self.up
create_table :categories do |t|
t.string :name
t.integer :parent_id
t.timestamps
end
end
def self.down
drop_table :categories
end
end
class CreateFacebookUsers < ActiveRecord::Migration
def self.up
create_table :facebook_users do |t|
t.string :name
t.integer :friend_id
t.timestamps
end
end
def self.down
drop_table :facebook_users
end
end
5 Custom Key Relationships
AS3
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="actors")]
[Bindable]
public class Actor extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[BelongsTo]
public var movie:Movie;
[BelongsTo]
public var actionMovie:Movie;
[BelongsTo]
public var documentary:Movie;
public function Actor() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="movies")]
[Bindable]
public class Movie extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[HasOne]
public var leadActor:Actor;
[HasMany]
public var actors:ModelsCollection;
public function Movie() {
super(LABEL);
}
}
}
ActiveRecord Model
class Actor < ActiveRecord::Base
belongs_to :movie
belongs_to :action_movie, :class_name => 'Movie'
belongs_to :documentary, :class_name => 'Movie'
end
class Movie < ActiveRecord::Base
has_one :lead_actor, :class_name => 'Actor', :order => 'name asc'
has_many :actors
end
ActiveRecord Migration
class CreateActors < ActiveRecord::Migration
def self.up
create_table :actors do |t|
t.string :name
t.references :movie
t.references :action_movie
t.references :documentary
t.timestamps
end
end
def self.down
drop_table :actors
end
end
class CreateMovies < ActiveRecord::Migration
def self.up
create_table :movies do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :movies
end
end
6 Single Table Inheritance
AS3
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="accounts")]
[Bindable]
public class Account extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public function Account() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="payable_accounts")]
[Bindable]
public class PayableAccount extends Account {
public static const LABEL:String = "name";
public function PayableAccount() {
super();
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="receivable_accounts")]
[Bindable]
public class ReceivableAccount extends Account {
public static const LABEL:String = "name";
public function ReceivableAccount() {
super();
}
}
}
ActiveRecord Model
class Account < ActiveRecord::Base
end
class PayableAccount < Account
end
class ReceivableAccount < Account
end
ActiveRecord Migration
class CreateAccounts < ActiveRecord::Migration
def self.up
create_table :accounts do |t|
t.string :name
t.string :type
t.timestamps
end
end
def self.down
drop_table :accounts
end
end
7 Many-to-Many Relationships
AS3
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="clients")]
[Bindable]
public class Client extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var city:String;
[HasMany]
public var billableWeeks:ModelsCollection;
[HasMany(through="billableWeeks")]
public var timesheets:ModelsCollection;
[HasMany(type="Timesheet", through="billableWeeks")]
public var incompleteTimesheets:ModelsCollection;
public function Client() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="timesheets")]
[Bindable]
public class Timesheet extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var total:Number;
[HasMany]
public var billableWeeks:ModelsCollection;
[HasMany(through="billableWeeks")]
public var clients:ModelsCollection;
public function Timesheet() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="billable_weeks")]
[Bindable]
public class BillableWeek extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var total:Number;
[BelongsTo]
public var client:Client;
[BelongsTo]
public var timesheet:Timesheet;
public function BillableWeek() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="authors")]
[Bindable]
public class Author extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[BelongsTo]
public var book:Book;
public function Author() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="books")]
[Bindable]
public class Book extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[BelongsTo]
public var store:Store;
[HasMany]
public var authors:ModelsCollection;
public function Book() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="stores")]
[Bindable]
public class Store extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[HasMany]
public var books:ModelsCollection;
[HasMany(through="books")]
public var authors:ModelsCollection;
[HasMany(type="Author", through="books")]
public var randomAuthors:ModelsCollection;
public function Store() {
super(LABEL);
}
}
}
ActiveRecord Model
class Client < ActiveRecord::Base
has_many :billable_weeks
has_many :timesheets, :through => :billable_weeks
has_many :incomplete_timesheets, :through => :billable_weeks, :source => :timesheet
end
class Timesheet < ActiveRecord::Base
has_many :billable_weeks
has_many :clients, :through => :billable_weeks
end
class BillableWeek < ActiveRecord::Base
belongs_to :client
belongs_to :timesheet
end
class Author < ActiveRecord::Base
belongs_to :book
end
class Book < ActiveRecord::Base
belongs_to :store
has_many :authors
end
class Store < ActiveRecord::Base
has_many :books
has_many :authors, :through => :books
end
ActiveRecord Migration
class CreateClients < ActiveRecord::Migration
def self.up
create_table :clients do |t|
t.string :name
t.string :city
t.timestamps
end
end
def self.down
drop_table :clients
end
end
class CreateTimesheets < ActiveRecord::Migration
def self.up
create_table :timesheets do |t|
t.string :name
t.decimal :total
t.timestamps
end
end
def self.down
drop_table :timesheets
end
end
class CreateBillableWeeks < ActiveRecord::Migration
def self.up
create_table :billable_weeks do |t|
t.string :name
t.decimal :total
t.references :client
t.references :timesheet
t.timestamps
end
end
def self.down
drop_table :billable_weeks
end
end
class CreateAuthors < ActiveRecord::Migration
def self.up
create_table :authors do |t|
t.string :name
t.references :book
t.timestamps
end
end
def self.down
drop_table :authors
end
end
class CreateBooks < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.string :name
t.references :store
t.timestamps
end
end
def self.down
drop_table :books
end
end
class CreateStores < ActiveRecord::Migration
def self.up
create_table :stores do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :stores
end
end
8 Conditional Relationships (HasOne, HasMany)
AS3
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="projects")]
[Bindable]
public class Project extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[HasOne]
public var contractor:Contractor;
[HasOne(conditions="name:2")]
public var randomContractor:Contractor;
[HasMany]
public var tasks:ModelsCollection;
public function Project() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="contractors")]
[Bindable]
public class Contractor extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var address:String;
public var city:String;
[BelongsTo(referAs="contractor, randomContractor")]
public var project:Project;
public function Contractor() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="clients")]
[Bindable]
public class Client extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var city:String;
[HasMany]
public var billableWeeks:ModelsCollection;
[HasMany(through="billableWeeks")]
public var timesheets:ModelsCollection;
[HasMany(type="Timesheet", through="billableWeeks")]
public var incompleteTimesheets:ModelsCollection;
[HasMany(type="Timesheet", through="billableWeeks", conditions="name:2")]
public var randomTimesheets:ModelsCollection;
public function Client() {
super(LABEL);
}
}
}
package restfulx.test.models {
import org.restfulx.collections.ModelsCollection;
import org.restfulx.models.RxModel;
[Resource(name="facebook_users")]
[Bindable]
public class FacebookUser extends RxModel {
public static const LABEL:String = "name";
public var name:String;
[BelongsTo(referAs="friends, randomFriends")]
public var friend:FacebookUser;
[HasMany(type="FacebookUser")]
public var friends:ModelsCollection;
[HasMany(type="FacebookUser", conditions="name:4")]
public var randomFriends:ModelsCollection;
public function FacebookUser() {
super(LABEL);
}
}
}
9 Nested Relationships
Serializing to FXML or JSON you can:
@projects.to_fxml(:include => [:contractor, :tasks])
@movie.to_fxml(:include => [:lead_actor, :actors])
@customer.to_fxml(:include => :location)
@store.to_fxml(:include => :authors)
10 Custom Methods
You can perform computations/delegate relevant logic to your server and then pass these methods as simple properties to Flex:
AS3
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Resource(name="simple_properties")]
[Bindable]
public class SimpleProperty extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public var amount:int;
public var price:Number;
public var quantity:Number;
public var available:Boolean;
public var deliveredOn:Date;
[DateTime]
public var soldOn:Date;
[DateTime]
public var createdAt:Date;
[Ignored]
public var randomComputedProperty:String
public function SimpleProperty() {
super(LABEL);
}
}
}
ActiveRecord Model
class SimpleProperty < ActiveRecord::Base
def random_computed_property
"foobar"
end
end
ActionController
@simple_properties.to_fxml(:methods => :random_computed_property)
Alternatively you can express that using default_methods helper.
ActiveRecord Model
class SimpleProperty < ActiveRecord::Base
default_methods :random_computed_property
def random_computed_property
"foobar"
end
end
Then in your ActionController, you can skip the methods array and call:
ActionController
@simple_properties.to_fxml
// or
@simple.properties.to_json
11 Model Path Prefixes
If you are working with a remote data service such as Rails, it is sometimes useful to prepend a string to the generated model URL. You can accomplish this using pathPrefix:
AS3
package restfulx.test.models {
import org.restfulx.models.RxModel;
[Bindable]
[Resource(name="articles", pathPrefix="admin")]
public class Article extends RxModel {
public static const LABEL:String = "name";
public var name:String;
public function Article() {
super(LABEL);
}
}
}
This will produce /admin/articles.fxml URL for POSTS and GETS and so on.
pathPrefix annotation is simply ignored in SQLite mode. You can safely leave it on if necessary for some other Service Providers, it just doesn’t have an effect with AIRServiceProvier.
12 Nested Models
Let’s say you want to index only a subset of models based on a model they belong to. If your service provider supports these kind of requests, you can pass a nestedBy array with instances of the models you want the requested nested by. nestedBy is supported on all REST/CRUD methods such as index, show, create, etc.
AS3
Rx.models.index(Task, {nestedBy: [currentProject]});
Where currentProject is a model instance of the project we are going to be differentiating by. This will produce the following URL /projects/123123123/tasks.fxml






