<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>OnRails.org: Category Flex</title>
    <link>http://onrails.org/articles/category/flex</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Ruby On Rails and related matters.</description>
    <item>
      <title>Determine Test Coverage on your Flex Projects with Flexcover.</title>
      <description>&lt;p&gt;This week I was playing with &lt;a href="http://code.google.com/p/flexcover/"&gt;Flexcover&lt;/a&gt; a test coverage tool for Flex&amp;#8230;and it&amp;#8217;s really cool. If you you to determine how much test coverage you have in your Flex application then check out this screencast&amp;#8230;maybe skip to the end where you will see flexcover in action. The first part is how to assemble the Flexcover &lt;span class="caps"&gt;SDK&lt;/span&gt; to use with FlexBuilder. Again this is a non-scripted screencast with several &amp;#8220;oops&amp;#8221; and a big Swiss-French accent which I hope you will find useful.&lt;/p&gt;


	&lt;p&gt;The key here is if you do Flex, write unit tests and use this test coverage tool.&lt;/p&gt;


&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=2185199&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=2185199&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/2185199"&gt;Setting up Flexcover as test coverage tool for your Flex applications.&lt;/a&gt; from &lt;a href="http://vimeo.com/user507500"&gt;daniel wanja&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.

	&lt;p&gt;Enjoy,
Daniel.&lt;/p&gt;</description>
      <pubDate>Fri, 24 Oct 2008 06:06:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:63b1b9aa-0dbf-473f-a888-3eb821f6b2c9</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2008/10/24/determine-test-coverage-on-your-flex-projects-with-flexcover</link>
      <category>Flex</category>
    </item>
    <item>
      <title>Flex test coverage?</title>
      <description>&lt;p&gt;It&amp;#8217;s hard to imaging writing a Rails application without using &lt;a href="http://eigenclass.org/hiki.rb?rcov"&gt;rcov&lt;/a&gt; and get that fuzzy feeling you tested most if not all you application. Or at least get a good idea of what&amp;#8217;s tested. I &lt;a href="http://weblogs.macromedia.com/swebster/archives/2007/11/unit_testing_an.html"&gt;heard&lt;/a&gt; way back that Alex Uhlmann was working on some test coverage tools, but I didn&amp;#8217;t see anything coming out from Adobe. I haven&amp;#8217;t used test coverage for my Flex apps, but want to start. Any body has any good hints, stories, frameworks they use for test unit coverage in Flex? A quick google search pointed me to this &lt;a href="http://www.joeberkovitz.com/blog/2008/04/12/flex-air-code-coverage-announce/"&gt;article&lt;/a&gt; describing &lt;a href="http://code.google.com/p/flexcover/"&gt;Flexcover&lt;/a&gt;, just what I was looking for. Please share your experience.&lt;/p&gt;


	&lt;p&gt;Thanks!
Daniel.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: I am playing with FlexCover and just saw this &amp;#8220;Flexcover is a joint effort with Alex Uhlmann of Adobe Consulting, who has been working on a related set of ideas.&amp;#8221;. So I guess this is really Alex&amp;#8217;s work that Steven was referring to which is now open source under the &lt;span class="caps"&gt;MIT&lt;/span&gt; license. Cool!&lt;/p&gt;</description>
      <pubDate>Sat, 11 Oct 2008 02:36:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:42f7436f-e267-4dbf-9b4d-8650d7dbfc9f</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2008/10/11/flex-test-coverage</link>
      <category>Flex</category>
      <category>Ruby On Rails</category>
    </item>
    <item>
      <title>Flash Player 10 Mobile for iPhone?</title>
      <description>&lt;style&gt;
