<?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: Flex Dynamic  Scaffolding for Ruby on Rails.</title>
    <link>http://onrails.org/articles/2007/08/05/flex-dynamic-scaffolding-for-ruby-on-rails</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Ruby On Rails and related matters.</description>
    <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>
    <item>
      <title>"Flex Dynamic  Scaffolding for Ruby on Rails." by george</title>
      <description>&lt;p&gt;fsvb&lt;/p&gt;</description>
      <pubDate>Fri, 30 Nov 2007 23:49:02 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:e2c71cd7-c407-49b6-ace5-45d3021e340e</guid>
      <link>http://onrails.org/articles/2007/08/05/flex-dynamic-scaffolding-for-ruby-on-rails#comment-2939</link>
    </item>
    <item>
      <title>"Flex Dynamic  Scaffolding for Ruby on Rails." by Doug Hays</title>
      <description>&lt;p&gt;Daniel,
 This is great stuff.  As we discussed at the AIR Bus Tour stop back in July, I am taking the exact approach you are trying to avoid by building a generator that creates the Flex app and the necessary Cairngorm, WebORB and Flex components to have a functioning front-end for a Rails app.&lt;/p&gt;


	&lt;p&gt;Mine is much more brute-force, lean-on-the-strong-typing than your approach&amp;#8230; but it definitely feels like a diversion from some of the beauty of Rails.&lt;/p&gt;


	&lt;p&gt;I hope you continue to develop your ideas on this front!&lt;/p&gt;


	&lt;p&gt;Good luck,
Doug.&lt;/p&gt;</description>
      <pubDate>Sun, 05 Aug 2007 20:33:02 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:de54fd1d-2e72-46fc-8f33-beea76cbb591</guid>
      <link>http://onrails.org/articles/2007/08/05/flex-dynamic-scaffolding-for-ruby-on-rails#comment-2490</link>
    </item>
  </channel>
</rss>
