RealityForge.org http://www.realityforge.org/ en-us 40 A little short for a storm trooper Testing Helpers in Rails <p>It can be useful at times to unit test helpers to make sure they generate correct html. It is not obvious how to do this at first. So far I have been testing my helper by defining a class &#8220;MyClass&#8221; at the top of my unit test and including all the appropriate modules. I also need to define a url_for method if I ever want to test helpers that generate links.</p> <p>The code follows (Replace MyHelper with your appropriate helper class);</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">MyClass</span> <span class="ident">include</span> <span class="constant">ERB</span><span class="punct">::</span><span class="constant">Util</span> <span class="ident">include</span> <span class="constant">ActionView</span><span class="punct">::</span><span class="constant">Helpers</span><span class="punct">::</span><span class="constant">TagHelper</span> <span class="ident">include</span> <span class="constant">ActionView</span><span class="punct">::</span><span class="constant">Helpers</span><span class="punct">::</span><span class="constant">UrlHelper</span> <span class="ident">include</span> <span class="constant">MyHelper</span> <span class="keyword">def </span><span class="method">url_for</span><span class="punct">(</span><span class="ident">options</span><span class="punct">)</span> <span class="constant">ActionController</span><span class="punct">::</span><span class="constant">Routing</span><span class="punct">::</span><span class="constant">Routes</span><span class="punct">.</span><span class="ident">reload</span> <span class="keyword">if</span> <span class="constant">ActionController</span><span class="punct">::</span><span class="constant">Routing</span><span class="punct">::</span><span class="constant">Routes</span><span class="punct">.</span><span class="ident">empty?</span> <span class="ident">generated_path</span><span class="punct">,</span> <span class="ident">extra_keys</span> <span class="punct">=</span> <span class="constant">ActionController</span><span class="punct">::</span><span class="constant">Routing</span><span class="punct">::</span><span class="constant">Routes</span><span class="punct">.</span><span class="ident">generate_extras</span><span class="punct">(</span><span class="ident">options</span><span class="punct">,</span> <span class="punct">{})</span> <span class="ident">generated_path</span> <span class="keyword">end</span> <span class="keyword">end</span></code></pre></div> <p>Then in my tests I do something like;</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">def </span><span class="method">test_revision_link</span> <span class="ident">assert_equal</span><span class="punct">(</span> <span class="punct">&quot;</span><span class="string">&lt;a href=<span class="escape">\&quot;</span>http://svn.sourceforge.net/viewvc/jikesrvm?view=rev&amp;amp;revision=22<span class="escape">\&quot;</span>&gt;22&lt;/a&gt;</span><span class="punct">&quot;,</span> <span class="constant">MyClass</span><span class="punct">.</span><span class="ident">new</span><span class="punct">.</span><span class="ident">revision_link</span><span class="punct">(</span><span class="number">22</span><span class="punct">))</span> <span class="keyword">end</span></code></pre></div> <p>Seems easy enough to do in retrospect but things usually do.</p> Thu, 14 Jun 2007 00:01:00 +1000 urn:uuid:877a7994-e03f-4c59-b776-02299c1da8c2 Peter Donald http://www.realityforge.org/articles/2007/06/14/testing-helpers-in-rails Rails http://www.realityforge.org/articles/trackback/74 Enhanced Rails Plugin to Validate (X)HTML and CSS <p>It feels like forever ago that I was last working with ruby on rails. But I am back hacking away at a few rails and I slowly getting more familiarity with ruby itself rather than just using it as part of the rails platform.</p> <p>Something I have wanted to do for a long time is automagically validate content such as (X)HTML, <span class="caps">CSS</span>, atom feeds etc that is generated by the web application. A while ago I put together the <a href="http://www.realityforge.org/articles/2006/03/15/rails-plugin-to-validate-x-html-and-css">assert-valid-asset</a> plugin that allowed you to assert (in functional tests) that the content generated is valid. However you still had to explicitly call the assert.</p> <p>So recently I enhanced the plugin so that it can automatically validate generated content when configured to do so. To configure auto validation you need to set a class variable in Test::Unit::TestCase via code such as;</p> <div class="typocode"><pre><code class="typocode_ruby "> <span class="keyword">class </span><span class="class">Test::Unit::TestCase</span> <span class="constant">self</span><span class="punct">.</span><span class="ident">auto_validate</span> <span class="punct">=</span> <span class="constant">true</span> <span class="keyword">end</span></code></pre></div> <p>Then anytime content is generated in tests (such as via get and post methods) it will check the mime type of the content. If the content has a mime type of &#8216;text/html&#8217; or &#8216;text/xhtml&#8217; it will pass it to the &#8216;assert_valid_markup&#8217; method. If the content is &#8216;text/css&#8217; then it will be validated by the &#8216;assert_valid_css&#8217; method.</p> <p>Of course you may have tests that generate invalid (X)HTML or <span class="caps">CSS</span> (to work with specific unnamed browsers) and you may want to exclude these tests from the automatic content validation. This can be done by adding the test symbol to the exclude list or alternatively by adding the desired test symbols to an include list. Both of the following examples have identical behavior;</p> Example 1: <div class="typocode"><pre><code class="typocode_ruby "> <span class="keyword">class </span><span class="class">FooControllerTest</span> <span class="punct">&lt;</span> <span class="constant">Test</span><span class="punct">::</span><span class="constant">Unit</span><span class="punct">::</span><span class="constant">TestCase</span> <span class="punct">...</span> <span class="constant">self</span><span class="punct">.</span><span class="ident">auto_validate_excludes</span> <span class="punct">=</span> <span class="punct">[</span><span class="symbol">:test_foo</span><span class="punct">,</span><span class="symbol">:test_bar</span><span class="punct">]</span> <span class="keyword">def </span><span class="method">test_foo</span><span class="punct">;</span> <span class="punct">...</span> <span class="punct">;</span> <span class="keyword">end</span> <span class="keyword">def </span><span class="method">test_bar</span><span class="punct">;</span> <span class="punct">...</span> <span class="punct">;</span> <span class="keyword">end</span> <span class="keyword">def </span><span class="method">test_baz</span><span class="punct">;</span> <span class="punct">...</span> <span class="punct">;</span> <span class="keyword">end</span> <span class="keyword">end</span></code></pre></div> Example 2: <div class="typocode"><pre><code class="typocode_ruby "> <span class="keyword">class </span><span class="class">FooControllerTest</span> <span class="punct">&lt;</span> <span class="constant">Test</span><span class="punct">::</span><span class="constant">Unit</span><span class="punct">::</span><span class="constant">TestCase</span> <span class="punct">...</span> <span class="constant">self</span><span class="punct">.</span><span class="ident">auto_validate_includes</span> <span class="punct">=</span> <span class="punct">[</span><span class="symbol">:test_baz</span><span class="punct">]</span> <span class="keyword">def </span><span class="method">test_foo</span><span class="punct">;</span> <span class="punct">...</span> <span class="punct">;</span> <span class="keyword">end</span> <span class="keyword">def </span><span class="method">test_bar</span><span class="punct">;</span> <span class="punct">...</span> <span class="punct">;</span> <span class="keyword">end</span> <span class="keyword">def </span><span class="method">test_baz</span><span class="punct">;</span> <span class="punct">...</span> <span class="punct">;</span> <span class="keyword">end</span> <span class="keyword">end</span></code></pre></div> <p>You can grab it from subversion at;</p> <p><a href="http://www.realityforge.org/svn/code/assert-valid-asset/trunk/">http://www.realityforge.org/svn/code/assert-valid-asset/trunk/</a></p> <p>The original article describing the plugin is <a href="http://www.realityforge.org/articles/2006/03/15/rails-plugin-to-validate-x-html-and-css">here</a> .</p> Wed, 09 May 2007 15:17:00 +1000 urn:uuid:b48f332b-faa7-4b92-b722-e1722432e9c6 Peter Donald http://www.realityforge.org/articles/2007/05/09/enhanced-rails-plugin-to-validate-x-html-and-css Rails http://www.realityforge.org/articles/trackback/73 Smuggle <p>I needed to mirror some galleries from one <a href="http://www.smugmug.com/">smugmug</a> <a href="http://bluemeanie.smugmug.com/">account</a> to <a href="http://lumc.smugmug.com/">another</a>. I thought about doing it manually but that idea seemed like way too much work.</p> <p>I found a python <a href="http://www.dgrin.com/showthread.php?t=3853">script</a> by rutt that did a little bit of what I wanted and went to work hacking. This resulted in <a href="http://www.realityforge.org/svn/code/smuggle/trunk/smuggle.py">smuggle.py</a> that may be useful if you ever have to programatically interact with the smugmug APIs. It will probably evolve as my needs change and as I actually start to learn python.</p> <p>The source is available from subversion. Enjoy!</p> <p>svn co <a href="http://www.realityforge.org/svn/code/smuggle/trunk/">http://www.realityforge.org/svn/code/smuggle/trunk/</a> smuggle</p> Tue, 14 Nov 2006 12:56:00 +1100 urn:uuid:a6475e9f-4152-44f5-a831-51a50e31b55a Peter Donald http://www.realityforge.org/articles/2006/11/14/smuggle http://www.realityforge.org/articles/trackback/62 Moving from Eyelook to Smugmug <p>I needed to host photos from a recent trip to New Zealand. I started modifying <a href="http://www.realityforge.org/articles/2006/04/21/eyelook-rails-photo-gallery">eyelook</a> to make it easier to do what I wanted such as geocoding, bulk upload, hierarchial grouping, different sizes, different layouts, themes etc. It was taking a bit of time so I decided to look around at existing services but none of them suited my needs.</p> <p>Then I found <a href="http://www.smugmug.com/">SmugMug</a> and I was hooked. This is the best photo-sharing service I have seen. It seems to be aimed at professional photographers &#8211; there is no free version but you get what you pay for. It is far from perfect but there is no way I would consider anything else at this stage.</p> <p>Luckily it has a referral system that gets you $5 off your first year if you indicate an account that got you onto the system so I got mine a little cheaper. I also helped out the friend that referred me by making it a little cheaper for them next year. If anyone wants to get same deal, it&#8217;s simple: enter my email address ( peter at realityforge dot org ) or my coupon ( EqCTz7hz7wkW2 ) in the &#8216;Referred by&#8217; field on the signup form and you get $5 off.</p> <p>Best photo sharing service yet!</p> Mon, 03 Jul 2006 15:33:00 +1000 urn:uuid:529c40a4-745d-4737-821e-c38cb20aface Peter Donald http://www.realityforge.org/articles/2006/07/03/moving-from-eyelook-to-smugmug http://www.realityforge.org/articles/trackback/61 Eyelook: Rails photo gallery <p>Eyelook is a photo gallery I created over a weekend when I was home sick. It is amazing how productive rails can make you because within 8 hours I had the code in place and had set it up on my personal web server.</p> <p>Very little of that time was spent coding &#8211; most of it was spent working on re-arranging the xhtml+css or figuring out how to go about <a href="http://www.realityforge.org/articles/2006/04/06/loading-binary-data-into-rails-fixtures">Loading Binary Data into Rails Fixtures.</a></p> <p>Every eyelook application has a set of users who have a list of albums with pictures. The image data is stored in the database and cached on the filesystem on demand. This way a backup of the database backs up the complete system.</p> <p>An example of users page that lists galleries is</p> <p><a href="/files/album_list.jpg"><img src="http://www.realityforge.org/files/album_list_small.jpg" alt="" /></a></p> <p>You can select one of these galleries and it will bring up a list of images such as</p> <p><a href="/files/photo_list.jpg"><img src="http://www.realityforge.org/files/photo_list_small.jpg" alt="" /></a></p> <p>From there you can either download the original or can view a larger lightbox style image</p> <p><a href="/files/lightbox.jpg"><img src="http://www.realityforge.org/files/lightbox_small.jpg" alt="" /></a></p> <p>The admin section is not as sexy but it is functional.</p> <p>You can grab the source from subversion via the following command. Read the <span class="caps">README</span>.txt for installation instructions.</p> <p>svn co <a href="http://www.realityforge.org/svn/code/eyelook/trunk">http://www.realityforge.org/svn/code/eyelook/trunk</a> eyelook</p> Fri, 21 Apr 2006 14:55:00 +1000 urn:uuid:de452e21-b289-4e8c-923d-800d94ef5ee2 Peter Donald http://www.realityforge.org/articles/2006/04/21/eyelook-rails-photo-gallery Rails http://www.realityforge.org/articles/trackback/50 Loading Binary Data into Rails Fixtures <p>Loading image data into fixtures was a chore until recently as I had been using separate rake tasks to do the job. The following code demonstrates how easy it is to load binary data such as images into the fixtures via standard mechanisms. It loads some image data from within the <code>$RAILS_ROOT/test/fixtures/</code> directory and puts it in database.</p> <div class="typocode"><pre><code class="typocode_yml ">&lt;% def fixture_data(name) render_binary(&quot;#{RAILS_ROOT}/test/fixtures/#{name}&quot;) end def render_binary(filename) data = File.open(filename,'rb').read &quot;!binary | #{[data].pack('m').gsub(/\n/,&quot;\n &quot;)}\n&quot; end %&gt; picture_data_1: id: 1 picture_id: 1 content_type: 'image/jpg' data: &lt;%= fixture_data(&quot;picture_data_1.jpg&quot;) %&gt; picture_data_2: id: 2 picture_id: 2 content_type: 'image/gif' data: &lt;%= fixture_data(&quot;picture_data_2.gif&quot;) %&gt;</code></pre></div> <p>If you do not use two spaces as your indent then you will need to alter the line in <code>render_binary(filename)</code> that replaces newline so that every newline is replaced with two indents.</p> <p>Easy peasy!</p> <p><b>Update on 16th April 2006</b></p> <p>It turns out that it was not as easy peasy under postgres as the driver did not know it had to escape the data as binary as fixtures don&#8217;t actually load the column type. The simplest hack around it is to add in the following bit of code somewhere that just patches the driver if a 0 is in the data. This may not always work but it works with my test data so that is good enough for me at the moment.</p> <div class="typocode"><pre><code class="typocode_default ">class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter &lt; ActiveRecord::ConnectionAdapters::AbstractAdapter def quote(value, column = nil) if (value.kind_of?(String) &amp;&amp; column &amp;&amp; column.type == :binary) || (value.kind_of?(String) &amp;&amp; value.include?(0)) &quot;'#{escape_bytea(value)}'&quot; else super end end end</code></pre></div> Thu, 06 Apr 2006 07:50:00 +1000 urn:uuid:83791ba6-2051-45ac-9377-76356d4a7717 Peter Donald http://www.realityforge.org/articles/2006/04/06/loading-binary-data-into-rails-fixtures Rails rails binary fixture image http://www.realityforge.org/articles/trackback/44 Rails Plugin to Help Debug Views <p>The debug_view_helper plugin was developed to make it easy to add debug information into your views. It was derived from techniques described in <a href="http://wiki.rubyonrails.com/rails/pages/HowtoDebugViews">HowtoDebugViews</a> and it makes it possible to expose the followng following debug data;</p> <ul> <li>Request Parameters</li> <li>Session Variables</li> <li>Flash Variables</li> <li>Assigned Template Variables</li> </ul> <p>Typically you add code such as the following to the bottom of your layout that exposes the debug button in development mode.</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="punct">&lt;%</span> <span class="keyword">if</span> <span class="constant">RAILS_ENV</span> <span class="punct">==</span> <span class="punct">'</span><span class="string">development</span><span class="punct">'</span> <span class="punct">%&gt;</span><span class="string"> &lt;center</span><span class="punct">&gt;</span> <span class="punct">&lt;</span><span class="ident">button</span> <span class="ident">onclick</span><span class="punct">=&quot;</span><span class="string">show_debug_popup(); return false;</span><span class="punct">&quot;&gt;</span> <span class="constant">Show</span> <span class="ident">debug</span> <span class="ident">popup</span> <span class="punct">&lt;/</span><span class="regex">button&gt; &lt;</span><span class="punct">/</span><span class="ident">center</span><span class="punct">&gt;</span> <span class="punct">&lt;%=</span><span class="string"> debug_popup %&gt; &lt;% end %&gt;</span></code></pre></div> <p>You can grab the plugin from subversion at;</p> <p><a href="http://www.realityforge.org/svn/code/debug-view-helper/trunk/">http://www.realityforge.org/svn/code/debug-view-helper/trunk/</a></p> <p><b>Update:</b> Added the ability to add inline debug information via the following. Suggestion by John Dell.</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="punct">&lt;%</span> <span class="keyword">if</span> <span class="constant">RAILS_ENV</span> <span class="punct">==</span> <span class="punct">'</span><span class="string">development</span><span class="punct">'</span> <span class="punct">%&gt;</span><span class="string"> &lt;%= debug_inline %</span><span class="punct">&gt;</span> <span class="punct">&lt;%</span> <span class="keyword">end</span> <span class="punct">%&gt;</span><span class="string"></span></code></pre></div> Mon, 20 Mar 2006 14:02:00 +1100 urn:uuid:3b08aded-4f0c-4955-9cdf-a39457c1a9aa Peter Donald http://www.realityforge.org/articles/2006/03/20/rails-plugin-to-help-debug-views Rails rails debug http://www.realityforge.org/articles/trackback/40 Rails Plugin to Validate (X)HTML and CSS <p>Here is an enahnced version of <a href="http://scottraymond.net">Scott Raymond&#8217;s</a> <a href="http://redgreenblu.com/svn/projects/assert_valid_markup/">assert_valid_markup</a> plugin that I use in my projects. Below are the directions for use;</p> <h3>HowTo Validate (X)HTML</h3> <div class="typocode"><pre><code class="typocode_ruby "><span class="comment"># Calling the assertion with no parameters validates </span> <span class="comment"># whatever is in @request.body, which is automatically </span> <span class="comment"># set by the existing get/post/etc helpers. For example:</span> <span class="keyword">class </span><span class="class">FooControllerTest</span> <span class="punct">&lt;</span> <span class="constant">Test</span><span class="punct">::</span><span class="constant">Unit</span><span class="punct">::</span><span class="constant">TestCase</span> <span class="keyword">def </span><span class="method">test_bar_markup</span> <span class="ident">get</span> <span class="symbol">:bar</span> <span class="ident">assert_valid_markup</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="comment"># Add a string parameter to the assertion to validate </span> <span class="comment"># any random fragment. For example:</span> <span class="keyword">class </span><span class="class">FooControllerTest</span> <span class="punct">&lt;</span> <span class="constant">Test</span><span class="punct">::</span><span class="constant">Unit</span><span class="punct">::</span><span class="constant">TestCase</span> <span class="keyword">def </span><span class="method">test_bar_markup</span> <span class="ident">assert_valid_markup</span> <span class="punct">&quot;</span><span class="string">&lt;div&gt;Hello, world.&lt;/div&gt;</span><span class="punct">&quot;</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="comment"># For the ultimate in convenience, use the class-level</span> <span class="comment"># method to validate a number of actions in one line. </span> <span class="keyword">class </span><span class="class">FooControllerTest</span> <span class="punct">&lt;</span> <span class="constant">Test</span><span class="punct">::</span><span class="constant">Unit</span><span class="punct">::</span><span class="constant">TestCase</span> <span class="ident">assert_valid_markup</span> <span class="symbol">:bar</span><span class="punct">,</span> <span class="symbol">:baz</span><span class="punct">,</span> <span class="symbol">:qux</span> <span class="keyword">end</span></code></pre></div> <h3>HowTo Validate <span class="caps">CSS</span></h3> <div class="typocode"><pre><code class="typocode_ruby "><span class="comment"># Pass a string parameter to the assertion to validate </span> <span class="comment"># a css fragment. For example:</span> <span class="keyword">class </span><span class="class">FooControllerTest</span> <span class="punct">&lt;</span> <span class="constant">Test</span><span class="punct">::</span><span class="constant">Unit</span><span class="punct">::</span><span class="constant">TestCase</span> <span class="keyword">def </span><span class="method">test_bar_css</span> <span class="ident">filename</span> <span class="punct">=</span> <span class="punct">&quot;</span><span class="string"><span class="expr">#{RAILS_ROOT}</span>/public/stylesheets/bar.css</span><span class="punct">&quot;</span> <span class="ident">assert_valid_css</span><span class="punct">(</span><span class="constant">File</span><span class="punct">.</span><span class="ident">open</span><span class="punct">(</span><span class="ident">filename</span> <span class="punct">,'</span><span class="string">rb</span><span class="punct">').</span><span class="ident">read</span><span class="punct">)</span> <span class="keyword">end</span> <span class="keyword">end</span> <span class="comment"># For the ultimate in convenience, use the class-level</span> <span class="comment"># method to validate a bunch of css files in one line.</span> <span class="comment"># Assumes that the CSS files are relative to </span> <span class="comment"># $RAILS_ROOT/public/stylesheets/ and end with '.css'. </span> <span class="comment"># The following example validates </span> <span class="comment"># $RAILS_ROOT/public/stylesheets/layout.css, </span> <span class="comment"># $RAILS_ROOT/public/stylesheets/standard.css and </span> <span class="comment"># $RAILS_ROOT/public/stylesheets/theme.css</span> <span class="keyword">class </span><span class="class">FooControllerTest</span> <span class="punct">&lt;</span> <span class="constant">Test</span><span class="punct">::</span><span class="constant">Unit</span><span class="punct">::</span><span class="constant">TestCase</span> <span class="ident">assert_valid_css_files</span> <span class="punct">'</span><span class="string">layout</span><span class="punct">',</span> <span class="punct">'</span><span class="string">standard</span><span class="punct">',</span> <span class="punct">'</span><span class="string">theme</span><span class="punct">'</span> <span class="keyword">end</span></code></pre></div> <p>Most of the credit for this plugin goes to Scott for the initial idea! The modifications that I made include;</p> <ul> <li>Validation of <span class="caps">CSS</span> files.</li> <li>Caching of fragments occurs in <code>$RAILS_ROOT/tmp</code> according to the name of the test class + test method. This avoids filling up the system temp folder with expired cache files.</li> <li>Ability to turn off validation by setting the &#8220;NONET&#8221; environment variable to &#8220;true&#8221;.</li> </ul> <p>You can grab it from subversion at;</p> <p><a href="http://www.realityforge.org/svn/code/assert-valid-asset/trunk/">http://www.realityforge.org/svn/code/assert-valid-asset/trunk/</a></p> <h4>Update 12th of May, 2008</h4> <p>Steve Sloan has also added a Git repo for the code which you can grab from:</p> <p><a href="http://github.com/CodeMonkeySteve/assert-valid-asset/tree/master">http://github.com/CodeMonkeySteve/assert-valid-asset/tree/master</a></p> Wed, 15 Mar 2006 19:18:00 +1100 urn:uuid:e93d2591-c8bb-4fe9-993e-f958140f5ad6 Peter Donald http://www.realityforge.org/articles/2006/03/15/rails-plugin-to-validate-x-html-and-css Rails rails plugin css html validate http://www.realityforge.org/articles/trackback/37 Meta-Programming in Java <p>I have been looking over my old code repository and I came across <acronym title="Generated Entity Layer">GEL</acronym>. <span class="caps">GEL</span> was a toolkit that allowed me to define entities and events for <a href="http://en.wikipedia.org/wiki/High_Level_Architecture" title="High Level Architecture">HLA</a> using an <span class="caps">XML</span> data definition language.</p> <p>The <acronym title="High Level Architecture">HLA</acronym> is a family of specifications developed to promote intereoperability and reuse of simulation assets. Unfortunately there is a significant development effort associated with construction of a <span class="caps">HLA</span>-compliant federation. Less than 2% of the 2500+ lines of code in the &#8220;Hello World&#8221; sample <span class="caps">HLA</span> application relates to simulation logic. The integration code is a significant cost and there is often a high-level of coupling between the simulation code and the integration code.</p> <p><acronym title="Generated Entity Layer">GEL</acronym> was created to simplify <acronym title="High Level Architecture">HLA</acronym> developers task by generating all the integration code from a simulation model defined in an <span class="caps">XML</span> document. The <span class="caps">HLA</span> developer had the sole responsibility of writing the simulation/logic code. Think of <span class="caps">GEL</span> as a a poor-mans <a href="http://en.wikipedia.org/wiki/Model_Driven_Architecture">MDA</a> (I even planned to have a set of separate generators that would allow the simulation objects to be hosted in a Quake3 game). This approach rocks as you only need to fix and update the code in one place (the generator) and you are far more productive at the higher level of abstraction.</p> <p>Each simulation object in the <span class="caps">GEL XML</span> document resulted in the generation of several Java classes by <a href="http://jakarta.apache.org/velocity/">velocity</a>.</p> <ul> <li>a <code>Model</code> class for holding data of a specific instance.</li> <li>a <code>ModelListener</code> class that receives events relating to a <code>Model</code> instance.</li> <li>a <code>HLAPeer</code> class that reflects the data in a <code>Model</code> instance into the <span class="caps">HLA</span> runtime.</li> <li>a <code>PersistPeer</code> class that persists the data in a <code>Model</code> instance.</li> <li>a number of <a href="http://www.martinfowler.com/ap2/valueObject.html">Value Object</a> classes to represent various events</li> <li>etc&#8230;</li> </ul> <p>I had long believed in having a single high-level model of the domain objects and generating. Prior to <span class="caps">XML I</span> had used <span class="caps">SGML</span>, INI and custom formats to represent the model. On a number of occasions I have attempted to move the model data into the code to make it easier to keep up to date. I have used C/C++&#8217;s macro expansions, XDoclet-like processors and Java 1.5 Annotations at various times.</p> <p>Six months using <a href="http://www.rubyonrails.org/">Ruby On Rails&#8217;</a> has changed my world view. The model classes are very close to the level at which I would create my domain model. The good thing about ruby is that you can always add more language constructs to make sure the code matches your domain model. (I know Lisp-ers have always raved about this but I have never been able to use lisp in a commercial environment). Things like <a href="http://api.rubyonrails.com/classes/ActiveRecord/Acts/List/ClassMethods.html">acts_as_list</a> to order your domain objects, <a href="http://ar-versioned.rubyforge.org/">acts_as_versioned</a> to version your domain objects or <a href="http://www.railtie.net/articles/2006/02/05/rails-acts_as_threaded-plugin">acts_as_threaded</a> to have a threaded tree representation radically simplify the representation of domain objects.</p> <p>I have been thinking about how I would do this in Java but most of the neat stuff just does not seem possible without the introduction of a <a href="http://en.wikipedia.org/wiki/Meta-object_protocol">Meta-object Protocol</a> or some sort of load-time class file modification.</p> <p>Consider a simple simulation object. In ruby I would represent it via</p> <div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">Kettle</span> <span class="punct">&lt;</span> <span class="constant">Model</span><span class="punct">::</span><span class="constant">Base</span> <span class="ident">shared_attr</span> <span class="symbol">:temperature</span><span class="punct">,</span> <span class="symbol">:float</span><span class="punct">,</span> <span class="symbol">:resolution</span> <span class="punct">=&gt;</span> <span class="number">1.0</span><span class="punct">,</span> <span class="symbol">:accuracy</span> <span class="punct">=&gt;</span> <span class="number">1.0</span> <span class="keyword">end</span></code></pre></div> <p>In java there is no simple equivalent. I could just define the model in a class like below. However this would probably need to be instrumented during loading so that the runtime could monitor changes to the shared attribute.</p> <div class="typocode"><pre><code class="typocode_default ">public class Kettle extends BaseModel { @SharedAttribute(resolution = 1.0, accuracy = 1.0 ) private float m_temperature; public float getTemperature() { return m_temperature; } public void setTemperature(final float temperature) { m_temperature = temperature; } }</code></pre></div> <p>Instrumentation in whatever form it takes is fairly complex even if you use something like AspectJ that is perfect for this scenario. Much more complex than writing the equivalent acts_as_* plugin.</p> <p>The above only works when the instrumentation code does not need to add any methods. However if you want a simulation object to support shared events you need to be able to subscribe, unsubscribe and generate these events which means you need the same boilerplate code repeated over and over.</p> <p>I can not think of anyway to do this in java so I guess it is back to generating the Java classes from a central model file. Pity I think I liked the ruby way better.</p> Thu, 09 Mar 2006 16:33:00 +1100 urn:uuid:46b9155f-329f-4367-b264-7956dfc0babe Peter Donald http://www.realityforge.org/articles/2006/03/09/meta-programming-in-java Java java ruby meta programming HLA MDA http://www.realityforge.org/articles/trackback/32 Distributed Case-Based Reasoning using Java <p>Over the next few months I will be investing some time into a research project focusing on distributed <a href="http://en.wikipedia.org/wiki/Case-based_reasoning">case-base reasoning</a>. The idea is to establish an <a href="http://en.wikipedia.org/wiki/Mobile_ad-hoc_network">ad-hoc network</a> of nodes that each have a separate case-base. When a node attempts to find a solution to a problem it will query both it&#8217;s local case-base and case-bases of connected nodes to determine the solution.</p> <p>The exact algorithms that the solver uses to select nodes to query will have a significant impact on the speed and accuracy with which a solution can be found. The maintainece of the distributed cases-bases via case addition or removal will also need to be addressed in our research.</p> <p>I will be working on an existing codebase but I have been looking around to see if I can find any free or opensource java case-base reasoning software. Something that I can tack a distribution layer on top of but I have been unable to find any products that are not commercial software and/or under highly restrictive licenses. I wonder if this is an area that just does not appeal to <span class="caps">FOSS</span> developers?</p> Wed, 08 Mar 2006 13:05:00 +1100 urn:uuid:2c386742-324f-49eb-a7d5-dd038f523132 Peter Donald http://www.realityforge.org/articles/2006/03/08/distributed-case-based-reasoning-using-java Java cbr case base reasoning java distributed http://www.realityforge.org/articles/trackback/31