.qttitle {
  padding-left: 120px;
  min-height: 120px;
  background-image: url(http://images.apple.com/downloads/images/essentials_quicktime20070611.png);
  background-position: top left;
  background-repeat: no-repeat;
  vertical-align: middle;
}

.playButton {
  background-color: rgb(20,20,20);
  cursor: pointer;
  font-weight: bold;
  font-size: 1.25em;
  opacity: .8;
  filter: alpha(opacity=80);
  -moz-border-radius: 1em;
  -webkit-border-radius: 1em;
  position: relative;
  top: 50%;
  zoom: 100%;
  padding: .5em 1em;
  color: white;
}

.playBackground {
  background-color: rgb(0,0,0);
  opacity: 0.0;
  filter: alpha(opacity=0);
  position: absolute;
  top: 0px; left: 0px;
}
&lt;/style&gt;

I was viewing the video of the &lt;a href="http://www.onflex.org/ted/2008/08/360flex-day-1-keynote-by-mark-anders.php"&gt;Day 1 Keynote&lt;/a&gt; by Mark Anders at 360Flex where he made a reference to a mobile Flash application build in Flex. Mark just skinned a desktop app which turned in into a very iPhone like application which just happen to have the iPhone screen dimensions and behavior. It's 56 minutes in the presentation. Check it out and let me know what you think. I've included a video extract here after (without the sound): 

&lt;script src="http://www.apple.com/library/quicktime/scripts/ac_quicktime.js" language="JavaScript" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="http://www.apple.com/library/quicktime/scripts/qtp_library.js" language="JavaScript" type="text/javascript"&gt;&lt;/script&gt;

&lt;script type="text/javascript"&gt;&lt;!--
	QT_WritePoster_XHTML('Click to Play', 'http://onrails.org/files/20080827_flexiphoneskin_action-poster.jpg',
		'http://onrails.org/files/20080827_flexiphoneskin_action.mov',
		'246', '385', '',
		'controller', 'true',
		'autoplay', 'true',
		'bgcolor', 'black',
		'scale', 'aspect');
//--&gt;
&lt;/script&gt;
&lt;noscript&gt;
&lt;object width="246" height="385" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab"&gt;
	&lt;param name="src" value="http://onrails.org/files/20080827_flexiphoneskin_action-poster.jpg" /&gt;
	&lt;param name="href" value="http://onrails.org/files/20080827_flexiphoneskin_action.mov" /&gt;
	&lt;param name="target" value="myself" /&gt;
	&lt;param name="controller" value="false" /&gt;
	&lt;param name="autoplay" value="false" /&gt;
	&lt;param name="scale" value="aspect" /&gt;
	&lt;embed width="246" height="385" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/"
		src="http://onrails.org/files/20080827_flexiphoneskin_action-poster.jpg"
		href="http://onrails.org/files/20080827_flexiphoneskin_action.mov"
		target="myself"
		controller="false"
		autoplay="false"
		scale="aspect"&gt;
	&lt;/embed&gt;
&lt;/object&gt;
&lt;/noscript&gt;
	
That's when he changed the skin:
&lt;div style="text-align:center;"&gt;&lt;img src="http://onrails.org/files/20080827_flexiphoneskin.png" alt="20080827_flexiphoneskin.png" border="0" width="567" height="179" /&gt;&lt;/div&gt;

That would be cool if we could soon start coding in Flex for the iPhone.

Enjoy!
Daniel.</description>
      <pubDate>Wed, 27 Aug 2008 21:58:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:754e7526-9929-44b0-ada2-e8af98162600</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2008/08/27/flash-player-10-mobile-for-iphone</link>
      <category>Flex</category>
    </item>
    <item>
      <title>BlazeDS and open source version of livecycle data services...</title>
      <description>&lt;p&gt;That sounds cool. Read all about it here&amp;#8230;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.techcrunch.com/2007/12/12/adobe-releases-blaze-ds-open-source-version-of-livecycle-data-services/"&gt;http://www.techcrunch.com/2007/12/12/adobe-releases-blaze-ds-open-source-version-of-livecycle-data-services/&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Maybe not. Techcrunch released this message on their blog but no text was attached and comments where closed. Maybe somebody clicked the submit button to quickly. Now I am curious&amp;#8230;&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: 10:17pm Denver time&amp;#8230;it&amp;#8217;s official: &lt;a href="http://www.adobe.com/aboutadobe/pressroom/pressreleases/200712/121307BlazeDS.html"&gt;http://www.adobe.com/aboutadobe/pressroom/pressreleases/200712/121307BlazeDS.html&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 13 Dec 2007 03:35:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:3ea750d6-f365-444e-a9ef-865ea9db8a8d</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/12/13/blaze-ds-and-open-source-version-of-livecycle-data-services</link>
      <category>Flex</category>
    </item>
    <item>
      <title>Analyzing the Subversion logs from the Rails project with mx:OLAPCube</title>
      <description>&lt;p&gt;I started playing with &lt;a href="http://anthonyeden.com"&gt;Anthony Eden&amp;#8217;s&lt;/a&gt; &lt;a href="http://activewarehouse.rubyforge.org/"&gt;ActiveWarehouse&lt;/a&gt; and followed his &lt;a href="http://anthonyeden.com/2006/12/20/activewarehouse-example-with-rails-svn-logs"&gt;excellent tutorial&lt;/a&gt; on how to analyze the Ruby On Rails Svn Commit Log with the ActiveWarehouse framework. Of course this made me want to try to do the same with the new mx:OLAPCube and mx:OLAPDataGrid provided by Flex 3 as part of the DataVisualization components. Let me just say this&amp;#8230;I am not done playing with either the Flex OLAPCube nor the Rails ActiveWarehouse framework as these are pretty complex beasts. Both of these frameworks are overlapping and complementary. There are overlapping as both can digest raw data and perform aggregation of that data. They are complementary in the sense that a server side warehouse needs a good visualization front-end. Maybe the OLAPCube and OLAPDataGrid can be this front-end. In my initial trials I haven&amp;#8217;t come up with a compelling way to integrate both, but by using some simple &lt;span class="caps"&gt;SQL I&lt;/span&gt; could extract the data from the ActiveWarehouse and pass it to the OLAPCube.&lt;/p&gt;


	&lt;p&gt;Before going on you may want to read Anthony&amp;#8217;s &lt;a href="http://anthonyeden.com"&gt;blog&lt;/a&gt; and check his presentation  on &lt;a href="anthonyeden.com/assets/2007/5/20/activewarehouse.pdf"&gt;Data Warehouses with ActiveWarehouse&lt;/a&gt;. I didn&amp;#8217;t find much information on the Flex OLAPCube besides these: &lt;a href="http://labs.adobe.com/wiki/index.php/Flex_3:Feature_Introductions:_OLAPDataGrid"&gt;Feature_Introductions:_OLAPDataGrid on Adobe&amp;#8217;s labs&lt;/a&gt;,  &lt;a href="http://labs.adobe.com/technologies/flex/videos/olap/"&gt;Flex 3: Feature Introduction Video for &lt;span class="caps"&gt;OLAP&lt;/span&gt; Support&lt;/a&gt;, and these &lt;a href="http://download.macromedia.com/pub/labs/flex/3/featuresamples/olapsamples_beta2.zip"&gt;Flex examples&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;So I create the following sample application. You can try it out &lt;a href="http://myspyder.net/tools/svnlogvisualizer/" target="_blank"&gt;here&lt;/a&gt;. Note it&amp;#8217;s pretty slow, it takes up to a minute to aggregate 10000 values. The Flex team mentioned they didn&amp;#8217;t optimize this component yet. I can confirm this. But I may also have messed something up as these are only my initial steps with that component. The application displays the Author dimension with the Author Name as rows and the Time dimension with the Year and Quarter as columns. The facts is the File Change count during that period. Flex calls the &amp;#8220;facts&amp;#8221; a measure. 
&lt;br/&gt;
&lt;img src="http://onrails.org/files/20071128_OLAPCube.jpg" alt="20071128_OLAPCube.jpg" border="0" width="495" /&gt;
&lt;br/&gt;
&lt;a href="http://myspyder.net/tools/svnlogvisualizer/" target="_blank"&gt;Run the applicaiton&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;To extract the data from the ActiveWarehouse I created this &lt;span class="caps"&gt;SQL&lt;/span&gt; to join the facts table with all the dimensions table. I need to find out if the ActiveWarehouse doesn&amp;#8217;t just return this data in xml format by using it&amp;#8217;s build-in classes.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;report_as_xml&lt;/span&gt;
    &lt;span class="ident"&gt;sql&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="constant"&gt;EOSQL&lt;/span&gt;&lt;span class="string"&gt;
    SELECT
     date.calendar_year,
     date.calendar_quarter,
     date.calendar_month_name,
     author.name,
     file_revision_facts.file_changed AS `file_changed`
    FROM
     file_revision_facts
    JOIN date_dimension as date
     ON file_revision_facts.date_id = date.id
    JOIN author_dimension as author
     ON file_revision_facts.author_id = author.id
    WHERE 
      date.calendar_year &amp;gt; '2005'
&lt;/span&gt;&lt;span class="constant"&gt;    EOSQL&lt;/span&gt;

    &lt;span class="attribute"&gt;@@xml&lt;/span&gt; &lt;span class="punct"&gt;||=&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;connection&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select_all&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sql&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;to_xml&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:dasherize&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;render&lt;/span&gt; &lt;span class="symbol"&gt;:text&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="attribute"&gt;@@xml&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;In Flex the OLAPCube can be loaded with the &lt;span class="caps"&gt;XML&lt;/span&gt;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    var data:ICollectionView = new ArrayCollection(result.records.record); // is Array
    cube.dataProvider = data;
    cube.addEventListener(CubeEvent.CUBE_COMPLETE, creationCompleteHandler);
    cube.refresh();        &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Once the cube is loaded you can slice and dice it in many ways by using an OLAPQuery. I still need to figure out all the possibilities which are offered.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    [Bindable]
    private var cubeResult:IOLAPResult;

    private function creationCompleteHandler(event:CubeEvent):void
    {
        //Cube was created, let's query it
        var query:OLAPQuery = new OLAPQuery;

        // TIME DIMENSION            
        var yearSet:IOLAPSet = new OLAPSet;
        yearSet.addElements(cube.findDimension(&amp;quot;Time&amp;quot;).findAttribute(&amp;quot;Year&amp;quot;).members);

        var quarterSet:IOLAPSet = new OLAPSet;
        quarterSet.addElements(cube.findDimension(&amp;quot;Time&amp;quot;).findAttribute(&amp;quot;Quarter&amp;quot;).members);

        //year-quarter
        var newTimeSet:IOLAPSet = yearSet.crossJoin(quarterSet);

        // AUTHOR    DIMENSION    
        var authorSet:IOLAPSet = new OLAPSet;
        authorSet.addElements(cube.findDimension(&amp;quot;Author&amp;quot;).findAttribute(&amp;quot;Name&amp;quot;).members);

        // ROW/COLUMNS        
        var rowAxis:IOLAPQueryAxis = query.getAxis(OLAPQuery.ROW_AXIS);
        rowAxis.addSet(authorSet.hierarchize(true));
        var colAxis:IOLAPQueryAxis = query.getAxis(OLAPQuery.COLUMN_AXIS);
        colAxis.addSet(newTimeSet.hierarchize(true));

        // QUERY CUBE
        var token:AsyncToken = cube.execute(query);
       token.addResponder(new AsyncResponder(displayResult, olapFaultHandler));
    }
    private function displayResult(result:Object, token:Object=null):void
    {
        cubeResult = result as IOLAPResult;
    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The cube result is the dataProvider of the Cube which in it&amp;#8217;s simplests form can be defined as follows:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;mx:OLAPDataGrid id=&amp;quot;olapGrid&amp;quot; dataProvider=&amp;quot;{cubeResult}&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I&amp;#8217;ve then added a change listener for the grid to create the dataProvider for the ColumnChart.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    [Bindable]
    private var chartData:Array;

    private function gridSelectionChanged():void {
        if (!(olapGrid.selectedItem is OLAPAxisPosition)) return;
        var rowIndex:Number = olapGrid.selectedIndex;
        var axis:IOLAPQueryAxis = cubeResult.query.getAxis(OLAPQuery.COLUMN_AXIS);
        var columnLength:Number = cubeResult.getAxis(OLAPQuery.COLUMN_AXIS).positions.length;
        var newChartData:Array = [];
        for (var i:int=0;i&amp;lt;columnLength;i++) {
            var tuple:OLAPTuple = axis.tuples[i];
            var key:String = tuple.explicitMembers.toArray().join(&amp;quot;,&amp;quot;);
            if (key.indexOf(&amp;quot;(All)&amp;quot;) &amp;gt; -1) continue;            newChartData.push({key:key, value:cubeResult.getCell(rowIndex, i).value});
        }
        chartData = newChartData;
    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

This code to extract a time serie for the chart is a little &amp;#8220;hairy&amp;#8221;. I hope the Flex team has some OLAPCharts on their todo list ;-)&lt;br/&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;mx:ColumnChart id=&amp;quot;chart&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;30%&amp;quot; dataProvider=&amp;quot;{chartData}&amp;quot;&amp;gt;
        &amp;lt;mx:series&amp;gt;
            &amp;lt;mx:ColumnSeries yField=&amp;quot;value&amp;quot; /&amp;gt;
        &amp;lt;/mx:series&amp;gt;
        &amp;lt;mx:horizontalAxis&amp;gt;
            &amp;lt;mx:CategoryAxis categoryField=&amp;quot;key&amp;quot; /&amp;gt;
        &amp;lt;/mx:horizontalAxis&amp;gt;
&amp;lt;/mx:ColumnChart&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;This are my first tribulations with both frameworks. Over the next few month I will have to dive more deeply into the possibilities which are offered. Thanks to both teams as this is pretty cool.&lt;/p&gt;


	&lt;p&gt;Enjoy!
Daniel.&lt;/p&gt;</description>
      <pubDate>Thu, 29 Nov 2007 05:23:34 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:e8079876-729e-419c-93c8-50194b7026d5</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/11/29/analyzing-the-subversion-logs-from-the-rails-project-with-mx-olapcube</link>
      <category>Flex</category>
    </item>
    <item>
      <title>flash.utils.ByteArray compressing 4.1MB to 20K</title>
      <description>&lt;p&gt;I am currently preparing a demo using an mx:OLAPCube and OLAPDataGrid which analyze the Rails svn commit log. however I don&amp;#8217;t want to deploy a specific server side application as the Cube can load data from &lt;span class="caps"&gt;XML&lt;/span&gt;. So I have an report.xml that is 4.1MB.  I created the following &lt;span class="caps"&gt;AIR&lt;/span&gt; application (ZlibCompressor.mxml) that use the standard compression provided by the ByteArray class to compress this file down to 20Kb. The application that consumes this file (UnzipTest.mxml) uses the URLLoader to read this file straight into a ByteArray and uncompress the data. It&amp;#8217;s fast!&lt;/p&gt;


	&lt;p&gt;The key code for compression is the &amp;#8216;compress&amp;#8217; and &amp;#8216;uncompress&amp;#8217; method provided by the ByteArray. Note the URLLoader dataFormat is set to &amp;#8220;binary&amp;#8221;.&lt;/p&gt;


&lt;h3&gt;ZlibCompressor.mxml&lt;/h3&gt;        
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;mx:WindowedApplication xmlns:mx=&amp;quot;http://www.adobe.com/2006/mxml&amp;quot; layout=&amp;quot;vertical&amp;quot;
    nativeDragDrop=&amp;quot;onDrop(event)&amp;quot;
    nativeDragEnter=&amp;quot;onDragIn(event)&amp;quot;     &amp;gt;
&amp;lt;mx:Script&amp;gt;
    &amp;lt;![CDATA[
    import flash.desktop.ClipboardFormats;    
    import flash.utils.CompressionAlgorithm;
    public function onDragIn(event:NativeDragEvent):void {
        var transferable:Clipboard = event.clipboard;
        if (transferable.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) {
                DragManager.acceptDragDrop(this);
        }      
    }
    public function onDrop(event:NativeDragEvent):void {
        var fileList:Array = event.clipboard.dataForFormat(ClipboardFormats.FILE_LIST_FORMAT) as Array;
        if (fileList.length==0) return;

        var inFile:File = fileList[0];
        var fileStream:FileStream = new FileStream();
        fileStream.open(inFile, FileMode.READ);
        var ba:ByteArray = new ByteArray();
        fileStream.readBytes(ba, 0, fileStream.bytesAvailable);
        fileStream.close();

        var newFileName:String = inFile.nativePath+&amp;quot;.zlib&amp;quot;;
        ba.compress();

        var outFile:File = new File(newFileName);
        fileStream = new FileStream();
        fileStream.open(outFile, FileMode.WRITE);
        fileStream.writeBytes(ba, 0, ba.length);
        fileStream.close();        
    }                    
    ]]&amp;gt;
&amp;lt;/mx:Script&amp;gt;    
&amp;lt;/mx:WindowedApplication&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;UnzipTest.mxml&lt;/h3&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;mx:Application xmlns:mx=&amp;quot;http://www.adobe.com/2006/mxml&amp;quot; layout=&amp;quot;vertical&amp;quot; creationComplete=&amp;quot;loadData()&amp;quot;&amp;gt;
&amp;lt;mx:Script&amp;gt;
    &amp;lt;![CDATA[
    import mx.rpc.events.ResultEvent;
    import flash.utils.ByteArray;

    import flash.events.*;
    import flash.net.*;    

    private function loadData():void {
         var loader:URLLoader = new URLLoader();
         loader.dataFormat = &amp;quot;binary&amp;quot;;
         loader.addEventListener(Event.COMPLETE, completeHandler); 
         var request:URLRequest = new URLRequest(&amp;quot;../data/report.xml.zlib&amp;quot;);
         loader.load(request);
    }
    private function completeHandler(event:Event):void {
        var loader:URLLoader = URLLoader(event.target);
        var ba:ByteArray = loader.data;
        ba.uncompress();
        var s:String = ba.toString();
        var xml:XML = new XML(s);
    }
    ]]&amp;gt;
&amp;lt;/mx:Script&amp;gt;    
&amp;lt;/mx:Application&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Tue, 27 Nov 2007 00:01:11 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:0dcf110b-931a-4cfc-92ab-84dd8205aa8e</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/11/27/flash-utils-bytearray-compressing-4-1mb-to-20k</link>
      <category>Flex</category>
    </item>
    <item>
      <title>Acts_as_nested_set  ActiveRecord rendered with mx:Tree in  Flex.</title>
      <description>ActiveRecord: app/models/category.rb
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;app/models/category.rb&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Category&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
  &lt;span class="ident"&gt;acts_as_nested_set&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

Controller: app/controllers/categories_controller.rb
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;app/controllers/categories_controller.rb&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;CategoriesController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&lt;/span&gt;
     &lt;span class="constant"&gt;Category&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;result_to_attributes_xml&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Category&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;root&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;full_set&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

Flex Application: ActsAsNestedSet.mxml
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;ActsAsNestedSet.mxml&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_javascript "&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;mx:Application xmlns:mx=&amp;quot;http://www.adobe.com/2006/mxml&amp;quot; 
    layout=&amp;quot;vertical&amp;quot;
    applicationComplete=&amp;quot;categories.send()&amp;quot;&amp;gt;
&amp;lt;mx:HTTPService id=&amp;quot;categories&amp;quot; url=&amp;quot;http://localhost:3000/categories&amp;quot; resultFormat=&amp;quot;e4x&amp;quot; /&amp;gt;
&amp;lt;mx:Tree dataProvider=&amp;quot;{categories.lastResult}&amp;quot; 
    labelField=&amp;quot;@name&amp;quot;
    width=&amp;quot;100%&amp;quot; height=&amp;quot;100%&amp;quot; /&amp;gt;    
&amp;lt;/mx:Application&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Result:
&lt;img src="http://onrails.org/files/20071123_categories.jpg" alt="20071123_categories.jpg" border="0" width="264" height="296" /&gt;&lt;/p&gt;


&lt;span class="caps"&gt;XML&lt;/span&gt; generated by Category.result_to_attributes_xml(Category.root.full_set):
&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;&lt;span class="caps"&gt;XML&lt;/span&gt; generated by Category.result_to_attributes_xml(Category.root.full_set)&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_xml "&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Main Category&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;15&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Cameras &lt;/span&gt;&lt;span class="entity"&gt;&amp;amp;amp;&lt;/span&gt;&lt;span class="string"&gt; Photo&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;16&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Bags&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;17&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Accessories&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;18&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Analog Cameras&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;19&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Digital Cameras&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Cell Phones&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;21&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Accessories&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;22&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Phones&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;23&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Prepaid Cards&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;24&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dvds&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;25&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Blueray&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;26&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;HD DVD&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;27&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;DVD&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;28&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="attribute"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&amp;quot;/&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;node&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I used the http://wiki.rubyonrails.org/rails/pages/BetterNestedSet plugin.&lt;/p&gt;


	&lt;p&gt;Too cool!&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: The BetterNestedSet plugin doesn&amp;#8217;t work out of the box with Rails 2.0 &lt;span class="caps"&gt;RC1&lt;/span&gt;. Thanks Joel for that info. Read more in the comment of this blog entry.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;UPDATE2&lt;/span&gt;: Thanks Fabien, BetterNestedSet now works with Rails 2.0!&lt;/p&gt;</description>
      <pubDate>Sat, 24 Nov 2007 03:30:13 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:b895cbd0-6a58-4532-9f96-4a3a6570947f</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/11/24/acts_as_nested_set-activerecord-rendered-with-mx-tree-in-flex</link>
      <category>Flex</category>
      <category>Ruby On Rails</category>
    </item>
    <item>
      <title>RailsLogVisualizer0.7 for AIR beta 2.</title>
      <description>I recompiled the RailsLogVisualizer for AIR beta. I added drag&amp;drop of log files to bypass an AIR bug on Leopard. File.browseForOpen doesn't trigger the Event.SELECT when the file is selected. I haven't yet tried this version of the application on older versions of OSX or on Windows. Let me know how it works. Also the feedback when loading large log files could be improved, as the application seems to freeze once the progress bar is complete. Just be a little patient as the AVM is working hard for you to compute all these number. 

    &lt;h3&gt;Install RailsLogVisualizer0.7.air&lt;/h3&gt;
    &lt;object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
         id="RailsLogVisualizer" width="215" height="138"
         codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"&gt;
      &lt;param name="movie" value="http://myspyder.net/tools/railslogvisualizer/badge.swf" /&gt;
      &lt;param name="FlashVars" value="appUrl=http://myspyder.net/tools/railslogvisualizer/RailsLogVisualizer0.7.air&amp;airversion=1.0.M5" /&gt;
      &lt;embed src="http://myspyder.net/tools/railslogvisualizer/badge.swf" quality="high" bgcolor="#ffffff"
                 FlashVars="appUrl=http://myspyder.net/tools/railslogvisualizer/RailsLogVisualizer0.7.air&amp;airversion=1.0.M5"
                 width="215" height="138" name="RailsLogVisualizer" align="middle"
                 play="true"
                 type="application/x-shockwave-flash"
                 pluginspage="http://www.adobe.com/go/getflashplayer"&gt; &lt;/embed&gt;
    &lt;/object&gt;

    &lt;h3&gt;Install Manually&lt;/h3&gt;
    1) Instal Adobe AIR beta 2. (See release notes if previous version was installed)&lt;br/&gt;
    &lt;a href="http://download.macromedia.com/pub/labs/air/air_b2_mac_100107.dmg"&gt;Download AIR for OSX&lt;/a&gt; &lt;a href="http://download.macromedia.com/pub/labs/air/air_b2_win_100107.exe"&gt;Download AIR for Windows&lt;/a&gt;&lt;br/&gt;
    Learn more on &lt;a href="http://labs.adobe.com/technologies/air/"&gt;AIR&lt;/a&gt; &lt;br/&gt;
    &lt;br/&gt;
    2) Download and install &lt;a href="RailsLogVisualizer0.7.air"&gt;http://myspyder.net/tools/railslogvisualizer/RailsLogVisualizer0.7.air&lt;/a&gt; 

&lt;p style="clear:both" /&gt;

For &lt;a href="http://time.onrails.org/"&gt;time.onrails.org&lt;/a&gt; the log file is currently 98Mb and is loaded and process in less than a minute. Here are the loading details:  
&lt;pre&gt;
Loaded 98571986bytes in 28093 milliseconds.
Parsing file. Please Wait this may take some time....
Parsing. Split 1639453entries in 1447 milliseconds.
found:220767 in 1925 milliseconds.
Aggregating data.
	aggregated:220767 in 13426 milliseconds.
	Aggregated:89135
	aggregated String :4440464(bytes) in 2790 milliseconds.
&lt;/pre&gt;

Then you can navigation through time and see how many request where processed and drill down in specific action and specific methods. For example, here we can quickly see that for October 99 people signed up, 869 did login, 22 forgot their password.
 
&lt;div style="text-align:center;"&gt;&lt;img src="http://onrails.org/files/20071106_railslogvisualizer.jpg" alt="20071106_railslogvisualizer.jpg" border="0" width="480" height="373" /&gt;&lt;/div&gt;

Enjoy,
Daniel.




</description>
      <pubDate>Thu, 08 Nov 2007 04:12:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:b2c54e85-6ef6-4ebb-8c7f-76f92925d428</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/11/08/railslogvisualizer0-7-for-air-beta-2</link>
      <category>Flex</category>
      <category>Ruby On Rails</category>
    </item>
    <item>
      <title>Sweet way to write Flex Unit tests for Rails</title>
      <description>&lt;p&gt;Using ActiveResources from Flex? Using FlexUnit? Here is a nice way to write your tests.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;div class="codetitle"&gt;Example Test Case&lt;/div&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;package&lt;/span&gt; &lt;span class="ident"&gt;tests&lt;/span&gt;
&lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;flexunit&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;framework&lt;/span&gt;&lt;span class="punct"&gt;.*;&lt;/span&gt;    
    &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;mx&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;rpc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;AsyncToken&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
    &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;mx&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;rpc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;events&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;ResultEvent&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
    &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;resources&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Raffles&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;

    &lt;span class="ident"&gt;public&lt;/span&gt; &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestRaffles&lt;/span&gt; &lt;span class="ident"&gt;extends&lt;/span&gt; &lt;span class="constant"&gt;BaseTestCase&lt;/span&gt;
    &lt;span class="punct"&gt;{&lt;/span&gt;    
        &lt;span class="ident"&gt;private&lt;/span&gt; &lt;span class="ident"&gt;var&lt;/span&gt; &lt;span class="ident"&gt;raffles&lt;/span&gt;&lt;span class="symbol"&gt;:Raffles&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;        
        &lt;span class="ident"&gt;public&lt;/span&gt; &lt;span class="ident"&gt;function&lt;/span&gt; &lt;span class="constant"&gt;TestRaffles&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="constant"&gt;String&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;null&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="punct"&gt;{&lt;/span&gt;
            &lt;span class="keyword"&gt;super&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
            &lt;span class="ident"&gt;fixtures&lt;/span&gt;&lt;span class="punct"&gt;([&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;raffles&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]);&lt;/span&gt;
             &lt;span class="ident"&gt;raffles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="constant"&gt;Raffles&lt;/span&gt;&lt;span class="punct"&gt;();&lt;/span&gt;
        &lt;span class="punct"&gt;}&lt;/span&gt;            
        &lt;span class="ident"&gt;public&lt;/span&gt; &lt;span class="ident"&gt;function&lt;/span&gt; &lt;span class="ident"&gt;testRemoteFindRaffle&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;&lt;span class="symbol"&gt;:void&lt;/span&gt;
        &lt;span class="punct"&gt;{&lt;/span&gt;
            &lt;span class="ident"&gt;assertRemote&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;raffles&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;show&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;));&lt;/span&gt;
        &lt;span class="punct"&gt;}&lt;/span&gt;
        &lt;span class="ident"&gt;public&lt;/span&gt; &lt;span class="ident"&gt;function&lt;/span&gt; &lt;span class="ident"&gt;assertRemote_testRemoteFindRaffle&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;data&lt;/span&gt;&lt;span class="symbol"&gt;:Object&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;span class="symbol"&gt;:void&lt;/span&gt;
        &lt;span class="punct"&gt;{&lt;/span&gt;
            &lt;span class="constant"&gt;Assert&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assertTrue&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Raffle show successfully called&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;data&lt;/span&gt; &lt;span class="ident"&gt;is&lt;/span&gt; &lt;span class="constant"&gt;ResultEvent&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;  
            &lt;span class="ident"&gt;assertEquals&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;MyString&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;data&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;result&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt;
        &lt;span class="punct"&gt;}&lt;/span&gt;        

    &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Note this code is not yet a plugin and is using code you can find here: &lt;a href="http://code.google.com/p/flexonrails/source"&gt;http://code.google.com/p/flexonrails/source&lt;/a&gt;. I was starting to use it on multiple projects so I thought it was to time find a home for it. Also it is using the org.onrails.rails.ActiveResourceClient Flex class. I would recommend that you use &lt;a href="http://code.google.com/p/as3-active-resource/"&gt;Alex MacCaw&amp;#8217;s ActvieResrouce for Actionscript&lt;/a&gt;. I still need to talk with Alex and integrate this fixture loading code with his code.&lt;/p&gt;


	&lt;p&gt;The BaseTestCase Flex class is an extended TestCase that provides support for fixtures. Now in your constructor you can define which fixtures you want to reload between each test. Only tests methods starting with &amp;#8220;testRemote&amp;#8221; will trigger refreshing the fixtures. As you know, when using &lt;span class="caps"&gt;AMF&lt;/span&gt; or HttpService remote invocations are asynchronous and you cannot test the result of a remote call in the same method than where the call is made from. That&amp;#8217;s why I added the assertRemote method which takes an AsyncToken as parameters. This will automatically invoke a method whos name starts with assertRemote_ followed by the test method name. This simplifies greatly writing asynchronous tests. FlexUnit provides the &lt;em&gt;addAsync&lt;/em&gt; method, we just add the convenience assertRemote function to setup all the callbacks.&lt;/p&gt;


	&lt;p&gt;To make this work for you Flex with Rails project. You need to fixtures_controller.rb to your controllers and setup the following routes:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;RAILS_ENV&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;map&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;resources&lt;/span&gt; &lt;span class="symbol"&gt;:fixtures&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:new&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:test_results&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:post&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="ident"&gt;map&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;crossdomain&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/crossdomain.xml&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;fixtures&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;crossdomain&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;You need to extend your Flex TestCase from tests.BaseTestCase.&lt;/p&gt;


	&lt;p&gt;Enjoy,
