I love my morning espresso and biscotti! Strada is a Godsend.
This is going to be my first complete tutorial for the Social Computing world on how to use the most cutting edge open source Enterprise Web 2.0 Application Framework ever, Ruboss. Check it out! With a community of active Ruboss contributors, we will, in very short order, take the internet by storm. Building websites like Facebook or Youtube or Digg with an interactive Flash and/or Flex interface will be so insanely simple (Heroku for the backend server scaling) that any one individual could support such a data-driven madhouse. Add to this all of the functionalities of web services available (google maps, amazon, salesforce …), and we have an information revolution.
But in order to get to this point, some key principles must be well understood. These are found within DESIGN PATTERNS, and the principles of REST. With the publication of Design Patterns - Elements of Reusable Object-Oriented Software Fall of 1994, the Gang of Four ushered in a new age of building scalable, reusable, and extremely well-defined software components. J2EE, the Java 2 Enterprise Edition, then implemented and expanded on these core Design Patterns into the famous MVC (Model View Controller) application framework. However, they and no software other group or company has, for one reason or another, been able to unite together and implement a powerful AND well excepted Web Application Framework for building amazing, highly structured, and repeatable software components based on design patterns.
Enter Flex, Cairngorm, and Ruby on Rails.
2004 was a BIG year… Flex packages Actionscript into an XML document, Cairngorm packages Flex XML Documents into an Enterprise application that can efficiently talk to a backend database, and Ruby on Rails comes out and revolutionizes the way people around the globe build software and web applications. Everyone is super excited.
Flex takes Actionscript, the most widely adopted and interactive-friendly programming language to hit the internet and turns it into basically an XML document, so what took 10 lines of code in Actionscript now takes only 1 line in Flex XML (MXML for Macromedia XML). Actionscript and Flash by themselves took over the interactive market. At around the same time, a few Adobe consultants recognized the limitations faced by J2EE developers when building Rich Internet Applications and released Cairngorm for Flex, an Enterprise level
Warning: gzuncompress() [function.gzuncompress]: data error in /home/.zwingli/lancorn411/systemsofseven.com/blog/wp-content/plugins/easyswf.php on line 255
.
David Heinemeier Hansson, creator of Rails, saw the inefficiencies and repetitives tasks required to build web applications and used cutting edge design patterns to automate almost all of these commonalities using the dynamic programming language Ruby.
Now, in 2008, Peter Armstrong and Dima Berastau have integrated Flex and Ruby on Rails into the most powerful, highly efficient, and scalable Rich Web Application Framework, Ruboss. This is it! What all of these frameworks have in common is very well thought out design patterns that allow us to think about building software on the web like scientists, something that most other programming languages are leaving out of the picture and which is hurting them tremendously.
Design Patterns and the Evolution of the Universe
Design Patterns are the best things to have hit the software world in my opinion. They tie software development perfectly into the evolutionary process of the universe. Once they are set into place, you no longer have to think about the implementation details because they follow consistent patterns. This is the basis of evolution: as complexity arises, patterns emerge from these complexities and ultimately become new entities themselves. And as these entities grow in number, they create a new complex system out of which new patterns arise, on and on and on into the infinite…
Energy condenses into atoms; atoms condense into molecules; molecules into cells; cells into organisms; organisms into intelligent organisms. Thoughts become encapsulated into words, which are strung together into sentences and stories, and sent as signals to other human beings for them to unpack and understand and integrate into their own being. Ken Wilber, a prominent philosopher today, has come up with a universal theory of how all things in the universe are modeled, as holons, or whole-parts, and this can be seen in design patterns. With patterns implement at all levels, we can focus on the highest level, which is, ultimately, our own experience in the world–our ideas and our communication of those ideas to other people.
We are now at the point of implementing these evolutionary design patterns into the web to create a foundation of richly interactive and database driven content, freely accessible and modifiable by the social computers, us. I recommend these books and people, in no particular order, to get going on understanding design patterns and their implementation for the evolution of the social web:
- Martin Fowler
- Head First Design Patterns
- Gang of Four
- Actionscript Design Patterns
- Paul Williams
- Ken Wilber (holons)
- RESTful Web Services
And the second important principle is REST, Representational State Transfer. If there is one things that needlessly increases the complexity of a software application, its creating un-RESTful methods when they can be RESTful. In short, all actions between a User Interface and a Database can be mapped onto four simple HTTP methods: GET, POST, UPDATE, and DELETE. These four methods comprise the Universal Interface. Before this design pattern was discovered/revealed, it was often difficult to tell how to do certain things to data in a database. But recognizing that you only need to do these four things, ALL of the thinking is done for you, AND we now have a template by which all Flex UIComponents access a database. Now if you want to make a blog post component for instance, know that it only needs to implement those four methods; same for most everything else.
In order to hasten the evolution of the social interactive web, I recommend getting to know these books well, along with the ones above, as they are the basis of everything in this tutorial:
——- THE RUBOSS TUTORIAL: ——-
Ruboss currently consists of a Flex front end and a Ruby on Rails back end. Ruby on Rails then uses ActiveRecord (Martin Fowler’s design pattern) to access the database, abstracting away all the complicated SQL. I have also modified the Ruboss plugin to include the ability to load files to/from the server from Flex and to create authenticated users. Download it for the tutorial.
To get you started using Ruboss, make sure you have installed Ruby, Rails, Mongrel, Flex 3 (or the Flex 3 SDK), and MySQL. Then download the plugin-enhanced Ruboss. We will first create a single Flex UIComponent, a blog “Post”, and see how everything is wired together. Then we will add to it to create the beginnings of a Flexible Blog, which, in short order, can surely be made into an open source Flexible Social Networking Platform.
Creating a Flex UIComponent with Ruboss…
Let’s start by creating a new project called “flexible_blog” in rails:
cd Documents/rails rails -d mysql flexible_blog
Next, place the plugin-enhanced Ruboss to the vendor/Plugins directory:
ls
ruboss_rails_integrationNow run the rconfig command to generate Flex and Rails scaffolding for the application (”scaffolds” are just predefined template classes to get you going, taking most of the initial work out of the project):
ruby script/generate rconfig create .flexProperties create .actionScriptProperties create .project create html-template/history create html-template/index.template.html create html-template/AC_OETags.js create html-template/playerProductInstall.swf create html-template/history/history.css create html-template/history/history.js create html-template/history/historyFrame.html create app/flex/flexible_blog/components create app/flex/flexible_blog/controllers create app/flex/flexible_blog/commands create app/flex/flexible_blog/models create app/flex/flexible_blog/components/generated/users create lib/ruboss.swc create public/javascripts/swfobject.js create public/expressInstall.swf overwrite public/index.html? (enter "h" for help) [Ynaqdh] a forcing ruboss_config force public/index.html create app/flex/lib create app/flex/lib/Cairngorm.swc create app/flex/com/pomodo/utils create app/flex/com/pomodo/utils/CairngormUtils.as create app/flex/flexible_blog/controllers/AppController.as create app/flex/flexible_blog/models/Flexible_blogModelLocator.as create app/flex/flexible_blog/controllers/Flexible_blogEvents.as create app/flex/skins create app/flex/skins/aqua create app/flex/skins/aqua/fonts create app/flex/skins/aqua/images create app/flex/skins/aqua/CSSPlus.swc create app/flex/skins/aqua/Aqua.css create app/flex/skins/aqua/fonts/lucidaGrande.swf ... lots of Aqua png image files ... dependency ruboss_controller create app/flex/flexible_blog/controllers/Flexible_blogController.as create app/flex/flexible_blog/components/generated/users/MainBox.mxml create app/flex/Flexible_blog.mxml
Next, set up your database connection. We are using MySQL.
rake db:mysql:stage ADMINPASS="mysql root password" USER="root"
If you haven’t yet set a root password for MySQL, type the following:
sudo mysqladmin -u root password your_passwordNow we will generate a scaffold for a blog “Post” and rerun rconfig to wire up the Flex Application controller and the events with the models, views, and commands. Our blog Post will have a title, a subtitle, a body, an author, a published boolean, and a created_at date. Also, to make it authenticated, we will say that it belongs_to a user, an authenticated User.
ruby script/generate rscaffold post title:string subtitle:string body:text author:string published:boolean created_at:date belongs_to:user with_user:user exists db/migrate create db/migrate/20080903234914_create_posts.rb create app/controllers/posts_controller.rb create app/models/post.rb create test/fixtures/posts.yml create app/flex/flexible_blog/models/Post.as create app/flex/flexible_blog/components/generated/PostBox.mxml route map.resources :posts exists app/flex/flexible_blog/commands create app/flex/flexible_blog/commands/PostCommand.as dependency rcontroller force app/flex/flexible_blog/controllers/Flexible_blogController.as dependency scaffold exists app/models/ exists app/controllers/ exists app/helpers/ create app/views/posts exists app/views/layouts/ exists test/functional/ exists test/unit/ exists public/stylesheets/ create app/views/posts/index.html.erb create app/views/posts/show.html.erb create app/views/posts/new.html.erb create app/views/posts/edit.html.erb create app/views/layouts/posts.html.erb create public/stylesheets/scaffold.css skip app/controllers/posts_controller.rb create test/functional/posts_controller_test.rb create app/helpers/posts_helper.rb route map.resources :posts dependency model exists app/models/ exists test/unit/ exists test/fixtures/ skip app/models/post.rb create test/unit/post_test.rb skip test/fixtures/posts.yml exists db/migrate Another migration is already named create_posts: db/migrate/20080903234914_create_posts.rb
The last line doesn’t matter (I’ll fix that later). The rscaffold command creates for you:
For Ruby on Rails:
- posts_controller.rb => controller
- post.rb => model
- create_posts.rb => migration
- posts_helper.rb => helper (does nothing now)
- posts.yml => yaml scaffold
- map.resources :posts => routing for posts
For Flex:
- Post.as => model
- PostBox.mxml => view UIComponent
- PostCommand.as => command
Ruboss for Ruby on Rails - The Main Parts
The Post Controller:
The posts_controller defines 6 RESTful methods, all based off the four basic HTTP methods: GET, POST, UPDATE, and DELETE:
index=> retrieves all of the posts (based on user if you specifywith_user)show=> retrieves a specific Postnew=> refreshes the page if an error occurs, it is not used by Rubosscreate=> creates and saves a new Post into the databaseupdate=> edits the Post if you have modified itdestroy=> deletes a specific Post from the database
posts_controller.rb
class PostsController < ApplicationController # GET /posts # GET /posts.xml # GET /posts.fxml def index @posts = current_user.posts respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } format.fxml { render :xml => @posts } end end # GET /posts/1 # GET /posts/1.xml # GET /posts/1.fxml def show @post = current_user.posts.find(params[:id]) respond_to do |format| format.html # show.html.erb format.xml { render :xml => @post } format.fxml { render :xml => @post } end end # GET /posts/new # GET /posts/new.xml def new @post = Post.new respond_to do |format| format.html # new.html.erb format.xml { render :xml => @post } end end # GET /posts/1/edit def edit @post = current_user.posts.find(params[:id]) rescue ActiveRecord::RecordNotFound => e prevent_access(e) end # POST /posts # POST /posts.xml # POST /posts.fxml def create @post = current_user.posts.new(params[:post]) respond_to do |format| if @post.save flash[:notice] = 'Post was successfully created.' format.html { redirect_to(@post) } format.xml { render :xml => @post, :status => :created, :location => @post } format.fxml { render :xml => @post } else format.html { render :action => "new" } format.xml { render :xml => @post.errors, :status => :unprocessable_entity } format.fxml { render :xml => @post.errors } end end end # PUT /posts/1 # PUT /posts/1.xml # PUT /posts/1.fxml def update @post = current_user.posts.find(params[:id]) respond_to do |format| if @post.update_attributes(params[:post]) flash[:notice] = 'Post was successfully updated.' format.html { redirect_to(@post) } format.xml { head :ok } format.fxml { render :xml => @post } else format.html { render :action => "edit" } format.xml { render :xml => @post.errors, :status => :unprocessable_entity } format.fxml { render :xml => @post.errors } end end end # DELETE /posts/1 # DELETE /posts/1.xml # DELETE /posts/1.fxml def destroy @post = current_user.posts.find(params[:id]) @post.destroy respond_to do |format| format.html { redirect_to(posts_url) } format.xml { head :ok } format.fxml { render :xml => @post } end end end
Each Rails controller is called from Flex’s HTTPService request, and the routes.rb file determines how to route the HTTP request to the appropriate controller. Ruboss added the following to the routes.rb file to make this happen:
map.resources :posts
The appropriate method is then executed in the controller. Then controller the talks to the database using methods on the Post model such as Post.find(:all) or Post.new(), and the result is then formatted into HTML, XML, or FXML (or even JSON or AMF if you’d like!). Flex then receives this data and updates its view! Cake.
Note: I’ve included/created the last argument, with_user, to wire the Ruby posts_controller for restful_authentication, so it can only access the posts that our user is authorized to access. It should be named with the same thing you call your user model (user, person, human, entity, …). if you leave this out, then the controller will retrieve all files regardless of the user. The subtle difference looks like this, for finding all Posts related to one user:
posts_controller.rb with argument with_user:
def index @posts = current_user.posts respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } format.fxml { render :xml => @posts } end end
posts_controller.rb without argument with_user:
def index @posts = Post.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @posts } format.fxml { render :xml => @posts } end end
The Post Model:
Ruboss generates a Post model that only has code for its associations, in this case, that it belongs_to the user model:
post.rb
class Post < ActiveRecord::Base belongs_to :user end
The Post Migration:
Ruboss creates this Rails migrations file for our Post automatically:
001_create_posts.rb
class CreatePosts < ActiveRecord::Migration def self.up create_table :posts do |t| t.string :title t.string :subtitle t.text :body t.string :author t.boolean :published t.date :created_at # belongs_to the following... t.references :user t.timestamps end end def self.down drop_table :posts end end
All of the arguments you typed into the command line are mapped here, allowing you to create a posts database table with all of those columns by typing a simple command: rake db:migrate. Migrations are powerful because if you later decide you want to add a number_of_comments column to your posts table, you can easily do that!
Ruboss for Flex - The Main Parts
The Post Model:
Ruboss creates an Actionscript Model class that is essentially a map of the database model found in the create_posts migrations file. It is a Bindable class too, so you can assign any of the variables to values easily in a Flex UIComponent. It also extends the RubossModel class, allowing you to call RESTful methods directly from the Post model. Here’s the class (you don’t need to modify it):
Post.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | package flexible_blog.models { import org.ruboss.models.RubossModel; [Resource(controller="posts")] [Bindable] public class Post extends RubossModel { public static const LABEL:String = "title"; public var title:String; public var subtitle:String; public var body:String; public var author:String; public var published:Boolean; public var createdAt:Date; public var withUser:*; [BelongsTo] public var user:User; public function Post( title:String = "", subtitle:String = "", body:String = "", author:String = "", published:Boolean = false, createdAt:Date = null, withUser:* = null, user:User = null ) { super(LABEL); this.title = title; this.subtitle = subtitle; this.body = body; this.author = author; this.published = published; this.createdAt = createdAt; this.withUser = withUser; this.user = user; } } } |
The Post View:
Ruboss generates for you a sample Flex UIComponent to visualize your data! It uses a Datagrid to display all of your database listings, and input boxes to write to the database. Here is the PostBox.mxml file:
PostBox.mxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | <?xml version="1.0" encoding="utf-8"?> <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" label="Post" xmlns:rcomponents="org.ruboss.components.*"> <mx:Script><![CDATA[ import org.ruboss.Ruboss; import org.ruboss.utils.RubossUtils; import flexible_blog.models.User; import flexible_blog.models.Post; import flexible_blog.controllers.Flexible_blogEvents; import com.pomodo.utils.CairngormUtils; [Bindable] public var editedPost:Post = new Post(); public function sendData(eventType:String):void { editedPost.title = titleTextInput.text; editedPost.subtitle = subtitleTextInput.text; editedPost.body = bodyTextArea.text; editedPost.author = authorTextInput.text; editedPost.published = publishedCheckBox.selected; editedPost.createdAt = createdAtDateField.selectedDate; editedPost.user = User(userComboBox.selectedItem); CairngormUtils.dispatchEvent(eventType, editedPost); } ]]></mx:Script> <mx:Panel title="Edit Post" width="400" height="100%"> <mx:Form paddingTop="40" width="100%" height="100%"> <mx:FormItem label="Title" width="100%"> <mx:TextInput id="titleTextInput" width="100%" text="{editedPost.title}"/> </mx:FormItem> <mx:FormItem label="Subtitle" width="100%"> <mx:TextInput id="subtitleTextInput" width="100%" text="{editedPost.subtitle}"/> </mx:FormItem> <mx:FormItem label="Body" width="100%"> <mx:TextArea id="bodyTextArea" width="100%" height="200" text="{editedPost.body}"/> </mx:FormItem> <mx:FormItem label="Author" width="100%"> <mx:TextInput id="authorTextInput" width="100%" text="{editedPost.author}"/> </mx:FormItem> <mx:FormItem label="Published" width="100%"> <mx:CheckBox id="publishedCheckBox" selected="{editedPost.published}"/> </mx:FormItem> <mx:FormItem label="CreatedAt" width="100%"> <mx:DateField id="createdAtDateField" selectedDate="{editedPost.createdAt}"/> </mx:FormItem> <mx:FormItem label="User" width="100%"> <mx:ComboBox id="userComboBox" width="200" labelField="{User.LABEL + ' - ' + User.SCREEN_NAME}" dataProvider="{Ruboss.models.index(User)}" prompt="User ..." selectedItem="{editedPost.user}" /> </mx:FormItem> </mx:Form> <mx:ControlBar width="100%"> <mx:Button label="Save Post" width="33%" height="30" click="sendData(Flexible_blogEvents.CREATE_POST)"/> <mx:Button label="Update Post" width="33%" height="30" enabled="{postsDataGrid.selectedItem != null}" click="sendData(Flexible_blogEvents.UPDATE_POST)"/> <mx:Button label="Delete Post" width="33%" height="30" enabled="{postsDataGrid.selectedItem != null}" click="sendData(Flexible_blogEvents.DESTROY_POST)"/> </mx:ControlBar> </mx:Panel> <mx:Panel id="postsPanel" width="80%" height="100%"> <mx:DataGrid id="postsDataGrid" height="100%" width="800" horizontalScrollPolicy="on" dragEnabled="true" dragMoveEnabled="true" dropEnabled="true" dataProvider="{Ruboss.models.index(Post)}" change="editedPost = Post(postsDataGrid.selectedItem)"> <mx:columns> <mx:DataGridColumn dataField="title" headerText="Title" width="150" minWidth="100"/> <mx:DataGridColumn dataField="subtitle" headerText="Subtitle" width="150" minWidth="100"/> <mx:DataGridColumn dataField="body" headerText="Body" width="150" minWidth="100"/> <mx:DataGridColumn dataField="author" headerText="Author" width="150" minWidth="100"/> <mx:DataGridColumn dataField="published" headerText="Published" width="150" minWidth="100"/> <mx:DataGridColumn dataField="created_at" headerText="Created_at" width="150" minWidth="100"/> <mx:DataGridColumn dataField="with_user" headerText="With_user" width="150" minWidth="100"/> </mx:columns> </mx:DataGrid> </mx:Panel> </mx:HBox> |
This is fantastic! And if you want, you can create your own template UIComponents for your data by modifying the appropriate template file in the plugin! It’s very easy to do. All of this happens through the generator in the plugin. Examine the ruboss_rails_integration generators to see how all of the stuff works, it’s great! It’s basically Embedded Ruby using Rails’ ActionView templates.
—–
A side note about Plugins (in case you wanted add to neat functionality to Ruboss scaffolding): Generators are common to all Plugins and can be modified by anyone to add any kind of functionality you think is helpful for the world. If you take a look into the ruboss_config_generator.rb file you will find two methods: initialize and manifest. The initialize method is there to assign all of the command-line arguments to specific Ruby attributes, depending on the options you specify. The manifest method’s main job is to place the scaffold files into the appropriate place in your Flexible Rails application. Use m.directory 'directory_name' to create directories, m.file 'current_location', 'desired_location' to transfer files, and m.template 'current_location', File.join("current_directory", "file_name") to create files from templates.
—–
Notice how this View has only one method, sendData(eventType). This method only function to 1) assign user input values to your Post model, 2) package the Post model into a CairngormEvent, and 3) dispatch the Event according to the eventType passed in. So, if you have a button that you want to function as a “Save Button”, then when the button is clicked, have it execute the following:
sendData(Flexible_blogEvents.CREATE_POST)
Then in the sendData(eventType) method, (using our Post model for example), include the following code (all “Inputs”, “Areas”, and “Boxes” are the Flex Components that have your user input data):
[Bindable] public var editedPost:Post = new Post(); public function sendData(eventType:String):void { editedPost.title = titleTextInput.text; editedPost.subtitle = subtitleTextInput.text; editedPost.body = bodyTextArea.text; editedPost.author = authorTextInput.text; editedPost.published = publishedCheckBox.selected; editedPost.createdAt = createdAtDateField.selectedDate; editedPost.user = User(userComboBox.selectedItem); CairngormUtils.dispatchEvent(eventType, editedPost); }
This sends an Event packaged with your Post model to the AppController, where all the details of getting it to the database through Rails is handled. It does this because each model only has four RESTful Events to choose from: LIST_POSTS, CREATE_POST, UPDATE_POST, and DELETE_POST.
The Post Command:
After the CairngormEvent is packaged with the Post model and dispatched, the PostCommand, which is a registered listener for the four RESTful Post Events listed above, does everything necessary to send the appropriate XML data to a Rails controller. It looks like this:
PostCommand.as
package flexible_blog.commands { import com.adobe.cairngorm.commands.Command; import com.adobe.cairngorm.control.CairngormEvent; import mx.rpc.IResponder; import org.ruboss.Ruboss; import org.ruboss.utils.RubossUtils; import flexible_blog.models.Post; import flexible_blog.controllers.Flexible_blogEvents; public class PostCommand implements Command { public var editedPost:Post; /** * Command Constructor. * Creates the "Post" Model from the Cairngorm Event data. * This allows common RESTful functions (show, create, update, delete) * to be reused by multiple views, thereby following the DRY principle. */ public function PostCommand() { super(); } public function execute(event:CairngormEvent):void { editedPost = event.data as Post; switch(event.type) { case Flexible_blogEvents.LIST_POSTS: listPosts(); break; case Flexible_blogEvents.CREATE_POST: createPost(); break; case Flexible_blogEvents.UPDATE_POST: updatePost(); break; case Flexible_blogEvents.DESTROY_POST: destroyPost(); break; } } /** * GET /posts * GET /posts.xml */ public function listPosts():void { Ruboss.models.index(Post); } /** * POST /post * POST /post.xml */ public function createPost():void { editedPost.create({afterCallback: onPostCreate}); } /** * PUT /post/1 * PUT /post/1.xml */ public function updatePost():void { editedPost.update({afterCallback: onPostUpdate}); } /** * DELETE /post/1 * DELETE /post/1.xml */ public function destroyPost():void { editedPost.destroy({afterCallback: onPostDestroy}); } // PRIVATE CLASSES private function onPostCreate(post:Post):void { editedPost = new Post; } private function onPostUpdate(post:Post):void { editedPost = RubossUtils.clone(post) as Post; } private function onPostDestroy(post:Post):void { onPostCreate(post); } } }
The private methods at the end are what you do when an HTTP response is sent back from Rails to Flex. You can include in here anything else you want, such as changing to a new view through the ModelLocator, dispatching a new event, etc.). A lot of “Ruboss Magic” occurs here, described a little further down. By the way, all the ModelLocator does is keep track of Application State for Flex.
So THAT’s what’s basically happening when you type those two commands into the command line. Crazy huh! Ruboss is insane.
Now just execute the rconfig command again. This will register the PostCommand as a listener to the four RESTful Events of the Post Model. This occurs in the AppController like this:
AppController.as
// ... other stuff public function initializeCommands():void { // Commands for the Post model... addCommand(Flexible_blogEvents.LIST_POSTS, PostCommand); addCommand(Flexible_blogEvents.CREATE_POST, PostCommand); addCommand(Flexible_blogEvents.UPDATE_POST, PostCommand); addCommand(Flexible_blogEvents.DESTROY_POST, PostCommand); }
And the Events are also added to the Flexible_blogEvents Class:
Flexible_blogEvents.as
// Events for the Post model... public static const LIST_POSTS:String = "list_posts"; public static const CREATE_POST:String = "create_post"; public static const UPDATE_POST:String = "update_post"; public static const DESTROY_POST:String = "destroy_post";
Adding our Authenticated User!
Before we see our Flexible Rails application in action, let’s quickly add an authenticated user, using Ruboss and the integrated restful_authentication plugin. I have added the restful_authentication plugin to Ruboss, as well as some template files to create the account creation screen (similar to the Pomodo example in Flexible Rails). Following the same pattern as above, here is everything we need to do to create our authenticated User model, which has_many :posts. In the command line, in your “flexible_blog” directory, enter the following:
ruby script/generate rscaffold user has_many:posts --authenticated ruby script/generate rconfig rake db:refresh rake db:migrate
Now open up Flex, go to Import. Then import “Existing Projects into Workplace”. Find your “flexible_blog” entry and click Finish. Go to Projects and select “Build All”.
One last thing before we check it out. Go into the users_controller.rb and sessions_controller.rb and cut out the include AuthenticatedSystem line and place it into the application ruby controller. And finally, don’t forget to comment out the line protect_from_forgery in the application.rb controller, and ADD before_filter :login_required to the application controller. Now just start the server and go to the URL!
ruby script/serverThe --authenticated option tells the Ruboss plugin’s rscaffold generator to create the scaffolding according to the restful_authentication plugin and the corresponding Flex-Cairngorm scaffolding. Go to http://localhost:3000/bin/Flexible_blog.html and see your work!

DOWNLOAD RUBOSS (with restful_authentication and attachment_fu enhancements)
In the next post I will outline the general architecture of the Ruboss-Cairngorm-Rails combo. If anyone wants to add a view for the blog Post model in this simple app, post it in the comments section!
Adios,
Lance
P.S., if you want to see the Post as it would appear in a semi-realistic blog, add a comment with the component to make this happen!















