<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>usefulfor.com/ruby</title>
	<atom:link href="http://usefulfor.com/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://usefulfor.com/ruby</link>
	<description>ruby goodness for your daily needs</description>
	<pubDate>Thu, 09 Apr 2009 10:50:25 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>How to create a dradis export plugin?</title>
		<link>http://usefulfor.com/ruby/2009/03/27/how-to-create-a-dradis-export-plugin/</link>
		<comments>http://usefulfor.com/ruby/2009/03/27/how-to-create-a-dradis-export-plugin/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 01:04:47 +0000</pubDate>
		<dc:creator>etd</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[dradis]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=87</guid>
		<description><![CDATA[Although we presented some of this concepts already in dradis reporting: quick &#38; neat word export, here is the step by step guide to get an export plugin recognised by the dradis framework and ready to use!
Update (2009-04-09): Checkout the new import/export plugin generators at dradis community forums.

Generate the plugin skeleton

$ ./script/generate plugin my_export
  [...]]]></description>
			<content:encoded><![CDATA[<p>Although we presented some of this concepts already in <a href="http://usefulfor.com/ruby/2009/02/15/dradis-reporting-quick-neat-word-export/">dradis reporting: quick &amp; neat word export</a>, here is the step by step guide to get an export plugin recognised by the <a href="http://dradisframework.org/">dradis framework</a> and ready to use!</p>
<p><strong>Update (2009-04-09)</strong>: Checkout the new import/export plugin generators at <a href="http://dradisframework.org/community/index.php?topic=7.msg9">dradis community forums</a>.<br />
<span id="more-87"></span></p>
<h3>Generate the plugin skeleton</h3>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ .<span style="color: #000000; font-weight: bold;">/</span>script<span style="color: #000000; font-weight: bold;">/</span>generate plugin my_export
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>lib
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>tasks
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">test</span>
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>README
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>MIT-LICENSE
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>Rakefile
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>init.rb
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>install.rb
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>uninstall.rb
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>my_export.rb
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span>tasks<span style="color: #000000; font-weight: bold;">/</span>my_export_tasks.rake
      create  vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>my_export<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">test</span><span style="color: #000000; font-weight: bold;">/</span>my_export_test.rb</pre></div></div>

<p>Edit <code>vendor/plugins/my_export/init.rb</code> to include the main plugin library:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Include hook code here</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'my_export'</span></pre></div></div>

<p>In the main library (<code>vendor/plugins/my_export/lib/my_export.rb</code>), define a module (choose a name, ideally it should match the plugin name):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># MyExport</span>
<span style="color:#9966CC; font-weight:bold;">module</span> MyExport
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This is all you really need to get it started. Now you have to put your code in the right place so the framework finds it (and creates an entry for you in the <strong>export</strong> menu).</p>
<h3>Hooking into the framework</h3>
<p>At the end of the day an export plugin provides a number of Rails actions. These are methods that will be invoked through the URL, for instance:-</p>
<pre>
/export/to_pdf
/export/to_xml
/export/to_excel
...
</pre>
<p>Each export plugin can define several actions. If more than one action is defined a nested submenu will be appended to the <strong>export</strong> menu with all the defined actions.</p>
<p>In order for the framework to find your actions, they have to be defined in a certain way, they have to be defined inside the <code>Actions</code> module (we are still editing the same file):-</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># MyExport</span>
<span style="color:#9966CC; font-weight:bold;">module</span> MyExport
  <span style="color:#9966CC; font-weight:bold;">module</span> Actions
    <span style="color:#008000; font-style:italic;"># first action</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> to_myformat<span style="color:#006600; font-weight:bold;">&#40;</span>params=<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#008000; font-style:italic;"># your action code goes here</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># second action</span>
    <span style="color:#008000; font-style:italic;"># [...]</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>And that&#8217;s it, nice and easy, you can define as many actions as you like in you <code>Actions</code> module.</p>
<p>Finally, in order to make everything work together you need to include your module in the main repository of export plugins (<code>Plugins::Export</code>):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># MyExport</span>
<span style="color:#9966CC; font-weight:bold;">module</span> MyExport
  <span style="color:#9966CC; font-weight:bold;">module</span> Actions
    <span style="color:#008000; font-style:italic;"># first action</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> to_myformat<span style="color:#006600; font-weight:bold;">&#40;</span>params=<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#008000; font-style:italic;"># your action code goes here</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#008000; font-style:italic;"># [...]</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Plugins
  <span style="color:#9966CC; font-weight:bold;">module</span> Export
    <span style="color:#9966CC; font-weight:bold;">include</span> MyExport
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>Remember to restart you <strong>dradis</strong> server. Your <strong>export</strong> menu should have an entry for your newly created plugin. And now is the time to be creative about what you implement!</p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/03/27/how-to-create-a-dradis-export-plugin/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Use Rails to Create a Static Site: Rake and Subversion</title>
		<link>http://usefulfor.com/ruby/2009/03/23/use-rails-to-create-a-static-site-rake-and-subversion/</link>
		<comments>http://usefulfor.com/ruby/2009/03/23/use-rails-to-create-a-static-site-rake-and-subversion/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 10:31:23 +0000</pubDate>
		<dc:creator>etd</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=86</guid>
		<description><![CDATA[We have already seen how to Use Rails to Create a Static Site. In that article we left the site running, and we recommended the use of wget to generate the static copy. Although this is good enough, with a little bit of Rake we can make deployment easier.

The final goal is to have an [...]]]></description>
			<content:encoded><![CDATA[<p>We have already seen how to <a href="http://usefulfor.com/ruby/2009/02/04/use-rails-to-create-a-static-site/">Use Rails to Create a Static Site</a>. In that article we left the site running, and we recommended the use of <code>wget</code> to generate the static copy. Although this is good enough, with a little bit of <a href="http://rake.rubyforge.org/">Rake</a> we can make deployment easier.</p>
<p><span id="more-86"></span></p>
<p>The final goal is to have an automated process to generate fresh static copy of the site and to upload it to the subversion repository. Although more advanced solutions exist (i.e. <a href="http://www.capify.org/">Capistrano</a>), I used a 22 line Rake script for <a href="http://dradisframework.org/">dradisframework.org</a>. There are two tasks:-</p>
<ul>
<li><code>prepare</code>: uses <code>wget</code> to generate a static copy of the site in the <code>./out/</code> directory.</li>
<li><code>commit</code>: commits the changes in the <code>./out/</code> directory to the subversion repository.</li>
</ul>
<p>You would only need to synchronise your web server document root with the <code>./out/</code> directory of the subversion.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">desc <span style="color:#996600;">'Prepare the static site in the ./out/ directory'</span>
task <span style="color:#ff3333; font-weight:bold;">:prepare</span>  <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">mkdir</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'out'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exist</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'out'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">chdir</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'out'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#996600;">`wget -m -nH http://localhost:3000`</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#996600;">`rsync -ruv --exclude=.svn/ --exclude=dispatch* --exclude=500.html --exclude=422.html public/ out/`</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
desc <span style="color:#996600;">'Prepare the static site and commit the changes to the svn repo.'</span>
task <span style="color:#ff3333; font-weight:bold;">:commit</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:prepare</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#008000; font-style:italic;"># Display the messages as they come, don't buffer</span>
  STDOUT.<span style="color:#9900CC;">sync</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Subversion operations</span>
  <span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;Adding the output directory (out/) to subversion... &quot;</span>
  <span style="color:#996600;">`svn add --force out`</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;done.&quot;</span>
  <span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;Commiting... &quot;</span>
  <span style="color:#996600;">`svn commit out -m &quot;New static site content #{DateTime.now().to_s}&quot;`</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;done.&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>The only little trick here is the use of <strong>rsync</strong> in line 7. We want to make sure that everything we have in the <code>./public/</code> directory will also be in the static copy of the site. This includes flash videos, demos, full-size screenshots, etc. Using the <code>--exclude</code> parameter we prevent the copy of some files that won&#8217;t be required in the production environment.</p>
<p>Every time we want to generate a fresh copy of the site and send it to the subversion repository we will only need to run:-</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">rake commit</pre></div></div>

<p>And now we are done for good, from a Rails application in our laptop to a static site in the web server in a couple of lines!</p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/03/23/use-rails-to-create-a-static-site-rake-and-subversion/feed/</wfw:commentRss>
		</item>
		<item>
		<title>dradis extensions: how they work and how to write them</title>
		<link>http://usefulfor.com/ruby/2009/02/17/dradis-extensions-how-they-work-and-how-to-write-them/</link>
		<comments>http://usefulfor.com/ruby/2009/02/17/dradis-extensions-how-they-work-and-how-to-write-them/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 23:33:24 +0000</pubDate>
		<dc:creator>siebert</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[dradis]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=84</guid>
		<description><![CDATA[Dradis is a tool used for structured information storage and sharing. Although it is applicable to various environments, it is originally aimed at information security consultants working alone or in a team. One of the great features of the application is that the client side&#8217;s functionality can be extended by what is called (quite creatively) [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://dradis.sourceforge.net">Dradis</a> is a tool used for structured information storage and sharing. Although it is applicable to various environments, it is originally aimed at information security consultants working alone or in a team. One of the great features of the application is that the client side&#8217;s functionality can be extended by what is called (quite creatively) - <em>extensions</em>.</p>
<p>In this post I&#8217;ll be looking at what an extension is, how it fits into the dradis framework and how to write your own extensions.</p>
<p>You are welcome to jump ahead to the <strong><a href="#how_to">How do I write my own extension?</a></strong> if that is the only part that you are interested in.<br />
<span id="more-84"></span></p>
<p><strong>What is an extension?</strong></p>
<p>In a nutshell - <em>A dradis extension is an addition to the collection of functions offered by the dradis client side.</em> The possibilities of what an extension can be are almost endless. From a logical perspective it will be a function that enhances the usability of the application within the context of the user.</p>
<p>Currently the functionality that is offered by an extension is triggered from the command line console on the client side. To see what are all the commands offered by your currently installed extensions type <em>help</em> in the command line console of the dradis client. You might see something similar to:</p>
<pre>List of registered commands
---------------------------
help:	shows the help of all the commands available
reload:	reload the modules from the filesystem
quit:	exits the application
add:	add elements to the project
fact:	shows a random Chuck Norris fact
encode:	Encodes a string using various differnet encoding schemes
lookup:	Basically greps a file, useful for lookup tables
decode:	Decodes a string into the specified encoding type
export:	export the knowledge base to a local file
ls:	lists entries under the directory specified as argument
import:	import external resources to dradis
</pre>
<p>Some of those commands are hard coded into the console functionality but the majority are commands offered by your installed extensions. For example the <em>fact</em> command is offered to you by the <em>chucknorris extension</em> and the <em>ls</em> command is offered by the <em>filesystem</em> extension.</p>
<p>Extensions can also communicate to other parts of the application. In the majority of cases this will be communication to the data storage. For example the add command allows you to add data to the data storage and the export command allows you to export the data storage to a local file.</p>
<p><strong>Where do extensions fit into the dradis framework?</strong></p>
<p>Extension fact list:</p>
<ul>
<li>As mentioned previously, extensions are found on the client side of the dradis framework.</li>
<li>When looking at the code they can be found in the <em>client/extensions</em> folder.</li>
<li>An extension provides one or more commands that can be called from the client command line console.</li>
<li>Executing one of these commands in the console triggers a call to a method in the extension code (Executing <em>fact</em> in the console triggers the <em>fact</em> method in the <em>chucknorris.rb</em> file).</li>
<li>The return value of the extension method is printed to the console interface (The return value of the <em>fact</em> method is a Chuck Norris fact that is printed to the console interface).</li>
<li>The extension communicates to the rest of the application through calls to <em>service providers</em> (I&#8217;ll define a service provider shortly).</li>
<li>An extension can be one of two types: <em>simple</em> or <em>namespace</em> (Definition of these will follow).</li>
</ul>
<p><a name="service_provider"></a><br />
<em>What is a service provider?</em><br />
A service provider is an interface to a certain part of the application. It can be seen as a functionality presented through an API.<br />
Lets look at an example: The dradis client side is modeled on a Model-View-Controller architecture. The extension code has access to an instance of the Controller (<em>@controller</em>). The extension does not have direct access to the Model (the Model is the access layer to the data storage). Calls to the Model is made through the data-storage service provider (<em>client/core/service_providers/data_storage.rb</em>. The data-storage service provider has a set of methods (an API) through which you can:</p>
<ul>
<li>add a node - <em>@controller.request_service(:model_add_node, &#8230;)</em></li>
<li>add a category - <em>@controller.request_service(:model_add_category, &#8230;)</em></li>
<li>get the contents of a node - <em>@controller.request_service(:model_find_node, &#8230;)</em></li>
<li>etc.</li>
</ul>
<p>Have a look in the <a href="http://dradis.nomejortu.com/rdoc/classes/Core/Providers.html"><em>client/core/service_providers</em></a> folder for all the currently available service providers.</p>
<p><em>What is a simple extension and a namespace extension?</em><br />
A <strong>simple extension</strong> provides one or more commands that are grouped only by them being members of the extension. A command of a simple extension can be the only command in the current dradis client instance to have the name of that command. It is triggered in the command line console by: <em>command parameters</em>. The <em>chucknorris</em> extension is a simple extension and offers the <em>fact</em> command. No other simple extension can have a command called fact.</p>
<p>A <strong>namespace extension</strong> places its commands in a namespace. One namespace may contain commands with the same name as simple commands or commands in other namespaces. If we want to add a fact command that gives random Bruce Schneier facts then we can create the <em>bruceschneier</em> namespace and place a <em>fact</em> command in it that will not interfere with our Chuck Norris <em>fact</em> command. Namespace commands are called from the commandline in the format: <em>namespace command parameter</em>. The <em>export</em> extension is an example of a namespace extension.</p>
<p><a name="how_to"></a><br />
<strong>How do I write my own extension?</strong></p>
<p>Let&#8217;s have a look at the basic structure of a simple extension. Following is a simplified version of the <em>chucknorris</em> extension:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Extensions
  <span style="color:#9966CC; font-weight:bold;">class</span> Chucknorris <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Extensions::Simple</span>
    <span style="color:#008000; font-style:italic;">#----------------------------------------------------- Dispatcher implementation</span>
    INFO = <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff3333; font-weight:bold;">:commands</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#996600;">'fact'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
          <span style="color:#ff3333; font-weight:bold;">:desc</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'shows a random Chuck Norris fact'</span>,
          <span style="color:#ff3333; font-weight:bold;">:syntax</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
        <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;">#----------------------------------------------------- commands implementation</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> fact<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#008000; font-style:italic;"># here we implement the magic that gets the new fact and returns it</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<ul>
<li>line 1 - To implement our extension we need to extend the <em>Extensions</em> module</li>
<li>line 2 - We define our class to inherit from the <em>Extensions::Simple</em> class</li>
<li>lines 4-11 - The <em>INFO</em> hash defines all the commands in our extension for the use of the command launcher. In the case of the example above it defines the presence of the <em>fact</em> command with its description and its syntax. In this case there is no syntax defined as the command does not take any parameters.</li>
<li>lines 14-16 - This is the method implementation of the command that was defined in the <em>INFO</em> hash.</li>
</ul>
<p>Now lets look at a slightly more complex namespace extension. The example is  the <em>add</em> extension that hosts the <em>node</em> and <em>category</em> commands. The syntax for the two command are respectively:</p>
<pre>add node  &lt;parent id&gt; &lt;label&gt;
</pre>
<p>and</p>
<pre>add category &lt;name&gt;
</pre>
<p>This is the code for the extension:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Extensions
  <span style="color:#9966CC; font-weight:bold;">class</span> Add <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Extensions::Namespace</span>
    <span style="color:#008000; font-style:italic;">#----------------------------------------------------- private methods</span>
    private
    <span style="color:#008000; font-style:italic;">#----------------------------------------------------- Dispatcher implementation</span>
    INFO = <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff3333; font-weight:bold;">:namespace</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'add'</span>,
      <span style="color:#ff3333; font-weight:bold;">:description</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'add elements to the project'</span>,
      <span style="color:#ff3333; font-weight:bold;">:commands</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#996600;">'node'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
          <span style="color:#ff3333; font-weight:bold;">:desc</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Adds a node to the node tree.'</span>,
          <span style="color:#ff3333; font-weight:bold;">:syntax</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span>
&nbsp;
          <span style="color:#006600; font-weight:bold;">&#123;</span>
            <span style="color:#ff3333; font-weight:bold;">:required</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>,
            <span style="color:#ff3333; font-weight:bold;">:label</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'parent_id'</span>,
            <span style="color:#ff3333; font-weight:bold;">:desc</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'The id of parent to the new node. Use 0 if it is to be a root node.'</span>,
            <span style="color:#ff3333; font-weight:bold;">:regexp</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>^\d<span style="color:#006600; font-weight:bold;">*</span>$<span style="color:#006600; font-weight:bold;">/</span>
          <span style="color:#006600; font-weight:bold;">&#125;</span>,
          <span style="color:#006600; font-weight:bold;">&#123;</span>
            <span style="color:#ff3333; font-weight:bold;">:required</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>,
            <span style="color:#ff3333; font-weight:bold;">:label</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'label'</span>,
            <span style="color:#ff3333; font-weight:bold;">:desc</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'The label/name of the new node.'</span>,
            <span style="color:#ff3333; font-weight:bold;">:regexp</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>^\w<span style="color:#006600; font-weight:bold;">&#91;</span>\w\s<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">*</span>$<span style="color:#006600; font-weight:bold;">/</span>
          <span style="color:#006600; font-weight:bold;">&#125;</span>
          <span style="color:#006600; font-weight:bold;">&#93;</span>
        <span style="color:#006600; font-weight:bold;">&#125;</span>,
        <span style="color:#996600;">'category'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
          <span style="color:#ff3333; font-weight:bold;">:desc</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Adds a note category.'</span>,
          <span style="color:#ff3333; font-weight:bold;">:syntax</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span>
          <span style="color:#006600; font-weight:bold;">&#123;</span>
            <span style="color:#ff3333; font-weight:bold;">:required</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>,
            <span style="color:#ff3333; font-weight:bold;">:label</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'name'</span>,
            <span style="color:#ff3333; font-weight:bold;">:desc</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'name of the new category'</span>,
            <span style="color:#ff3333; font-weight:bold;">:regexp</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>^\w<span style="color:#006600; font-weight:bold;">&#91;</span>\w\s<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">*</span>$<span style="color:#006600; font-weight:bold;">/</span>
          <span style="color:#006600; font-weight:bold;">&#125;</span>
          <span style="color:#006600; font-weight:bold;">&#93;</span>
        <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Implements the add node fucntionality. See the above for allowed parameters</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> node<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#008000; font-style:italic;"># the parent_id needs to be an integer or a nil value</span>
      args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> = args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#996600;">'0'</span> ? <span style="color:#0000FF; font-weight:bold;">nil</span> : args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_i</span>
      <span style="color:#008000; font-style:italic;"># call the service provider to add a node with the specified parameters</span>
      <span style="color:#0066ff; font-weight:bold;">@controller</span>.<span style="color:#9900CC;">request_service</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:model_add_node</span>, args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#0000FF; font-weight:bold;">nil</span>, args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#996600;">&quot;Added node: #{args[2]}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># Implements the add category fucntionality. See the above for allowed parameters</span>
    <span style="color:#9966CC; font-weight:bold;">def</span> category<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>args<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#008000; font-style:italic;"># call the service provider to add a node with the specified parameters</span>
      <span style="color:#0066ff; font-weight:bold;">@controller</span>.<span style="color:#9900CC;">request_service</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:model_add_category</span>, args<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#996600;">&quot;Added category: #{args[1]}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>I&#8217;ll highlight the important and new bits of code:</p>
<ul>
<li>line 2 - Different that in the previous example we define this extension to inherit from the <em>Extensions::Namespace</em> class</li>
<li>line 7 - In the <em>INFO</em> hash we define the namespace <em>add</em>. The contents associated with the <em>add</em> hash key defines the commands in the namespace.</li>
<li>lines 9-38 - Here we define our commads in a very similar fashion as in the previous example. We have added the complexity of each command accepting some parameters. This is defined by the array assigned to the <em>syntax</em> key</li>
<li>line 14 - States that the parameter is compulsary</li>
<li>line 15 - This is the displayed name of the parameter</li>
<li>line 16 - Defines the description of the command that will be printed in the help display of the command</li>
<li>line 17 - Specifies the regular expression by which the parameter will be validated by the command launcher</li>
<li>lines 42-55 - This is the implementation of the commands as defined in the <em>INFO</em> hash</li>
<li>line 44 - The args array contains the parameters that was passed. args[0] is the command, <em>node</em> in this case. args[1] contains the <em>parent_id</em> and args[2] contains the <em>label</em></li>
<li>line 46 - This is an example of a call to a service provider in this case it calls a method in the data-storage service provider. (See the <a href="#service_provider">architecture section</a> for a full discussion on this)</li>
<li>line 47 - The return value will be displayed in the command line console.</li>
</ul>
<p>As a last bit of advice:</p>
<ul>
<li>Name your extension file, class and if applicable namespace the same name</li>
<li>If you add something new to the data storage you might find that you can not reference the newly added record immediately. The reason is that you have to wait for the local cache of the data storage to be refreshed. You can force a refresh with a <em>@controller.request_service(:model_knowledge_refresh)</em> call.</li>
</ul>
<p>That should leave you with a good understanding of dradis extensions.</p>
<p>As always - Happy dradis coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/02/17/dradis-extensions-how-they-work-and-how-to-write-them/feed/</wfw:commentRss>
		</item>
		<item>
		<title>dradis reporting: quick &#38; neat word export</title>
		<link>http://usefulfor.com/ruby/2009/02/15/dradis-reporting-quick-neat-word-export/</link>
		<comments>http://usefulfor.com/ruby/2009/02/15/dradis-reporting-quick-neat-word-export/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 15:55:43 +0000</pubDate>
		<dc:creator>etd</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[dradis]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=83</guid>
		<description><![CDATA[With over 800 downloads in the first two weeks of dradis v2.0, there is lots of interest on what is going to be next. We are working on solutions for importing and exporting data to and from the repository, but for those of you that can&#8217;t wait, we have put together a plug-in for the [...]]]></description>
			<content:encoded><![CDATA[<p>With over 800 downloads in the first two weeks of <a href="http://dradis.sourceforge.net/">dradis v2.0</a>, there is lots of interest on what is going to be next. We are working on solutions for importing and exporting data to and from the repository, but for those of you that can&#8217;t wait, we have put together a plug-in for the server that exports your notes to a Word file.</p>
<p>It is not the final solution, and it is not integrated with the web interface, but hopefully it will give you an idea of how easy is to get your own exporting modules for dradis.<br />
<span id="more-83"></span></p>
<h3>The Template</h3>
<p>So the first step was to use Word to generate a template we could use for our export plug-in. I just created a simple empty document that looked like this:-</p>
<p><img src="http://usefulfor.com/ruby/files/2009/02/word-template.png" alt="" width="500" height="242" class="aligncenter size-full wp-image-109" /></p>
<p>Save your template as an XML document (you can get mine here: <a href="http://usefulfor.com/ruby/files/2009/02/template.xml">template.xml</a>). The template contains these sections:-</p>
<ul>
<li>Issue title</li>
<li>Date of discovery</li>
<li>Issue description</li>
<li>Mitigation recommendations</li>
<li>Additional information</li>
</ul>
<p>What our plug-in is going to do is to walk through the notes in the repository and repeat this template for each one. In order for the code to find the different sections, you have to edit the XML file an add some <code>id</code> attributes to the tags associated with the sections. For instance:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!-- Note Section --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wx:sub-section<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:p</span> <span style="color: #000066;">wsp:rsidR</span>=<span style="color: #ff0000;">&quot;005F557A&quot;</span> <span style="color: #000066;">wsp:rsidRDefault</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidP</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:pStyle</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;Heading1&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:t</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;vulntitle&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Directory Listings<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:p</span> <span style="color: #000066;">wsp:rsidR</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidRPr</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidRDefault</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidP</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:jc</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;right&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:rPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:rFonts</span> <span style="color: #000066;">w:ascii</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span> <span style="color: #000066;">w:h-ansi</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span> <span style="color: #000066;">w:cs</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wx:font</span> <span style="color: #000066;">wx:val</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:sz</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;16&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:sz-cs</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;16&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:rPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:r</span> <span style="color: #000066;">wsp:rsidRPr</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:rPr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:rFonts</span> <span style="color: #000066;">w:ascii</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span> <span style="color: #000066;">w:h-ansi</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span> <span style="color: #000066;">w:cs</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;wx:font</span> <span style="color: #000066;">wx:val</span>=<span style="color: #ff0000;">&quot;Arial&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;w:sz</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;16&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;w:sz-cs</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;16&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/w:rPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:t</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;vulncreated&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>2009-02-10 00:07 GMT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wx:sub-section</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;vulndesc&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:p</span> <span style="color: #000066;">wsp:rsidR</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidRDefault</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidP</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:pStyle</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;Heading2&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Description<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wx:sub-section<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wx:sub-section</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;vulnrec&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:p</span> <span style="color: #000066;">wsp:rsidR</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidRDefault</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidP</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:pStyle</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;Heading2&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Recommendation<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wx:sub-section<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wx:sub-section</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;vulnextra&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:p</span> <span style="color: #000066;">wsp:rsidR</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidRDefault</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span> <span style="color: #000066;">wsp:rsidP</span>=<span style="color: #ff0000;">&quot;00C27C1C&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:pStyle</span> <span style="color: #000066;">w:val</span>=<span style="color: #ff0000;">&quot;Heading2&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/w:pPr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Additional Information<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:t<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/w:r<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/w:p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wx:sub-section<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wx:sub-section<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">&lt;!-- /Note Section --&gt;</span></pre></td></tr></table></div>

<ul>
<li>Issue title: <code>&lt;w:t id="vulntitle"&gt;</code> (line 7)</li>
<li>Date of discovery: <code>&lt;w:t id="vulncreated"&gt;</code> (line 21)</li>
<li>Issue description: <code>&lt;wx:sub-section id="vulndesc"&gt;</code> (line 25)</li>
<li>Mitigation recommendations: <code>&lt;wx:sub-section id="vulnrec"&gt;</code> (line 32)</li>
<li>Additional information: <code>&lt;wx:sub-section id="vulnextra"&gt;</code> (line 39)</li>
</ul>
<p>For the issue title and the date of discovery we will be modifying the <code>text</code> of the XML node. For the description, recommendation and additional information we will be attaching child nodes to the one tagged.</p>
<h3>The Code-fu</h3>
<p>We are already thinking on ways of mapping your template sections with you repository fields, but for the time being most of the information is extracted from the the Note text. So the structure of our notes would be:-</p>
<div class="hl-surround" style="height:280px;"><div class="hl-main"><pre>Title:
Whatever is the title of the issue

Descripton:
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Recommendation:
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab
illo inventore veritatis et quasi architecto beatae vitae dicta sunt
explicabo.

Additional stuff:
- this and that
- blah blah</pre></div></div>
<p>The code will take the Note text, then apply a regular expression to find the different sections and extract the fields used in the template:-</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">  Note.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>n<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#008000; font-style:italic;">#... more stuff here</span>
    <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;processing Note #{n.id}&quot;</span>
    fields = n.<span style="color:#9900CC;">text</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#006600; font-weight:bold;">+</span>?:\n.<span style="color:#006600; font-weight:bold;">*</span>?<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">collect</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>field<span style="color:#006600; font-weight:bold;">|</span> field.<span style="color:#9900CC;">strip</span> <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#008000; font-style:italic;">#... more stuff here</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>The code will be smart enough to detect if the <em>Additional stuff</em> section is present or not, this is done by simply counting the number of extracted fields.</p>
<h4>The XML Documents</h4>
<p>For To process XML we will be using <a href="http://www.germane-software.com/software/rexml/">REXML</a>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">begin</span>
  doc = <span style="color:#6666ff; font-weight:bold;">REXML::Document</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'./vendor/plugins/word_export/template.xml'</span>,<span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">REXML::ParseException</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e <span style="color:#008000; font-style:italic;"># re-raise exception</span>
  <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">Exception</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>e<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
vulns = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
body = <span style="color:#6666ff; font-weight:bold;">REXML::XPath</span>.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#40;</span>doc, <span style="color:#996600;">'//w:body'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
vuln_template = <span style="color:#6666ff; font-weight:bold;">REXML::Document</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span> doc.<span style="color:#9900CC;">root</span>.<span style="color:#9900CC;">clone</span>.<span style="color:#9900CC;">to_s</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
vuln_template.<span style="color:#9900CC;">root</span>.<span style="color:#9900CC;">add</span> body.<span style="color:#9900CC;">children</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></td></tr></table></div>

<p>First we need to load the template, then in lines 8-10 we locate the section of the code we will be repeating for each Note. and store a copy of the full section in <code>vuln_template</code>. </p>
<p>Using <code>REXML</code> there are two ways of copying an XML node, one is with <code>element.clone()</code> (that will create a copy of the node, but not of its children) and the other is creating a new document: <code>Document.new( element.to_s )</code> (that will create a swallow copy). Ideally I would have created a new Document with the subsection that contains the template for the Note, however, Word defines a number of XML namespaces at the begining of the document, and REXML complains if we try to create a document without the right namespaces (this would be a simple: <code>Document.new(body.children[3].to_s)</code>).</p>
<p>So instead we need to create a new document that contains the Word namespaces, and then include the Note template we want to use. We do this by cloning the root node of the original document and then attaching the desired structure of the Note.</p>
<p>Also note in line 7 we are initialising an array of vulnerabilities. We will be looping through our notes and filling in the template with the information contained in the Note text and storing the vulnerability in this array. Afterwards, we will attach all the vulnerabilities to the <code>w:body</code> of our document.</p>
<h4>Filling in the template</h4>
<p>So for each Note we need to create a new XML section that will be stored in the <code>vulns</code> array. This is done by duplicating the <code>vuln_template</code> and filling it with content from the Note.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">v = <span style="color:#6666ff; font-weight:bold;">REXML::Document</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>vuln_template.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>The rest of the code is standard XML processing. For the Title and Date fields, just assign the text of the node:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#title</span>
title = <span style="color:#6666ff; font-weight:bold;">REXML::XPath</span>.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#40;</span>v, <span style="color:#996600;">&quot;//w:t[@id='vulntitle']&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> 
title.<span style="color:#9900CC;">delete_attribute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'id'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
title.<span style="color:#9900CC;">text</span> = fields<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></td></tr></table></div>

<p>For the Description, Recommendation and Additional information sections, we create a new XML paragraph for each paragraph in the original text:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">description = <span style="color:#6666ff; font-weight:bold;">REXML::XPath</span>.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#40;</span>v, <span style="color:#996600;">&quot;//wx:sub-section[@id='vulndesc']&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
description.<span style="color:#9900CC;">delete_attribute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'id'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
fields<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;<span style="color:#000099;">\n</span><span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>paragraph<span style="color:#006600; font-weight:bold;">|</span>
  par = <span style="color:#6666ff; font-weight:bold;">REXML::Element</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'w:t'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  par.<span style="color:#9900CC;">text</span> = paragraph
  r = <span style="color:#6666ff; font-weight:bold;">REXML::Element</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'w:r'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  r.<span style="color:#9900CC;">elements</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> par
  chunk = <span style="color:#6666ff; font-weight:bold;">REXML::Element</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'w:p'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  chunk.<span style="color:#9900CC;">attributes</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'wsp:rsidR'</span><span style="color:#006600; font-weight:bold;">&#93;</span>=<span style="color:#996600;">'00C27C1C'</span> 
  chunk.<span style="color:#9900CC;">attributes</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'wsp:rsidRDefault'</span><span style="color:#006600; font-weight:bold;">&#93;</span>=<span style="color:#996600;">'00C27C1C'</span>
  chunk.<span style="color:#9900CC;">attributes</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'wsp:rsidP'</span><span style="color:#006600; font-weight:bold;">&#93;</span>=<span style="color:#996600;">'00C27C1C'</span>
  chunk.<span style="color:#9900CC;">elements</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> r
  description.<span style="color:#9900CC;">elements</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> chunk 
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<h4>Attaching the Vulnerabilities to the Document</h4>
<p>Finally we need to attach all the vulnerabilities to the body of the main document. This is done with the following code:-</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">vulns.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>v<span style="color:#006600; font-weight:bold;">|</span>
  body.<span style="color:#9900CC;">insert_before</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'//w:sectPr'</span>, v.<span style="color:#9900CC;">root</span>.<span style="color:#9900CC;">children</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>  
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Note that we are not adding the root element, but its first child. This is because the root element is <code>w:wordDocument</code> tag that contains the namespace declarations as already discussed.</p>
<p>And the last thing that is left is to write the document in our output <code>report.xml</code> file:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">doc.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'report.xml'</span>,<span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span>, <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<h3>Get the Plug-in</h3>
<p>The plugin is already in the repository (in <a href="http://dradis.svn.sourceforge.net/viewvc/dradis/server/trunk/vendor/plugins/">server/trunk/vendor/plugins/</a>), but if you have dradis already in your box you can get it by going to the <strong>server</strong> folder and executing:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">ruby script\plugin <span style="color: #c20cb9; font-weight: bold;">install</span> http:<span style="color: #000000; font-weight: bold;">//</span>dradis.svn.sourceforge.net<span style="color: #000000; font-weight: bold;">/</span>svnroot<span style="color: #000000; font-weight: bold;">/</span>dradis<span style="color: #000000; font-weight: bold;">/</span>server<span style="color: #000000; font-weight: bold;">/</span>trunk<span style="color: #000000; font-weight: bold;">/</span>vendor<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>word_export<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>And to run it:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">rake <span style="color: #7a0874; font-weight: bold;">export</span>:word</pre></div></div>

<p>Just remember that you need your notes to formatted as the plugin expects. You can download a sample <a href="http://usefulfor.com/ruby/files/2009/02/development.sqlite3">development.sqlite3</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/02/15/dradis-reporting-quick-neat-word-export/feed/</wfw:commentRss>
		</item>
		<item>
		<title>NSIS installer for a Ruby application - Part 3 - A few script improvements</title>
		<link>http://usefulfor.com/ruby/2009/02/09/nsis-installer-for-a-ruby-application-part-3-a-few-script-improvements/</link>
		<comments>http://usefulfor.com/ruby/2009/02/09/nsis-installer-for-a-ruby-application-part-3-a-few-script-improvements/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 10:53:08 +0000</pubDate>
		<dc:creator>siebert</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[X Windows]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=82</guid>
		<description><![CDATA[In this part of the series (see Part 1 and Part 2) we will:

Make one of the components compulsory to install.
We will look at a way to write our script in such a way that it can be reused for future releases of MyApplication.
A few extra tips and tricks.


Making a component compulsory
At the end of [...]]]></description>
			<content:encoded><![CDATA[<p>In this part of the series (see <a title="Part 1" href="http://usefulfor.com/ruby/2009/02/02/nsis-installer-for-a-ruby-application-part-1-hm-nis-wizard-output/">Part 1</a> and <a title="Part 2" href="http://usefulfor.com/ruby/2009/02/09/nsis-installer-for-a-ruby-application-part-2-install-ruby-and-a-gem/">Part 2</a>) we will:</p>
<ul>
<li>Make one of the components compulsory to install.</li>
<li>We will look at a way to write our script in such a way that it can be reused for future releases of MyApplication.</li>
<li>A few extra tips and tricks.</li>
</ul>
<p><span id="more-82"></span><br />
<strong>Making a component compulsory</strong><br />
At the end of Part 2 we added the components page to our installer. The component page gives the user the option to select which components he want to install. However, we want the installer not to give the user the option to not install MyApplication component but to make the installation of MyApplication when executing the script. We use the <a href="http://nsis.sourceforge.net/Docs/Chapter4.html#4.9.13">SectionSetFlags</a> method to achieve this. <em>SetSectionFlags</em> allows you to set certain attributes of a section (component to be installed). We add the following code:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066;">Function</span> <span style="color: #006600;">.onInit</span>
  <span style="color: #000099;">IntOp</span> <span style="color: #660000;">$0</span> <span style="color: #660000;">$<span style="">&#123;</span>SF_SELECTED<span style="">&#125;</span> | $<span style="">&#123;</span>SF_RO<span style="">&#125;</span></span>
  <span style="color: #000099;">SectionSetFlags</span> <span style="color: #660000;">$<span style="">&#123;</span>SEC03<span style="">&#125;</span></span> <span style="color: #660000;">$0</span>
<span style="color: #000066;">FunctionEnd</span></pre></div></div>

<ul>
<li>You will recall from Part 1 that the <em>.onInit</em> function is called on initiating the script.</li>
<li>The <em>SectionSetFlags</em> method sets first 8 bits of the section&#8217;s flags. We are interested in the first bit (setting a sections and selected) and the fifth bit (setting a section as read only)</li>
<li>To achieve this we use the <em>SF_SELECTED</em> and the <em>SF_RO</em> constants that are equal to 1 and 16 respectively.</li>
<li>When we <em>OR</em> these to constants together we end up with a value of which the first and the fifth bit are set (line 2).</li>
<li>In line 3 we use the <em>SectionSetFlags</em> method to apply the result of the <em>OR</em> to <em>SEC03</em> which is our MyApplication component.</li>
<li>The result is that the MyApplication component will be selected and read only on the components page of the installer.</li>
<p><strong>Making our script usable for the future</strong><br />
I might happen that we want to release a new version of MyApplication that requires a new installer. The new version might have the same requirements but a few new files might be added that now needs to be added to the installer. If the install section of MyApplication gets very big (depending on the size of MyApplication) it can be a daunting task to review all the <em>SetOutPath &#8220;$INSTDIR\my_folder&#8221;</em> and <em>File &#8220;application_files\myapplication.rb&#8221;</em> type calls. It will be great if we can automate the creating of these calls.</p>
<p>I have created the following Ruby script that receives as commandline argument the folder in which MyApplication lives and the creates a text file that contains the instruction set that we need in the MyApplication section:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'fileutils'</span>
<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">FileUtils::Verbose</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> recursive_folder_dump<span style="color:#006600; font-weight:bold;">&#40;</span>folder, install_file, uninstall_file, relative_path<span style="color:#006600; font-weight:bold;">&#41;</span>
  cd<span style="color:#006600; font-weight:bold;">&#40;</span>folder<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
    folders = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#CC00FF; font-weight:bold;">Dir</span>.<span style="color:#9900CC;">foreach</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'.<span style="color:#000099;">\\</span>'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>inner_file<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">directory</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>inner_file<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&amp;</span>amp;<span style="color:#006600; font-weight:bold;">&amp;</span>amp; inner_file != <span style="color:#996600;">'.'</span> <span style="color:#006600; font-weight:bold;">&amp;</span>amp;<span style="color:#006600; font-weight:bold;">&amp;</span>amp; inner_file != <span style="color:#996600;">'..'</span>
        folders <span style="color:#006600; font-weight:bold;">&amp;</span>lt;<span style="color:#006600; font-weight:bold;">&amp;</span>lt; inner_file
      <span style="color:#9966CC; font-weight:bold;">elsif</span> inner_file != <span style="color:#996600;">'.'</span> <span style="color:#006600; font-weight:bold;">&amp;</span>amp;<span style="color:#006600; font-weight:bold;">&amp;</span>amp; inner_file != <span style="color:#996600;">'..'</span>
        install_file.<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;File <span style="color:#000099;">\&quot;</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> relative_path <span style="color:#006600; font-weight:bold;">+</span> inner_file <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\&quot;</span>&quot;</span>
        uninstall_file.<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Delete <span style="color:#000099;">\&quot;</span>$INSTDIR<span style="color:#000099;">\\</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> relative_path <span style="color:#006600; font-weight:bold;">+</span> inner_file <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\&quot;</span>&quot;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
    folders.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>folder<span style="color:#006600; font-weight:bold;">|</span>
      install_file.<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;SetOutPath <span style="color:#000099;">\&quot;</span>$INSTDIR<span style="color:#000099;">\\</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> relative_path <span style="color:#006600; font-weight:bold;">+</span> folder <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\&quot;</span>&quot;</span>
      recursive_folder_dump<span style="color:#006600; font-weight:bold;">&#40;</span>folder, install_file, uninstall_file, relative_path <span style="color:#006600; font-weight:bold;">+</span> folder <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\\</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      uninstall_file.<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;RMDir <span style="color:#000099;">\&quot;</span>$INSTDIR<span style="color:#000099;">\\</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> relative_path <span style="color:#006600; font-weight:bold;">+</span> folder <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\&quot;</span>&quot;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">if</span> ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#0000FF; font-weight:bold;">nil</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">'usage: ruby nsis_folder_dump.rb  '</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">'where:'</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">' - is the folder/file structure to be dumped'</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">' - will be used to create the output file names: _install.nsi and _uninstall.nsi'</span>
  <span style="color:#CC0066; font-weight:bold;">exit</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">if</span> !<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot; is not an existing folder&quot;</span>
  <span style="color:#CC0066; font-weight:bold;">exit</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
install_file = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#996600;">&quot;_install.nsh&quot;</span>,<span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
uninstall_file = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#996600;">&quot;_uninstall.nsh&quot;</span>,<span style="color:#996600;">'w'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
install_file.<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;SetOutPath <span style="color:#000099;">\&quot;</span>$INSTDIR<span style="color:#000099;">\\</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\&quot;</span>&quot;</span>
recursive_folder_dump<span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>, install_file, uninstall_file, ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\\</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
uninstall_file.<span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;RMDir <span style="color:#000099;">\&quot;</span>$INSTDIR<span style="color:#000099;">\\</span>&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\&quot;</span>&quot;</span>
&nbsp;
install_file.<span style="color:#9900CC;">close</span></pre></div></div>

<p>The above script will create two files. Depending on the commandline parameters they might be <em>myapplication_install.nsh</em> and <em>myapplication_uninstall.nsh</em>.</p>
<p>NSIS allows us to include these files in our script with the <em>!include</em>. We change the MyApplication install section to look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;MyApplication&quot;</span> SEC03
  <span style="color: #000066; font-weight:bold;">!include</span> <span style="color: #660066;">&quot;myapplication_install.nsh&quot;</span>
<span style="color: #000066;">SectionEnd</span></pre></div></div>

<p>And we add the following to the top of our <em>Uninstall</em> section:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;">!include</span> <span style="color: #660066;">&quot;myapplication_uninstall.nsh&quot;</span></pre></div></div>

<p>We can now keep our NSIS install script the same for all future releases of MyApplication and just generate new <em>myapplication_install.nsh</em> and <em>myapplication_uninstall.nsh</em> files.</p>
<p><strong>A few more tips and tricks</strong><br />
MyApplication has a database the can be initialised by a rake task. We can run this rake task at the end of a successful installation. We achieve that with the following code:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;">!define</span> <span style="color: #006600;">MUI_FINISHPAGE_RUN_TEXT</span> <span style="color: #660066;">&quot;Initialise the database&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> <span style="color: #006600;">MUI_FINISHPAGE_RUN</span> <span style="color: #660066;">&quot;$0\bin\rake.bat&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> <span style="color: #006600;">MUI_FINISHPAGE_RUN_PARAMETERS</span> <span style="color: #660066;">&quot;-f $\&quot;</span><span style="color: #660000;">$INSTDIR</span>\server\Rakefile$\<span style="color: #660066;">&quot; db:migrate&quot;</span></pre></div></div>

<p>On uninstall files and folders can be removed by the <em>Delete</em> and <em>RMDir</em> methods. If you want to delete a whole folder recursively its contents you can use the <em>/r</em> directive:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000099;">RMDir</span> <span style="color: #ff6600;">/r</span> <span style="color: #660066;">&quot;$INSTDIR\my_application&quot;</span></pre></div></div>

<p>And that brings us to the end of Part 3.</ul>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/02/09/nsis-installer-for-a-ruby-application-part-3-a-few-script-improvements/feed/</wfw:commentRss>
		</item>
		<item>
		<title>NSIS installer for a Ruby application - Part 2 - Install Ruby and a gem</title>
		<link>http://usefulfor.com/ruby/2009/02/09/nsis-installer-for-a-ruby-application-part-2-install-ruby-and-a-gem/</link>
		<comments>http://usefulfor.com/ruby/2009/02/09/nsis-installer-for-a-ruby-application-part-2-install-ruby-and-a-gem/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 23:24:05 +0000</pubDate>
		<dc:creator>siebert</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[X Windows]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=78</guid>
		<description><![CDATA[In Part 1 of this series we had a look at the general structure of a NSIS script as it was created for us by the HM NIS editor and IDE. We previously defined three components to be installed by our installer:

Ruby (the target machine that our application is installed on requires Ruby)
MyGem (our application [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="/ruby/2009/02/02/nsis-installer-for-a-ruby-application-part-1-hm-nis-wizard-output/">Part 1</a> of this series we had a look at the general structure of a NSIS script as it was created for us by the HM NIS editor and IDE. We previously defined three components to be installed by our installer:</p>
<ul>
<li>Ruby (the target machine that our application is installed on requires Ruby)</li>
<li>MyGem (our application is dependent on this fictitious gem)</li>
<li>MyApplication (this is our application to be installed)</li>
</ul>
<p>In this part we will look at how we will let the installer take care of the Ruby and MyGem components.</p>
<p><span id="more-78"></span></p>
<p>To start off, place the following at the top of your code:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;">!include</span> <span style="color: #006600;">LogicLib.nsh</span></pre></div></div>

<p>This includes the LogicLib library and allow us to write more readable code by providing us some macros to write traditional logical structures for example <em>IF</em> and <em>CASE</em> structures</p>
<p><strong>Ruby</strong></p>
<p>Our application needs Ruby to be installed on the target machine. In the case that Ruby is not installed on the machine we want to relieve the user from having to install Ruby separately. Instead we want to install it for him.</p>
<p>In the example in Part one we replace the code:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;Ruby&quot;</span> SEC01
<span style="color: #000066;">SectionEnd</span></pre></div></div>

<p>with (we will go through this in detail):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;ruby&quot;</span> SEC01
  <span style="color: #666666; font-style: italic;">; read the registry to check if there is not already a local installation of ruby</span>
  <span style="color: #000099;">readRegStr</span> <span style="color: #660000;">$0</span> <span style="color: #ff6600;">HKLM</span> <span style="color: #660066;">&quot;SOFTWARE\RubyInstaller&quot;</span> Path
  <span style="color: #660000;">$<span style="">&#123;</span>If<span style="">&#125;</span></span> <span style="color: #660000;">$0</span> != <span style="color: #660066;">''</span>
    <span style="color: #666666; font-style: italic;">; ruby installed</span>
    <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_OK</span> <span style="color: #660066;">'Ruby is already installed on the system. The automated installation of Ruby will not proceed'</span>
  <span style="color: #660000;">$<span style="">&#123;</span>Else<span style="">&#125;</span></span>
    <span style="color: #666666; font-style: italic;">; no ruby installer</span>
    <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_OK</span> <span style="color: #660066;">'The ruby installer will now be downloaded and executed. This might take a few moments.'</span>
    <span style="color: #666666; font-style: italic;">; download and install ruby</span>
    NSI<span style="color: #000099;">Sdl</span>::<span style="color: #003399;">download </span>/NOIEPROXY <span style="color: #660066;">&quot;http://rubyforge.org/frs/download.php/29263/ruby186-26.exe&quot;</span> <span style="color: #660066;">&quot;ruby186-26.exe&quot;</span>
    <span style="color: #000099;">Pop</span> <span style="color: #660000;">$R0</span>
    <span style="color: #660000;">$<span style="">&#123;</span>If<span style="">&#125;</span></span> <span style="color: #660000;">$R0</span> == <span style="color: #660066;">'success'</span>
      <span style="color: #666666; font-style: italic;">; ruby download successful</span>
      <span style="color: #000099;">StrCpy</span> <span style="color: #660000;">$0</span> <span style="color: #660066;">''</span>
      <span style="color: #666666; font-style: italic;">; rum the one click installer</span>
      <span style="color: #000099;">ExecWait</span> <span style="color: #660066;">'&quot;ruby186-26.exe&quot;'</span> <span style="color: #660000;">$0</span>
      <span style="color: #660000;">$<span style="">&#123;</span>If<span style="">&#125;</span></span> <span style="color: #660000;">$0</span> == <span style="color: #660066;">''</span>
        <span style="color: #666666; font-style: italic;">; execution of one click installer failed</span>
        <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_OK</span> <span style="color: #660066;">&quot;Ruby install failed. Please install Ruby manually&quot;</span>
      <span style="color: #660000;">$<span style="">&#123;</span>EndIf<span style="">&#125;</span></span>
      <span style="color: #666666; font-style: italic;">; delete the ruby one click installer</span>
    <span style="color: #660000;">$<span style="">&#123;</span>Else<span style="">&#125;</span></span>
      <span style="color: #666666; font-style: italic;">; ruby download not successfull</span>
      <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_OK</span> <span style="color: #660066;">&quot;Ruby download failed. Please download and install Ruby manually&quot;</span>
    <span style="color: #660000;">$<span style="">&#123;</span>EndIf<span style="">&#125;</span></span>
    <span style="color: #000099;">Delete</span> <span style="color: #660066;">&quot;ruby186-26.exe&quot;</span>
  <span style="color: #660000;">$<span style="">&#123;</span>EndIf<span style="">&#125;</span></span>
<span style="color: #000066;">SectionEnd</span></pre></td></tr></table></div>

<p>Lets go through the code in detail</p>
<ul>
<li>We make the assumption that if Ruby is installed on the system that there will be a registry entry for the installation. We check for this registry entry with the <em>readRegStr</em> command (line 3).</li>
<li>If we find an entry in the registry we prompt (<em>MessageBox</em>) this to the user and we do not proceed with the Ruby installation (line 6).</li>
<li>If Ruby is not installed we notify the user that the installer will download the Ruby one-click installer and then proceed with the download (<em>NSISdl::download</em>, line 11)</li>
<li>A successful download will place the <em>success </em>string on the stack. We <em>Pop</em> the top value from the stack and store in <em>$0</em> (line 12).</li>
<li>The installer inspects <em>$0</em> and is the download was successful it proceeds to running the Ruby one-click installer (<em>ExecWait</em>, line 17)</li>
<li>The return value of the one-click installer is inspected to determine a successful install. In the case of failure this is prompted to the user (lines 18-20).</li>
<li>Towards the end of the script we handle the case of a failed download (lines 23-25).</li>
<li>Finally the installer deletes the downloaded one-click installer (<em>Delete</em>, line 27)</li>
</ul>
<p><strong>MyGem</strong></p>
<p>The installer needs to take care of the installation of our required gem, MyGem. To minimize the insteraction between the user and the installation process the installer installs the gem from a file in the installation package. This file contains the gem for local install.</p>
<p>Once again refering to the example in Part 1 one, we replace the code:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;MyGem&quot;</span> SEC02
<span style="color: #000066;">SectionEnd</span></pre></div></div>

<p>with:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;MyGem&quot;</span> SEC02
  <span style="color: #000099;">SetOutPath</span> <span style="color: #660066;">&quot;$INSTDIR\client&quot;</span>
  <span style="color: #000099;">File</span> <span style="color: #660066;">&quot;my_gem-x86-mswin32-60.gem&quot;</span>
  <span style="color: #666666; font-style: italic;"># check if ruby is installed and install the mygem gem locally if so</span>
  <span style="color: #000099;">readRegStr</span> <span style="color: #660000;">$0</span> <span style="color: #ff6600;">HKLM</span> <span style="color: #660066;">&quot;SOFTWARE\RubyInstaller&quot;</span> Path
  <span style="color: #660000;">$<span style="">&#123;</span>If<span style="">&#125;</span></span> <span style="color: #660000;">$0</span> != <span style="color: #660066;">''</span>
    <span style="color: #666666; font-style: italic;">; ruby installed</span>
    <span style="color: #000099;">StrCpy</span> <span style="color: #660000;">$1</span> <span style="color: #660066;">''</span>
    <span style="color: #666666; font-style: italic;">; install the mygem locally</span>
    <span style="color: #000099;">ExecWait</span> <span style="color: #660066;">'&quot;$0\bin\gem.bat&quot; install my_gem-x86-mswin32-60.gem'</span> <span style="color: #660000;">$1</span>
    <span style="color: #660000;">$<span style="">&#123;</span>If<span style="">&#125;</span></span> <span style="color: #660000;">$1</span> == <span style="color: #660066;">''</span>
      <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_OK</span> <span style="color: #660066;">&quot;Gem install failed. Please install the MyGem gem manually&quot;</span>
    <span style="color: #660000;">$<span style="">&#123;</span>EndIf<span style="">&#125;</span></span>
  <span style="color: #660000;">$<span style="">&#123;</span>Else<span style="">&#125;</span></span>
    <span style="color: #666666; font-style: italic;">; ruby not installed</span>
    <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_OK</span> <span style="color: #660066;">&quot;Ruby is not installed. Please install ruby and then run the installer again or install the MyGem gem manually&quot;</span>
  <span style="color: #660000;">$<span style="">&#123;</span>EndIf<span style="">&#125;</span></span>
  <span style="color: #000099;">Delete</span> <span style="color: #660066;">&quot;my_gem-x86-mswin32-60.gem&quot;</span>
<span style="color: #000066;">SectionEnd</span></pre></td></tr></table></div>

<p>By now you should be able to follow the code quite easily. I will just highlight to things:</p>
<ul>
<li>Yet again we have to check if Ruby is installed on the target machine (line 5).</li>
<li>Note that you have to give the full path to the gem batch file when triggering the gem installation (line 10).</li>
</ul>
<p><strong>Choosing Components</strong></p>
<p>You might what to give you users the option to choose the components that they want to install. The modern user interface makes it really easy for you.</p>
<p>Add the following to your script below <em>!insertmacro MUI_PAGE_COMPONENTS</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_PAGE_COMPONENTS</span></pre></div></div>

<p>And at the end of all your section code add:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_FUNCTION_DESCRIPTION_BEGIN</span>
  <span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_DESCRIPTION_TEXT</span> <span style="color: #660000;">$<span style="">&#123;</span>SEC01<span style="">&#125;</span></span> <span style="color: #660066;">&quot;Installs ruby. The installer will download the ruby one click installer and execute. Alternatively you can install ruby manually.&quot;</span>
  <span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_DESCRIPTION_TEXT</span> <span style="color: #660000;">$<span style="">&#123;</span>SEC02<span style="">&#125;</span></span> <span style="color: #660066;">&quot;Installs the MyGem gem. The gem requires ruby to be installed.&quot;</span>
  <span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_DESCRIPTION_TEXT</span> <span style="color: #660000;">$<span style="">&#123;</span>SEC03<span style="">&#125;</span></span> <span style="color: #660066;">&quot;Installs the MyApplication.&quot;</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_FUNCTION_DESCRIPTION_END</span></pre></div></div>

<p>I am going to leave it at that. In Part 3 we will look at you can make certain components compulsory, how we can write our script so that we can also use it for future releases of MyApplication and a few extra tips and tricks to clean up the script.</p>
<p>Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/02/09/nsis-installer-for-a-ruby-application-part-2-install-ruby-and-a-gem/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Use Rails to Create a Static Site</title>
		<link>http://usefulfor.com/ruby/2009/02/04/use-rails-to-create-a-static-site/</link>
		<comments>http://usefulfor.com/ruby/2009/02/04/use-rails-to-create-a-static-site/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 12:00:16 +0000</pubDate>
		<dc:creator>etd</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[dradis]]></category>

		<category><![CDATA[Add new tag]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=75</guid>
		<description><![CDATA[One of the new things we released last week with dradis v2.0 was a new web site for the project (dradis.sourceforge.net).
The old site consisted of 20 static pages or so, which was nice and easy but a real pain to maintain or restructure. So we thought that letting Rails do the heavy lifting for us [...]]]></description>
			<content:encoded><![CDATA[<p>One of the new things we released last week with <a href="/security/2009/01/30/dradis-v2/">dradis v2.0</a> was a new web site for the project (<a href="http://dradis.sourceforge.net/">dradis.sourceforge.net</a>).</p>
<p>The old site consisted of 20 static pages or so, which was nice and easy but a real pain to maintain or restructure. So we thought that letting Rails do the heavy lifting for us would be a good idea, but we did not want to set up a Rail environment in the server&#8230;</p>
<p>What we finally did is use Rails as a tool to create a static site that we could <em>.tar.gz</em> and upload to the server. As a starting point we used a post in <a href="http://www.chuckvose.com/articles/2006/04/20/monkey">www.chuckvose.com</a> and this is how we completed it to fit our needs.</p>
<p><strong>Follow up</strong> (2009-03-23): do not miss how to integrate your rails-static site with Rake and Subversion in the second article of this series: <a href="http://usefulfor.com/ruby/2009/03/23/use-rails-to-create-a-static-site-rake-and-subversion/">Use Rails to Create a Static Site: Rake and Subversion</a>.</p>
<p><span id="more-75"></span><br />
<a name="thecontroller"></a></p>
<h3>The Controller</h3>
<p>We just need one action in our main controller (<code>PagesController</code>):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> PagesController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
  layout <span style="color:#996600;">'main'</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> index
    <span style="color:#0066ff; font-weight:bold;">@page</span> = params.<span style="color:#9900CC;">fetch</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#996600;">'index'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    expanded_page = <span style="color:#996600;">&quot;#{RAILS_ROOT}/app/views/pages/#{@page}.html.erb&quot;</span>
    exists = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">exists</span>?<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>expanded_page<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> exists
      render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@page</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      render <span style="color:#ff3333; font-weight:bold;">:text</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;#{expanded_page} doesn't exist&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>We <code>fetch</code> the <strong>:id</strong> parameter from the request that contains the name of the requested page (or <code>index</code> by default), then we try to locate the corresponding file (in <code>/app/views/pages/</code>) and if found we render the action. Rendering the action with no action code in the controller will just render it&#8217;s <a href="http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html">ERB</a> template which is exactly what we want.</p>
<p>We also added a couple of routes in <code>/config/routes.rb</code> so every time a something<strong>.html</strong> was requested, the <code>PagesController</code> would be invoked:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">map.<span style="color:#9900CC;">root</span> <span style="color:#ff3333; font-weight:bold;">:controller</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'pages'</span>
map.<span style="color:#9900CC;">connect</span> <span style="color:#996600;">':id.html'</span>, <span style="color:#ff3333; font-weight:bold;">:controller</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'pages'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'index'</span></pre></div></div>

<h3>The Layout and the Pages</h3>
<p>The layout we used was quite simple. The most interesting bits follow.</p>
<p>First, we want each page to be able to set their own HTML title. This is accomplished by including the following code in the  layout:-</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">&lt;head&gt;
  &lt;title&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#9966CC; font-weight:bold;">yield</span> <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/title&gt;
&lt;/head&gt;</pre></div></div>

<p>Then pages must include this line to set the contents of the <strong>:title</strong> variable:-</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#5A0A0A; font-weight:bold;">content_for</span> <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>Announcements - dradis<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

<p>Other than that, we used the standard <code>@content_for_layout</code> in the main section of the page. However, the site has two menus, one in the top and one in the right hand side. This exposes a new challenge because we need to create the structure of the page in a way that is simple enough to maintain and add new content in the future. We had to code some Rails helpers to aid us in this.</p>
<h3>The Helpers</h3>
<h4>The Top Menu</h4>
<p><img src="http://usefulfor.com/ruby/files/2009/02/dradis2_topmenu.png" alt="" width="409" height="35" class="aligncenter size-full wp-image-79" /></p>
<p>The Top menu bar consists only of the main sections of the site. In the layout we call the Helper straight away passing the current page (see <a href="#thecontroller">The Controller</a> above):</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">&lt;div class=&quot;bar&quot;&gt;
&lt;ul&gt;
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= barmenu<span style="color:#006600; font-weight:bold;">&#40;</span>@page<span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#006600; font-weight:bold;">%&gt;</span>
&lt;/ul&gt;
&lt;/div&gt;</pre></div></div>

<p>The code of the helper in this instance is quite simple. The only intelligence we are adding is a check to see if the current page is one of the items in the menu, if it is, we add the CSS <strong>active</strong> class to the list item.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> barmenu<span style="color:#006600; font-weight:bold;">&#40;</span>page<span style="color:#006600; font-weight:bold;">&#41;</span>
    items = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'download'</span>, <span style="color:#996600;">'demo'</span>, <span style="color:#996600;">'screenshots'</span>, <span style="color:#996600;">'documentation'</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
    items.<span style="color:#9900CC;">collect</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span>
      active = <span style="color:#996600;">''</span>
      label = i.<span style="color:#9900CC;">capitalize</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>page == i<span style="color:#006600; font-weight:bold;">&#41;</span>
        active = <span style="color:#996600;">' class=&quot;active&quot;'</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        label = <span style="color:#996600;">&quot;&lt;a href=<span style="color:#000099;">\&quot;</span>#{i}.html<span style="color:#000099;">\&quot;</span>&gt;#{i.capitalize}&lt;/a&gt;&quot;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#996600;">&quot;&lt;li#{active}&gt;#{label}&lt;/li&gt;&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h4>Right Hand Side Navigation</h4>
<p><img src="http://usefulfor.com/ruby/files/2009/02/dradis2_navigation.png" alt="" width="275" height="253" class="alignright size-full wp-image-80" /><br />
The navigation menu in the right side was a bit trickier. We had our pages organised in three different sections: <em>using dradis</em>, <em>developing dradis</em> and <em>support from</em>. </p>
<p>Each section contains a number of items, some of the items have our content, some are links to external sites. In addition to this it would be useful if we could nest subsections as shown in the screenshot of the right.</p>
<p>So we had to figure out a way of representing the structure of the menu. Probably the neatest solution would have been to create an HTML page that contained a series of nested <code>ul</code> and <code>li</code> elements and then make the helper parse that structure assign the <strong>active</strong> CSS class to the right element and display it. Or maybe using a fancy JavaScript trick to locate the active item and assign the CSS class. However, as often happens we needed a solution, and it had to be fast, so we opted for having the structure loaded in a ruby array with one <code>Hash</code> per section:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#ff6633; font-weight:bold;">$sections</span> = <span style="color:#006600; font-weight:bold;">&#91;</span>
  <span style="color:#006600; font-weight:bold;">&#123;</span> ... <span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#008000; font-style:italic;"># using dradis</span>
  <span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'developing dradis'</span>,
    <span style="color:#ff3333; font-weight:bold;">:pages</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span>
      <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'info. for developers'</span>,
        <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'developers.html'</span>,
        <span style="color:#ff3333; font-weight:bold;">:pages</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:extensions</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>,
      <span style="color:#ff3333; font-weight:bold;">:roadmap</span>,
      <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:bug_tracker</span>,
        <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://sourceforge.net/tracker/?atid=1010917&amp;group_id=209736&amp;func=browse'</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>,
      <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:feature_requests</span>,
        <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://sourceforge.net/tracker/?atid=1010920&amp;group_id=209736&amp;func=browse'</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>,
      <span style="color:#006600; font-weight:bold;">&#123;</span>
        <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:subversion</span>,
        <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://sourceforge.net/svn/?group_id=209736'</span>
      <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>,
  <span style="color:#006600; font-weight:bold;">&#123;</span> ... <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#008000; font-style:italic;"># support from</span>
<span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>

<p>Each of the three section <code>Hash</code>es has a <code>:title</code> and a <code>:pages</code> attribute. The latter is an array containing the information of the pages associated with the parent section. The elements of the array can be either <code>Symbol</code>s or new <code>Hash</code>es that describe the different pages.</p>
<p>We use a <code>Symbol</code> if the content of the page is provided by the site such as in the <strong>:roadmap</strong> case whose contents are in <code>/app/views/pages/roadmap.html.erb</code> and the link displayed in the menu would be &#8220;roadmap&#8221;. In more complex cases (i.e. we want a custom title for the link or a section that contains subsections) we use a <code>Hash</code>.</p>
<p>When a <code>Hash</code> is used at least a <strong>:title</strong> and a <strong>:url</strong> elements must be provided. Optionally a <strong>:pages</strong> element can be used to nest sections inside sections. The format of this <strong>:pages</strong> value is again an array as the one used in the top level section. So there you have your recursion!</p>
<p>The helper in this case is a bit more complex. First, the call in the layout, nothing fancy here:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">&lt;div&gt;
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= rightmenu<span style="color:#006600; font-weight:bold;">&#40;</span>@page<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
&lt;/div&gt;</pre></div></div>

<p>The <code>rightmenu()</code> helper code:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> rightmenu<span style="color:#006600; font-weight:bold;">&#40;</span>page<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#ff6633; font-weight:bold;">$sections</span>.<span style="color:#9900CC;">collect</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>section<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#996600;">&quot;&lt;h3&gt;#{section[:title]}:&lt;/h3&gt;&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> sectionmenu<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page, <span style="color:#ff3333; font-weight:bold;">:section</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> section<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Each main section is enclosed in <code>h3</code> tags and then <code>sectionmenu</code> (a helper-to-the-helper method <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_rolleyes.gif' alt=':roll:' class='wp-smiley' /> ) is invoked for each section. There are some tricks going on in the following piece of code, have a look and we will nail it down later:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> sectionmenu<span style="color:#006600; font-weight:bold;">&#40;</span>options = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    current_page = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:page</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    section = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:section</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    level = options.<span style="color:#9900CC;">fetch</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:level</span>, <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    css = options.<span style="color:#9900CC;">fetch</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:css</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'right_articles'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    css <span style="color:#006600; font-weight:bold;">|</span>= <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;submenu#{level}&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>level <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    section<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:pages</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">collect</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>page<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#008000; font-style:italic;"># If the last item was the active one, clear the flag</span>
      css.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'active'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> css.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'active'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      title = <span style="color:#996600;">''</span>
      url = <span style="color:#996600;">''</span>
      complex = <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># simple page (Symbol) vs. complex page (Hash)</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>page.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC00FF; font-weight:bold;">Hash</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        complex = <span style="color:#0000FF; font-weight:bold;">true</span>
        title = page<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:title</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>_<span style="color:#006600; font-weight:bold;">/</span>,<span style="color:#996600;">' '</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        url = page<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:url</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        title = page.<span style="color:#9900CC;">to_s</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>_<span style="color:#006600; font-weight:bold;">/</span>,<span style="color:#996600;">' '</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        url = page.<span style="color:#9900CC;">to_s</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'.html'</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># active vs. inactive</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>current_page <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'.html'</span> == url<span style="color:#006600; font-weight:bold;">&#41;</span>
        css <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">'active'</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        title = <span style="color:#996600;">&quot;&lt;a href=<span style="color:#000099;">\&quot;</span>#{url}<span style="color:#000099;">\&quot;</span>&gt;#{title}&lt;/a&gt;&quot;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># subsections</span>
      <span style="color:#008000; font-style:italic;"># tradeoff: calculate the sub section,</span>
      <span style="color:#008000; font-style:italic;"># if it doesn't contain the &quot;active&quot; page, don't use it</span>
      subsection = <span style="color:#996600;">''</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>complex <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> page.<span style="color:#9900CC;">key</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:pages</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        subsection =  sectionmenu<span style="color:#006600; font-weight:bold;">&#40;</span>
            <span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> current_page,
            <span style="color:#ff3333; font-weight:bold;">:section</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page,
            <span style="color:#ff3333; font-weight:bold;">:level</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> level <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>
        <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
        found = !<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>active<span style="color:#006600; font-weight:bold;">/</span> =~ subsection<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
        <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span> !found <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> !css.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'active'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
          subsection = <span style="color:#996600;">''</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#996600;">&quot;&lt;div class=<span style="color:#000099;">\&quot;</span>#{css.join(' ')}<span style="color:#000099;">\&quot;</span>&gt;#{title}&lt;/div&gt;&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> subsection
    <span style="color:#9966CC; font-weight:bold;">end</span>.<span style="color:#9900CC;">join</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<p>In lines 2 to 6 we initialise the properties for this section. Then for each page in the section we apply the loop in 8 to 51. Due to the way the data is structured in the <code>$sections</code> variable, this code can be used to recursively crawl the tree of sections and subsections.</p>
<p>For each page in the section:</p>
<ul>
<li>we initialise the internal variables (9 to 13). If the page is a <code>Hash</code> we extract the title and URL for the link from it&#8217;s elements, if it is a <code>Symbol</code> we <em>infer</em> the title and link from the symbol name.</li>
<li>Then we check if the current page in the iteration is the active one (26 to 30). If it is, we add a CSS attribute to the item, if it is not, then we add a hyper-link to it (it would not make sense to have a link to the page if you are already in it).</li>
<li>Finally in 36 to 47 we check if there is a <strong>:pages</strong> element in the <code>Hash</code> and if there is one, we make a recursive call to render the subsection.</li>
</ul>
<p>Two things need to be said about the above piece of code. First, each subsection will be assigned a CSS class in accordance to it&#8217;s level: <code>submenu1</code>, <code>submenu2</code>, etc. This will allow us to style the different subsections appropriately. And second, because there is no easy way of knowing if the active belongs to one of the sub sections of the current section we make the recursive call, and then see if we have found the active page. If we have not, we discard the subsection altogether. We want this behaviour of not displaying a subsection in the menu unless the user is already in that section and this was the easiest way of implementing it. </p>
<h4>The Bread Crumbs</h4>
<p><img src="http://usefulfor.com/ruby/files/2009/02/dradis2_breadcrums.png" alt="" width="295" height="94" class="alignright size-full wp-image-81" /></p>
<p>The bread crumbs help our users to know where they are in the site (see picture in the right sid). We need to have a flexible helper that would display the path the user has followed to get into the page they are at the moment. Below is the code of the layout, just above the main content and with a check to verify that we are not in the main page:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">&lt;div class=&quot;left&quot;&gt;
  <span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@page</span> != <span style="color:#996600;">'index'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;div id=&quot;breadcrums&quot;&gt;
    &lt;ul&gt;
      <span style="color:#006600; font-weight:bold;">&lt;%</span>= breadcrumsmenu<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@page</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/ul&gt;
  &lt;/div&gt;
  <span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  <span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#0066ff; font-weight:bold;">@content_for_layout</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
&lt;/div&gt;</pre></div></div>

<p>And again, this helper will use the <code>$sections</code> as discussed above.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> breadcrumsmenu<span style="color:#006600; font-weight:bold;">&#40;</span>options=<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    crums = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#ff6633; font-weight:bold;">$sections</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>section<span style="color:#006600; font-weight:bold;">|</span>
      options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:section</span><span style="color:#006600; font-weight:bold;">&#93;</span> = section
      crums = breadcrums<span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">break</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>crums.<span style="color:#9900CC;">size</span> <span style="color:#006600; font-weight:bold;">&gt;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    this_page = crums.<span style="color:#9900CC;">pop</span>
    <span style="color:#006600; font-weight:bold;">&#40;</span>crums.<span style="color:#9900CC;">collect</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#996600;">&quot;&lt;li&gt;&lt;a href=<span style="color:#000099;">\&quot;</span>#{c[:url]}<span style="color:#000099;">\&quot;</span>&gt;#{c[:title]}&lt;/a&gt;&amp;lt/li&amp;gt&quot;</span>  <span style="color:#9966CC; font-weight:bold;">end</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">join</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">&quot;&lt;li&gt;#{this_page[:title]}&lt;/li&gt;&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Again a similar tradeoff here, we cycle through all the sections trying to find the <strong>active</strong> page. We use the <code>breadcrums</code> helper-to-the-helper function to find out if the page is in the given section and then we render the bread crumbs. I realise that the two helper-to-the-helper functions are quite similar (cycle through a section trying to locate the active page), and possibly we could refactor both into a single function that does thing. But then again, once it worked, we did not have too much spare time to look into it, so we may improve it in the future, but this is the solution we came up with at that point. The code of <code>breadcrums()</code> is very similar in structure to the code in <code>sectionmenu()</code> but this time, it returns an array of pages that will lead us to the active one:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> breadcrums<span style="color:#006600; font-weight:bold;">&#40;</span>options=<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    current_page = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:page</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    section = options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:section</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    crums = options.<span style="color:#9900CC;">fetch</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:crums</span>, <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:title <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'home'</span>, <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/'</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    section<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:pages</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>page<span style="color:#006600; font-weight:bold;">|</span>
      title = <span style="color:#996600;">''</span>
      url = <span style="color:#996600;">''</span>
      complex = <span style="color:#0000FF; font-weight:bold;">false</span>
      found = <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>page.<span style="color:#9966CC; font-weight:bold;">class</span> == <span style="color:#CC00FF; font-weight:bold;">Hash</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        complex = <span style="color:#0000FF; font-weight:bold;">true</span>
        title = page<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:title</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>_<span style="color:#006600; font-weight:bold;">/</span>,<span style="color:#996600;">' '</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        url = page<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:url</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        title = page.<span style="color:#9900CC;">to_s</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>_<span style="color:#006600; font-weight:bold;">/</span>,<span style="color:#996600;">' '</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        url = page.<span style="color:#9900CC;">to_s</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'.html'</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>current_page <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">'.html'</span> == url<span style="color:#006600; font-weight:bold;">&#41;</span>
        found = <span style="color:#0000FF; font-weight:bold;">true</span>
        crums <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> title, <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> url <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>!found <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> complex <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> page.<span style="color:#9900CC;">key</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:pages</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        subsectioncrums = breadcrums<span style="color:#006600; font-weight:bold;">&#40;</span>
          <span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> current_page,
          <span style="color:#ff3333; font-weight:bold;">:section</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page,
          <span style="color:#ff3333; font-weight:bold;">:crums</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#123;</span>:title <span style="color:#006600; font-weight:bold;">=&gt;</span> title, <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> url<span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
        <span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>subsectioncrums.<span style="color:#9900CC;">size</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          crums <span style="color:#006600; font-weight:bold;">+</span>= subsectioncrums
        <span style="color:#9966CC; font-weight:bold;">end</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">break</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span>crums.<span style="color:#9900CC;">size</span> <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> crums
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Finishing Touch</h3>
<p>Finally, to generate the static pages that we could compress and upload to the server, some good old <a href="http://www.gnu.org/software/wget/">wget</a> magic was used:</p>
<div class="hl-surround" ><div class="hl-main"><pre>&lt;br /&gt;
wget -m -nH http://localhost:3000/&lt;br /&gt;</pre></div></div></p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/02/04/use-rails-to-create-a-static-site/feed/</wfw:commentRss>
		</item>
		<item>
		<title>NSIS installer for a Ruby application - Part 1 - HM NIS wizard output</title>
		<link>http://usefulfor.com/ruby/2009/02/02/nsis-installer-for-a-ruby-application-part-1-hm-nis-wizard-output/</link>
		<comments>http://usefulfor.com/ruby/2009/02/02/nsis-installer-for-a-ruby-application-part-1-hm-nis-wizard-output/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 17:52:41 +0000</pubDate>
		<dc:creator>siebert</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[X Windows]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=77</guid>
		<description><![CDATA[I am working on an NSIS (Nullsoft Scriptable Install System) installer for a Ruby application (Dradis - check it out!). In this series I will try to keep log of how I progress with this.
I am using HM NIS editor and IDE for NSIS to make the task a little easier. To get out of [...]]]></description>
			<content:encoded><![CDATA[<p>I am working on an <a title="http://nsis.sourceforge.net" href="http://nsis.sourceforge.net">NSIS</a> (Nullsoft Scriptable Install System) installer for a Ruby application (<a title="Dradis" href="http://dradis.sourceforge.net/">Dradis</a> - check it out!). In this series I will try to keep log of how I progress with this.</p>
<p>I am using <a title="HM NIS Edit" href="http://hmne.sourceforge.net">HM NIS</a> editor and IDE for NSIS to make the task a little easier. To get out of the blocks a little quicker I used the HM NIS wizard to create a simple framework from where I will progress.<br />
<span id="more-77"></span><br />
The wizard allows you to install different components (groups). These are typically different parts of your application and dependencies that needs to be installed. I created the following components:</p>
<ul>
<li>Ruby (this will download and install the Ruby one-click installer if ruby is not installed)</li>
<li>MyGem (this will install the the required gems)</li>
<li>MyApplication (this will install my application)</li>
</ul>
<p>The wizard also lets you pick a GUI type. I picked <em>modern</em>. You can choose between <em>modern</em>, <em>classic</em> or <em>none</em>.</p>
<p>The script generated by the wizard will look something like the following (do not bother to read it all right now, I will go into detail for some parts of it):</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">; Script generated by the HM NIS Edit Script Wizard.</span>
&nbsp;
<span style="color: #666666; font-style: italic;">; HM NIS Edit Wizard helper defines</span>
<span style="color: #000066; font-weight:bold;">!define</span> PRODUCT_NAME <span style="color: #660066;">&quot;My application&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> PRODUCT_VERSION <span style="color: #660066;">&quot;1.0&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> PRODUCT_PUBLISHER <span style="color: #660066;">&quot;My company, Inc.&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> PRODUCT_WEB_SITE <span style="color: #660066;">&quot;http://www.mycompany.com&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> PRODUCT_UNINST_KEY <span style="color: #660066;">&quot;SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> PRODUCT_UNINST_ROOT_KEY <span style="color: #660066;">&quot;HKLM&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">; MUI 1.67 compatible ------</span>
<span style="color: #000066; font-weight:bold;">!include</span> <span style="color: #660066;">&quot;MUI.nsh&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">; MUI Settings</span>
<span style="color: #000066; font-weight:bold;">!define</span> <span style="color: #006600;">MUI_ABORTWARNING</span>
<span style="color: #000066; font-weight:bold;">!define</span> <span style="color: #006600;">MUI_ICON</span> <span style="color: #660066;">&quot;${NSISDIR}ContribGraphicsIconsmodern-install.ico&quot;</span>
<span style="color: #000066; font-weight:bold;">!define</span> <span style="color: #006600;">MUI_UNICON</span> <span style="color: #660066;">&quot;${NSISDIR}ContribGraphicsIconsmodern-uninstall.ico&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">; Welcome page</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_PAGE_WELCOME</span>
<span style="color: #666666; font-style: italic;">; License page</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_PAGE_LICENSE</span> <span style="color: #660066;">&quot;c:pathtolicenceYourSoftwareLicence.txt&quot;</span>
<span style="color: #666666; font-style: italic;">; Directory page</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_PAGE_DIRECTORY</span>
<span style="color: #666666; font-style: italic;">; Instfiles page</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_PAGE_INSTFILES</span>
<span style="color: #666666; font-style: italic;">; Finish page</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_PAGE_FINISH</span>
&nbsp;
<span style="color: #666666; font-style: italic;">; Uninstaller pages</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_UNPAGE_INSTFILES</span>
&nbsp;
<span style="color: #666666; font-style: italic;">; Language files</span>
<span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_LANGUAGE</span> <span style="color: #660066;">&quot;English&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">; MUI end ------</span>
&nbsp;
<span style="color: #000066;">Name</span> <span style="color: #660066;">&quot;${PRODUCT_NAME} ${PRODUCT_VERSION}&quot;</span>
<span style="color: #000066;">OutFile</span> <span style="color: #660066;">&quot;Setup.exe&quot;</span>
<span style="color: #000066;">InstallDir</span> <span style="color: #660066;">&quot;$PROGRAMFILESMy application&quot;</span>
<span style="color: #000066;">ShowInstDetails</span> <span style="color: #ff6600;">show</span>
<span style="color: #000066;">ShowUnInstDetails</span> <span style="color: #ff6600;">show</span>
&nbsp;
<span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;Ruby&quot;</span> SEC01
<span style="color: #000066;">SectionEnd</span>
&nbsp;
<span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;MyGem&quot;</span> SEC02
<span style="color: #000066;">SectionEnd</span>
&nbsp;
<span style="color: #000066;">Section</span> <span style="color: #660066;">&quot;MyApplication&quot;</span> SEC03
<span style="color: #000066;">SectionEnd</span>
&nbsp;
<span style="color: #000066;">Section</span> -AdditionalIcons
  <span style="color: #000099;">SetOutPath</span> <span style="color: #660000;">$INSTDIR</span> 
  <span style="color: #000099;">WriteIniStr</span> <span style="color: #660066;">&quot;$INSTDIR${PRODUCT_NAME}.url&quot;</span> <span style="color: #660066;">&quot;InternetShortcut&quot;</span> <span style="color: #660066;">&quot;URL&quot;</span> <span style="color: #660066;">&quot;${PRODUCT_WEB_SITE}&quot;</span>
  <span style="color: #000099;">CreateDirectory</span> <span style="color: #660066;">&quot;$SMPROGRAMSMy application&quot;</span>
  <span style="color: #000099;">CreateShortCut</span> <span style="color: #660066;">&quot;$SMPROGRAMSMy applicationWebsite.lnk&quot;</span> <span style="color: #660066;">&quot;$INSTDIR${PRODUCT_NAME}.url&quot;</span>
  <span style="color: #000099;">CreateShortCut</span> <span style="color: #660066;">&quot;$SMPROGRAMSMy applicationUninstall.lnk&quot;</span> <span style="color: #660066;">&quot;$INSTDIRuninst.exe&quot;</span>
<span style="color: #000066;">SectionEnd</span>
&nbsp;
<span style="color: #000066;">Section</span> -Post
  <span style="color: #000099;">WriteUninstaller</span> <span style="color: #660066;">&quot;$INSTDIRuninst.exe&quot;</span>
  <span style="color: #000099;">WriteRegStr</span> <span style="color: #660000;">$<span style="">&#123;</span>PRODUCT_UNINST_ROOT_KEY<span style="">&#125;</span></span> <span style="color: #660066;">&quot;${PRODUCT_UNINST_KEY}&quot;</span> <span style="color: #660066;">&quot;DisplayName&quot;</span> <span style="color: #660066;">&quot;$(^Name)&quot;</span>
  <span style="color: #000099;">WriteRegStr</span> <span style="color: #660000;">$<span style="">&#123;</span>PRODUCT_UNINST_ROOT_KEY<span style="">&#125;</span></span> <span style="color: #660066;">&quot;${PRODUCT_UNINST_KEY}&quot;</span> <span style="color: #660066;">&quot;UninstallString&quot;</span> <span style="color: #660066;">&quot;$INSTDIRuninst.exe&quot;</span>
  <span style="color: #000099;">WriteRegStr</span> <span style="color: #660000;">$<span style="">&#123;</span>PRODUCT_UNINST_ROOT_KEY<span style="">&#125;</span></span> <span style="color: #660066;">&quot;${PRODUCT_UNINST_KEY}&quot;</span> <span style="color: #660066;">&quot;DisplayVersion&quot;</span> <span style="color: #660066;">&quot;${PRODUCT_VERSION}&quot;</span>
  <span style="color: #000099;">WriteRegStr</span> <span style="color: #660000;">$<span style="">&#123;</span>PRODUCT_UNINST_ROOT_KEY<span style="">&#125;</span></span> <span style="color: #660066;">&quot;${PRODUCT_UNINST_KEY}&quot;</span> <span style="color: #660066;">&quot;URLInfoAbout&quot;</span> <span style="color: #660066;">&quot;${PRODUCT_WEB_SITE}&quot;</span>
  <span style="color: #000099;">WriteRegStr</span> <span style="color: #660000;">$<span style="">&#123;</span>PRODUCT_UNINST_ROOT_KEY<span style="">&#125;</span></span> <span style="color: #660066;">&quot;${PRODUCT_UNINST_KEY}&quot;</span> <span style="color: #660066;">&quot;Publisher&quot;</span> <span style="color: #660066;">&quot;${PRODUCT_PUBLISHER}&quot;</span>
<span style="color: #000066;">SectionEnd</span>
&nbsp;
<span style="color: #000066;">Function</span> <span style="color: #006600;">un.onUninstSuccess</span>
  <span style="color: #000099;">HideWindow</span>
  <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_ICONINFORMATION</span>|MB_OK <span style="color: #660066;">&quot;$(^Name) was successfully removed from your computer.&quot;</span>
<span style="color: #000066;">FunctionEnd</span>
&nbsp;
<span style="color: #000066;">Function</span> <span style="color: #006600;">un.onInit</span>
  <span style="color: #000099;">MessageBox</span> <span style="color: #ff6600;">MB_ICONQUESTION</span>|MB_YESNO|MB_DEFBUTTON2 <span style="color: #660066;">&quot;Are you sure you want to completely remove $(^Name) and all of its components?&quot;</span> <span style="color: #ff6600;">IDYES</span> +<span style="">2</span>
  <span style="color: #000099;">Abort</span>
<span style="color: #000066;">FunctionEnd</span>
&nbsp;
<span style="color: #000066;">Section</span> Uninstall
  <span style="color: #000099;">Delete</span> <span style="color: #660066;">&quot;$INSTDIR${PRODUCT_NAME}.url&quot;</span>
  <span style="color: #000099;">Delete</span> <span style="color: #660066;">&quot;$INSTDIRuninst.exe&quot;</span>
&nbsp;
  <span style="color: #000099;">Delete</span> <span style="color: #660066;">&quot;$SMPROGRAMSMy applicationUninstall.lnk&quot;</span>
  <span style="color: #000099;">Delete</span> <span style="color: #660066;">&quot;$SMPROGRAMSMy applicationWebsite.lnk&quot;</span>
&nbsp;
  <span style="color: #000099;">RMDir</span> <span style="color: #660066;">&quot;$SMPROGRAMSMy application&quot;</span>
&nbsp;
&nbsp;
&nbsp;
  <span style="color: #000099;">DeleteRegKey</span> <span style="color: #660000;">$<span style="">&#123;</span>PRODUCT_UNINST_ROOT_KEY<span style="">&#125;</span></span> <span style="color: #660066;">&quot;${PRODUCT_UNINST_KEY}&quot;</span>
  <span style="color: #000099;">SetAutoClose</span> <span style="color: #ff6600;">true</span>
<span style="color: #000066;">SectionEnd</span></pre></div></div>

<p>The first thing to get you head around here is the general layout of a NSIS script and how this maps to the final installer. For a thorough read on this refer to section <a href="http://nsis.sourceforge.net/Docs/Chapter2.html#2.3">2.3 Scripting structure</a> in the NSIS User Manual. As a brief overview:</p>
<ul>
<li><em>Compiler commands</em><br />
The instructions that start with ! (exclamation mark) are compiler commands. These commands are executed on compile time.</li>
<li><em>Installer attributes</em><br />
Close to the top of your script you will note a few installer attributes that are defined. For example:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066;">Name</span> <span style="color: #660066;">&quot;${PRODUCT_NAME} ${PRODUCT_VERSION}&quot;</span>
<span style="color: #000066;">OutFile</span> <span style="color: #660066;">&quot;Setup.exe&quot;</span>
<span style="color: #000066;">InstallDir</span> <span style="color: #660066;">&quot;$PROGRAMFILESMy application&quot;</span></pre></div></div>

<p>These attributes are used and referenced later in the installation process</li>
<li><em>Installer pages</em><br />
A non silent installer consist of different pages. These pages will mostly be taken care of by the GUI interface that you picked. The predefined GUI pages that are used are specified by the <em>!insertmacro</em> directives. For example:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;">!insertmacro</span> <span style="color: #006600;">MUI_PAGE_WELCOME</span></pre></div></div>

<p>specifies that the modern GUI&#8217;s welcome page should be inserted.</li>
<li><em>Sections</em><br />
You will note that chunks of the script are wrapped by the <em>Section </em>and <em>SectionEnd</em> directives. These mostly correspond to different components of your application to be installed.<br />
In my example you will note sections for <em>Ruby</em>, <em>MyGem</em> and <em>MyApplication</em>. You will also notice some sections that start with <em>un.</em> These sections are called during uninstall.<br />
The code inside a section are executed on the machine that the installer is being run on. Sections are executed in the order as they appear in the code.</li>
<li><em>Functions</em><br />
Functions are pieces of script code that are called either from within sections by using <em>Call functionName</em> or they are called at different points in the script execution as Callback functions. For example <em>.onInit </em>will be called when the installer is initiated.</li>
</ul>
<p>When you defined your application&#8217;s different components in the wizard you were allowed to specify the different files that should be installed. These files are referenced in the install and uninstall sections. In the install sections you will note something similar to:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000099;">SetOutPath</span> <span style="color: #660066;">&quot;$INSTDIRmy_folder&quot;</span>
<span style="color: #000099;">File</span> <span style="color: #660066;">&quot;application_filesmyapplication.rb&quot;</span></pre></div></div>

<p>The first line specifies that what follows after that line (<em>File &#8220;application_files\myapplication.rb&#8221;</em>) should be applied to the <em>$INSTDIR\my_folder </em>directory. It effectively changes the current directory path. The second line<em> </em>instructs the installer to copy the file located at <em>application_files\myapplication.rb</em> to the current path.</p>
<p>In the uninstall section you will note code that is similar to:</p>

<div class="wp_syntax"><div class="code"><pre class="nsis" style="font-family:monospace;"><span style="color: #000099;">Delete</span> <span style="color: #660066;">&quot;$INSTDIRmy_foldermyapplication.rb&quot;</span>
<span style="color: #000099;">RMDir</span> <span style="color: #660066;">&quot;$INSTDIRmy_folder&quot;</span></pre></div></div>

<p>It instructs the uninstaller to delete the file at <em>$INSTDIR\my_folder\myapplication.rb</em> and remove the folder <em>$INSTDIR\my_folder</em>.</p>
<p>I am going to leave it at that. In the next post I&#8217;ll describe how I install Ruby and the required gem on running the installer.</p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/02/02/nsis-installer-for-a-ruby-application-part-1-hm-nis-wizard-output/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Unit testing your Ruby on Rails plugin</title>
		<link>http://usefulfor.com/ruby/2009/01/22/unit-testing-your-ruby-on-rails-plugin/</link>
		<comments>http://usefulfor.com/ruby/2009/01/22/unit-testing-your-ruby-on-rails-plugin/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 10:51:40 +0000</pubDate>
		<dc:creator>siebert</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=74</guid>
		<description><![CDATA[So you want to write some tests for your hot new Rails plugin that extends the behaviour of a ActiveRecord model? The thing is - for it to be decent tests it needs to be functional outside of the context of you Rails application, so you need to create a temporary testing environment. I think [...]]]></description>
			<content:encoded><![CDATA[<p>So you want to write some tests for your hot new Rails plugin that extends the behaviour of a ActiveRecord model? The thing is - for it to be decent tests it needs to be functional outside of the context of you Rails application, so you need to create a temporary testing environment. I think there is a few ways to this but the following is what I did.<br />
<span id="more-74"></span></p>
<p>In the plugin <em>test</em> folder I created a <em>lib</em> and a <em>fixtures</em> folder. In the <em>lib</em> folder I created two files <code>activerecord_connector.rb</code> and <code>activerecord_test.rb.</code></p>
<p><strong>acticerecord_connector.rb:</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>require &quot;rubygems&quot;
require &quot;active_record&quot;
require 'active_record/fixtures'

conf = YAML::load(File.open(File.dirname(__FILE__) + '/../database.yml'))
ActiveRecord::Base.establish_connection(conf['sqlite3'])</pre></div></div>
<p>This file is required to make a connection to the database that is configured by <code>database.yml</code> that I placed in the <em>test</em> folder.</p>
<p><strong>database.yml:</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>sqlite3:
  database: &quot;:memory:&quot;
  adapter: sqlite3
  timeout: 500</pre></div></div>
<p>This specifies a connection to a Sqlite database that is to be kept in memory. It means the database is just alive for the duration of our test - perfect.</p>
<p><strong>activerecord_test.rb</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>require 'test/lib/activerecord_connector'
require 'test/fixtures/schema.rb'

class ActiverecordTest &amp;lt; Test::Unit::TestCase
  FIXTURES_PTH = File.join(File.dirname(__FILE__), '/../fixtures')
  dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
  dep.load_paths.unshift FIXTURES_PTH
end</pre></div></div>
<p>The code in this file does the following:</p>
<ul>
<li>It requires <code>activerecord_connector</code>.</li>
<li>Requires a <code>schema.rb</code> file for populating the database.</li>
<li>Defines the <em>ActiverecordTest</em> class that define and store the path to your <em>fixtures</em> folder.</li>
</ul>
<p><strong>schema.rb:</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>ActiveRecord::Schema.define do
  create_table &quot;users&quot;, :force =&amp;gt; true do |t|
    t.string   &quot;first_name&quot;
    t.string   &quot;last_name&quot;
    t.integer &quot;id&quot;
  end
end</pre></div></div>
<p>As you can see, this creates the <em>users</em> table in the database.</p>
<p>I created a User model that is stored in the <em>fixtures</em> folder.</p>
<p><strong>user.rb</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>class User &amp;lt; ActiveRecord::Base
  #this class might be extended by your plugin
end</pre></div></div>
<p>Also in the <em>fixtures</em> folder is a <code>users.yml</code> file to serve as test content in our database.</p>
<p><strong>users.yml</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>david:
  id: 1
  first_name: Thomas
  last_name: Black

jamis:
  id: 2
  first_name: Peter
  last_name: Martin</pre></div></div>
<p>Lastly we have our test file.</p>
<p><strong>hot_plugin_test.rb</strong></p>
<div class="hl-surround" ><div class="hl-main"><pre>require 'test/unit'
require 'test/lib/activerecord_test'

class HotPluginTest &amp;lt; ActiverecordTest

  def setup
    Fixtures.create_fixtures(FIXTURES_PTH, 'users')
  end

  def test_users
    user = User.find(:first)
    assert_equal &quot;Thomas&quot;, user.login, &quot;not working!!&quot;
  end
end</pre></div></div>
<ul>
<li><em>HotPluginTest</em> inherits from <em>ActiveRecordTest</em>.</li>
<li>The <em>setup</em> method creates the content in our database from the <code>users.yml</code> file.</li>
</ul>
<p>Now you can extend models that you place in the <em>fixtures </em>folder with your plugin and run tests against them in <em>HotPluginTest</em>.</p>
<p>As I said at the start, this is just a method of doing it - you might have some other ideas. I&#8217;ll be happy to hear about them. For another approach you might want to look at <a href="http://wiki.pluginaweek.org/Plugin_test_helper">Plugin Test Helper</a>.</p>
<p>Happy testing!</p>
<p>My credit to the following posts and plugin for leading to this solution:</p>
<ul>
<li><a href="http://www.alexyoung.org/articles/show/44/rails_plugin_testing_guide">Rails Plugin Testing Guide</a></li>
<li><a href="http://www.agileadvisor.com/2008/01/using-activerecord-outside-rails.html">Using ActiveRecord outside Rails</a></li>
<li><a href="http://wiki.github.com/mislav/will_paginate">will_paginate</a> plugin that has a great test example</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/01/22/unit-testing-your-ruby-on-rails-plugin/feed/</wfw:commentRss>
		</item>
		<item>
		<title>extjs ComboBox remote XML</title>
		<link>http://usefulfor.com/ruby/2008/11/12/extjs-combobox-remote-xml/</link>
		<comments>http://usefulfor.com/ruby/2008/11/12/extjs-combobox-remote-xml/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 23:33:47 +0000</pubDate>
		<dc:creator>etd</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=72</guid>
		<description><![CDATA[The new release of dradis is going to use the ExtJS library for the web interface. ExtJS provides lots of JavaScript widgets useful to create complex GUI for web applications.
This is the first of a series of posts with small tips and tricks of ExtJS that will also address its integration with Ruby on Rails. [...]]]></description>
			<content:encoded><![CDATA[<p>The new release of <a href="http://dradis.sourceforge.net/">dradis</a> is going to use the <a href="http://extjs.com/products/extjs/">ExtJS</a> library for the web interface. ExtJS provides lots of JavaScript widgets useful to create complex GUI for web applications.</p>
<p>This is the first of a series of posts with small tips and tricks of ExtJS that will also address its integration with Ruby on Rails. </p>
<p>In this release we are going to create a ComboBox that loads its items from a remote location (potentially a rails REST endpoint).</p>
<p><span id="more-72"></span></p>
<p>I wanted to create this series when I started using ExtJS so it could be used as a step-by-step howto of ExtJS and rails, but as sometimes happens, I got carried away with the coding side of things leaving the post writing abandoned :(. That is the main reason why some core concepts of ExtJS development are not included here. The project site, documentation and samples can help with that. Here we are dealing with the real stuff, so lets get it on.</p>
<p>First the code: <a href="http://usefulfor.com/ruby/files/2008/11/extjs-comboxml.tar.bz2">extjs-comboxml.tar.bz2</a>. I have a local apache for debuging purposes and I uncompressed the ExtJS package in <code>/var/www/ext-2.2/</code>, then I created a <code>test</code> folder inside it. This code should work fine if you uncompress its contents in the test folder. If you have a different environment, adjust the locations of the <strong>script</strong> tags in the header of <code>combo.html</code>.</p>
<p>This is how it should look like:<br />
<img src="http://usefulfor.com/ruby/files/2008/11/extjs-comboxml.png" alt="" width="370" height="105" class="centered size-full wp-image-73" /><br />
So with ExtJS there are two ways of loading combo items from a remote location, it is a bit confusing because these two are called <strong>local</strong> and <strong>remote</strong> modes. The difference is that in <strong>local</strong> mode, the combo is relying on someone else to grab the information and in <strong>remote</strong> mode the combo itself will make the Ajax call.</p>
<p>No matter what mode we choose, we will need a data store for our items. Here is the code used in the example:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">var </span><span class="hl-identifier">categories</span><span class="hl-default"> = </span><span class="hl-reserved">new </span><span class="hl-identifier">Ext</span><span class="hl-default">.</span><span class="hl-identifier">data</span><span class="hl-default">.</span><span class="hl-identifier">Store</span><span class="hl-brackets">({
        </span><span class="hl-identifier">url</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">categories.xml</span><span class="hl-quotes">'</span><span class="hl-code">,
        </span><span class="hl-identifier">autoLoad</span><span class="hl-code">: </span><span class="hl-reserved">true</span><span class="hl-code">, </span><span class="hl-comment">// required for the combo that does not use Ajax
        </span><span class="hl-identifier">reader</span><span class="hl-code">: </span><span class="hl-reserved">new </span><span class="hl-identifier">Ext</span><span class="hl-code">.</span><span class="hl-identifier">data</span><span class="hl-code">.</span><span class="hl-identifier">XmlReader</span><span class="hl-brackets">(
                { </span><span class="hl-identifier">record</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">category</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">id</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">id</span><span class="hl-quotes">'</span><span class="hl-brackets">}</span><span class="hl-code">,
                </span><span class="hl-brackets">[ { </span><span class="hl-identifier">name</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">name</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">type</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">string</span><span class="hl-quotes">' </span><span class="hl-brackets">} ]
              )</span><span class="hl-code">,
        </span><span class="hl-identifier">listeners</span><span class="hl-code">: </span><span class="hl-brackets">{
          </span><span class="hl-identifier">load</span><span class="hl-code">: </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">records</span><span class="hl-code">, </span><span class="hl-identifier">options</span><span class="hl-brackets">) {
            </span><span class="hl-identifier">console</span><span class="hl-code">.</span><span class="hl-identifier">log</span><span class="hl-brackets">( </span><span class="hl-quotes">'</span><span class="hl-string">loaded </span><span class="hl-quotes">'</span><span class="hl-code"> + </span><span class="hl-identifier">records</span><span class="hl-code">.</span><span class="hl-identifier">totalLength</span><span class="hl-code"> + </span><span class="hl-quotes">'</span><span class="hl-string"> records</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
          </span><span class="hl-brackets">}</span><span class="hl-code">,
          </span><span class="hl-identifier">loadexception</span><span class="hl-code">: </span><span class="hl-reserved">function</span><span class="hl-brackets">(</span><span class="hl-identifier">proxy</span><span class="hl-code">, </span><span class="hl-identifier">options</span><span class="hl-code">, </span><span class="hl-identifier">response</span><span class="hl-code">, </span><span class="hl-identifier">error</span><span class="hl-brackets">) {
            </span><span class="hl-identifier">console</span><span class="hl-code">.</span><span class="hl-identifier">log</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">error loading records from server:</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code">;
            </span><span class="hl-identifier">console</span><span class="hl-code">.</span><span class="hl-identifier">log</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">file: </span><span class="hl-quotes">&quot;</span><span class="hl-code">+</span><span class="hl-identifier">error</span><span class="hl-code">.</span><span class="hl-identifier">fileName</span><span class="hl-brackets">)</span><span class="hl-code">;
            </span><span class="hl-identifier">console</span><span class="hl-code">.</span><span class="hl-identifier">log</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-special">\t</span><span class="hl-string">line: </span><span class="hl-quotes">&quot;</span><span class="hl-code">+</span><span class="hl-identifier">error</span><span class="hl-code">.</span><span class="hl-identifier">lineNumber</span><span class="hl-brackets">)</span><span class="hl-code">;
          </span><span class="hl-brackets">}
        }
      })</span><span class="hl-default">;</span></pre></div></div>
<p>The listeners in the code above are just for debuging purposes and can be removed safely. The only interesting bit is the <strong>autoLoad</strong> option, but we will come back to that later. For now it is enough to say that the Store above will read an XML document with this structure:<br />
<code><br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;categories type="array"&gt;<br />
  &lt;category&gt;<br />
    &lt;id type="integer"&gt;1&lt;/id&gt;<br />
    &lt;name&gt;default category&lt;/name&gt;<br />
  &lt;/category&gt;<br />
  &lt;category&gt;<br />
    &lt;id type="integer"&gt;2&lt;/id&gt;<br />
    &lt;name&gt;security risk&lt;/name&gt;<br />
  &lt;/category&gt;<br />
&lt;/categories&gt;<br />
</code></p>
<p>The <code>autoLoad</code> config options determines if the data store will try to load the values from the provided url upon creation or if it will be necessary to call the <code>load()</code>. This is useful when we are working in <strong>local</strong> mode, let&#8217;s see the code for the first combo:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">var </span><span class="hl-identifier">comboLocal</span><span class="hl-default"> = </span><span class="hl-reserved">new </span><span class="hl-identifier">Ext</span><span class="hl-default">.</span><span class="hl-identifier">form</span><span class="hl-default">.</span><span class="hl-identifier">ComboBox</span><span class="hl-brackets">({
  </span><span class="hl-identifier">fieldLabel</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">Select a category</span><span class="hl-quotes">'</span><span class="hl-code">,
  </span><span class="hl-identifier">store</span><span class="hl-code">: </span><span class="hl-identifier">categories</span><span class="hl-code">,
  </span><span class="hl-identifier">mode</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">local</span><span class="hl-quotes">'</span><span class="hl-code">,
  </span><span class="hl-identifier">displayField</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">name</span><span class="hl-quotes">'</span><span class="hl-code">,
  </span><span class="hl-identifier">selectOnFocus</span><span class="hl-code">: </span><span class="hl-reserved">true</span><span class="hl-code">,
  </span><span class="hl-identifier">emptyText</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">No Ajax in the combo...</span><span class="hl-quotes">'
</span><span class="hl-brackets">})</span><span class="hl-default">;</span></pre></div></div>
<p>Above we specified <strong>local</strong> this means that options for this combo will be loaded from the <code>categories</code> store. The data store is expected to be populated already, this can be done either by specifying the <strong>autoLoad</strong> option as described above or by calling the <code>load()</code>.</p>
<p>If you rather have you combo performing the Ajax request, then the code you need to use is:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">var </span><span class="hl-identifier">comboRemote</span><span class="hl-default"> = </span><span class="hl-reserved">new </span><span class="hl-identifier">Ext</span><span class="hl-default">.</span><span class="hl-identifier">form</span><span class="hl-default">.</span><span class="hl-identifier">ComboBox</span><span class="hl-brackets">({
  </span><span class="hl-identifier">fieldLabel</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">Select a category</span><span class="hl-quotes">'</span><span class="hl-code">,
  </span><span class="hl-identifier">store</span><span class="hl-code">: </span><span class="hl-identifier">categories</span><span class="hl-code">,
  </span><span class="hl-identifier">displayField</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">name</span><span class="hl-quotes">'</span><span class="hl-code">,
  </span><span class="hl-identifier">triggerAction</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">all</span><span class="hl-quotes">'</span><span class="hl-code">,
  </span><span class="hl-identifier">selectOnFocus</span><span class="hl-code">: </span><span class="hl-reserved">true</span><span class="hl-code">,
  </span><span class="hl-identifier">emptyText</span><span class="hl-code">: </span><span class="hl-quotes">'</span><span class="hl-string">Options loaded using Ajax...</span><span class="hl-quotes">'
</span><span class="hl-brackets">})</span><span class="hl-default">;</span></pre></div></div>
<p>There is no need to include <code>mode: 'remote'</code> because is the default behaviour, here the trick is to include the <code>triggerAction: 'all'</code>, otherwise the Ajax request will never be executed.</p>
<p>So that was it, short and simple, stay tuned for the next one <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p>
]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2008/11/12/extjs-combobox-remote-xml/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