Daniel.&lt;/p&gt;</description>
      <pubDate>Mon, 05 Nov 2007 15:11:56 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:1b2986d1-3683-4b3a-8491-197e2ac794b3</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/11/05/sweet-way-to-write-flex-unit-tests-for-rails</link>
      <category>Flex</category>
      <category>Ruby On Rails</category>
    </item>
    <item>
      <title>Flex Dynamic  Scaffolding for Ruby on Rails.</title>
      <description>&lt;p&gt;No I am not announcing the next killer scaffolding framework but I had a couple of hours available today so I just explored some of the cool features or Ruby On Rails and Flex. The part I was most interested in (today) is dynamic user interface creation and not generating and application like several scaffolding frameworks are doing. So I was able to create a UI that adapts to a given model of a Rails application. Of course I didn&amp;#8217;t go as far as I wished, but I thought I could share it with my readers as I usually get valuable feedback. Right now the application doesn&amp;#8217;t  even manage data. That will be the next step.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://onrails.org/files/20070804_FlexScaffolding.jpg" border="0"  width="500" alt="20070804_FlexScaffolding.jpg" align="" /&gt;
In a first phase I have adapted &lt;a href="http://railroad.rubyforge.org/"&gt;RaildRoad&lt;/a&gt; Rails model class diagram generation tool to generate an xml definition that the UI would use to create it&amp;#8217;s components. I generated an xml model for &lt;a href="http://trac.streamlinedframework.org/wiki/SampleProject"&gt;Sports&lt;/a&gt; a sample application provided with Streamlined and &lt;a href="http://typosphere.org/"&gt;Typo&lt;/a&gt; a blog server.&lt;/p&gt;


	&lt;p&gt;The UI generation from the typo model is quite cpu intensive. There is not lazy instanciation of components, when you select the model, all the Tabs, lists and forms are created.&lt;/p&gt;


	&lt;p&gt;You can &lt;a href="http://nouvelles-solutions.com/onrails/flexscaffolding/FlexScaffolding#"&gt;run the application&lt;/a&gt; and press view source from the context menu. Or you can see the source &lt;a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/index.html"&gt;here&lt;/a&gt;. The generated xml can be seen &lt;a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/source/sports_models.xml.txt"&gt;here&lt;/a&gt; and &lt;a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/source/typo_models.xml.txt"&gt;here&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;In a second phase I created a Flex application that generates a UI from the given xml.&lt;/p&gt;


	&lt;p&gt;I was writing this blog entry while coding, so if you are more curious about how all this works, keep on reading.&lt;/p&gt;


&lt;h1&gt;Getting the schema of your ActiveRecords&lt;/h1&gt;

	&lt;p&gt;We will generate an xml version of the schema that Flex can use to assemble a UI. So we need to find out info about each ActiveRecord of the application, it&amp;#8217;s association with other ActiveRecords, and all it&amp;#8217;s attributes. Later on would also be nice to identify the validation rules, so that we can build some validations on the fly without having to do a server round trip for some of the basic validations, (required, length, confirmation, regex). Supporting the various acts_as could also provide lots of functionality that doesn&amp;#8217;t need to be coded over and over.&lt;/p&gt;


	&lt;p&gt;I will use the Streamlined Sports example database to experiment with. Later on we may have a look at Typo a blog server.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s use the community to see how to parse the ActiveRecord. I am now checking out &lt;a href="http://railroad.rubyforge.org"&gt;RailRoad (0.4.0)&lt;/a&gt; a class diagram generator for Rails. Railroad has the ModelsDiagram class that gather the information we need and then uses the DiagramGraph class to generate a &lt;em&gt;dot&lt;/em&gt; format file that in turn is used to generate .svg or .png of the diagram. We are not interested in the dot generation, but will just &amp;#8216;adapt&amp;#8217; the to_dot method to get the xml we need. So I simply reopened the class and created a new &lt;i&gt;to_dot&lt;/i&gt; method as follows:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# http://chadfowler.com/2007/8/3/enumerable-injecting&lt;/span&gt;
&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;Enumerable&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;injecting&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;inject&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="keyword"&gt;yield&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;);&lt;/span&gt; &lt;span class="ident"&gt;k&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;DiagramGraph&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;to_dot&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;definition&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_xml&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:root&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;active_records&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:dasherize&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;#Let organize the data in a way closer to the xml we want to generate.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;definition&lt;/span&gt;
    &lt;span class="ident"&gt;active_records&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{}&lt;/span&gt;
    &lt;span class="attribute"&gt;@nodes&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;node&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; 
      &lt;span class="ident"&gt;attributes&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;node&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;injecting&lt;/span&gt;&lt;span class="punct"&gt;({})&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;accumulator&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; :&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;);&lt;/span&gt; &lt;span class="ident"&gt;accumulator&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;k&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
      &lt;span class="ident"&gt;class_name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;node&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
      &lt;span class="ident"&gt;active_records&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;class_name&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;class_name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:attributes&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;attributes&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:relations&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="attribute"&gt;@edges&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;edge&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; 
      &lt;span class="ident"&gt;association_type&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;edge&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
      &lt;span class="ident"&gt;from_class_name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;edge&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
      &lt;span class="ident"&gt;to_class_name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;edge&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
      &lt;span class="ident"&gt;active_records&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;from_class_name&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="symbol"&gt;:relations&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;&lt;span class="ident"&gt;association_type&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_sym&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;to_class_name&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;active_records&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;  

&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The &lt;em&gt;definition&lt;/em&gt; method generates a hash map with the information of the model. The &lt;em&gt;to_xml&lt;/em&gt; is all that is needed to get an &lt;a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/source/sports_models.xml.txt"&gt;xml version&lt;/a&gt; of the data that the map contains.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;definition&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_xml&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:root&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;active_records&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:dasherize&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;Dynamically Generate a Flex UI&lt;/h1&gt;

	&lt;p&gt;Let looks at the model.&lt;/p&gt;


&lt;pre&gt;
Player has_many Sponsor
Coach has_many Sponsor
Team has_one Coach
           has_many Player
Sponsor has nobody!
&lt;/pre&gt;

	&lt;p&gt;The UI generation should be lot smarter and configurable. For now I have taken the approach to create one view for each model. This view shows all the records in a data grid and the detail of the selected record in a form view. All associations of the record are represented by a Tab Navigator. You will notice that this is not very practical for the Typo datamodel. We should have main ActiveRecords that are entry points to the application.  Also the depth of the active record view is one association down but could be driven by definition i.e. Team =&amp;gt; Coach =&amp;gt; Sponsor, similar to the :include option of the find methods. We should be able to flatten a &amp;#8220;to one&amp;#8221; relation and have all the attributes of the association in the same view than the source ActiveRecord.&lt;/p&gt;


	&lt;p&gt;You can &lt;a href="http://nouvelles-solutions.com/onrails/flexscaffolding/FlexScaffolding"&gt;run the application&lt;/a&gt; and &lt;a href="http://nouvelles-solutions.com/onrails/flexscaffolding/srcview/index.html"&gt;view the source&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The main application, FlexScaffolding, adds dynamically a ActiveRecordsView for each ActiveRecord in the model to the Tab navigator. That&amp;#8217;s too many tabs for the Typo model&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;    private function generateView():void {
          for each (var activeRecord:XML in definition.children()) {
               var arView:ActiveRecordsView = new ActiveRecordsView();
               arView.definition = activeRecord;
               mainView.addChild(arView);
          }        
    }       &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The ActiveRecordsView.mxml does the main work of generating the UI. It&amp;#8217;s not very big (66 lines), but is also limited for now. I let you check out the source code if you a curious. Next on the list is to map too more data types (ie a &amp;#8220;text&amp;#8221; ActiveRecord attribute should be mapped to a TextArea, date and datetime should be support). I need to add configuration options where the defaults can be overridden. I need to create a Rails controller that uses the same  xml model to expose the data to the view. There shouldn&amp;#8217;t be the need to hand code RESTFul controllers. Or maybe the UI should be build from the routes&amp;#8230;&lt;/p&gt;


	&lt;p&gt;That&amp;#8217;s all for now. Enjoy!
Daniel Wanja&lt;/p&gt;</description>
      <pubDate>Sun, 05 Aug 2007 04:31:57 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:883060a9-9a41-40a6-99df-75db76139344</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2007/08/05/flex-dynamic-scaffolding-for-ruby-on-rails</link>
      <category>Ruby On Rails</category>
      <category>Playground</category>
      <category>Flex</category>
    </item>
  </channel>
</rss>
