<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>usefulfor.com/ruby &#187; Ruby</title>
	<atom:link href="http://usefulfor.com/ruby/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://usefulfor.com/ruby</link>
	<description>ruby goodness for your daily needs</description>
	<lastBuildDate>Mon, 07 Dec 2009 23:20:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<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) &#8211; <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 &#8211; <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 &#8211; <em>@controller.request_service(:model_add_node, &#8230;)</em></li>
<li>add a category &#8211; <em>@controller.request_service(:model_add_category, &#8230;)</em></li>
<li>get the contents of a node &#8211; <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 &#8211; To implement our extension we need to extend the <em>Extensions</em> module</li>
<li>line 2 &#8211; We define our class to inherit from the <em>Extensions::Simple</em> class</li>
<li>lines 4-11 &#8211; 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 &#8211; 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 &#8211; Different that in the previous example we define this extension to inherit from the <em>Extensions::Namespace</em> class</li>
<li>line 7 &#8211; 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 &#8211; 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 &#8211; States that the parameter is compulsary</li>
<li>line 15 &#8211; This is the displayed name of the parameter</li>
<li>line 16 &#8211; Defines the description of the command that will be printed in the help display of the command</li>
<li>line 17 &#8211; Specifies the regular expression by which the parameter will be validated by the command launcher</li>
<li>lines 42-55 &#8211; This is the implementation of the commands as defined in the <em>INFO</em> hash</li>
<li>line 44 &#8211; 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 &#8211; 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 &#8211; 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 &#8211; Happy dradis coding!</p>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=84&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/02/17/dradis-extensions-how-they-work-and-how-to-write-them/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSIS installer for a Ruby application &#8211; Part 3 &#8211; 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>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=82&type=feed" alt="" />]]></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>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSIS installer for a Ruby application &#8211; Part 2 &#8211; 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>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=78&type=feed" alt="" />]]></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>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSIS installer for a Ruby application &#8211; Part 1 &#8211; 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 &#8211; 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> &#8211; 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>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=77&type=feed" alt="" />]]></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>
		<slash:comments>2</slash:comments>
		</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 &#8211; 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 &#8211; 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 &#8211; 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 &#8211; 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>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=74&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2009/01/22/unit-testing-your-ruby-on-rails-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</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 <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> . 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>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=72&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2008/11/12/extjs-combobox-remote-xml/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rails Conf 2008</title>
		<link>http://usefulfor.com/ruby/2008/09/11/rails-conf-2008/</link>
		<comments>http://usefulfor.com/ruby/2008/09/11/rails-conf-2008/#comments</comments>
		<pubDate>Thu, 11 Sep 2008 11:02:57 +0000</pubDate>
		<dc:creator>siebert</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=71</guid>
		<description><![CDATA[I attended Rails Conf 2008 in Berlin on the 3rd and 4th of September 2008. Following is a quick summary of the talks that I attended. There are loads interesting things going on in the Rails community. My opinion is very biased but I believe the Ruby on Rails community is setting the bar on [...]]]></description>
			<content:encoded><![CDATA[<p>I attended Rails Conf 2008 in Berlin on the 3rd and 4th of September 2008. Following is a quick summary of the talks that I attended. There are loads interesting things going on in the Rails community. My opinion is very biased but I believe the Ruby on Rails community is setting the bar on future web development. And I think this both the case for the techniques and approaches that is practised by these developers and equally the Ruby on Rails framework that is the result of this.<br />
<span id="more-71"></span></p>
<p><!--[if gte mso 9]&amp;gt;  Normal 0   false false false        MicrosoftInternetExplorer4  &amp;lt;![endif]--><!--[if gte mso 9]&amp;gt;   &amp;lt;![endif]--> <strong>Key note – David Heinemeier Hansson</strong></p>
<p>David is the creator of the Rails framework and obviously a bit of a celebrity. Interestingly enough I get the idea that he is not the highest contributor to the Rails code base – I appears to be Jeremy Kemper which is his colleague at 37signals (the company behind Ruby on Rails).</p>
<p>David delivered the keynote on Wednesday morning. The key note was on legacy code. Initially I thought – “What a boring subject” and then later I caught myself thinking – “Now you are talking a load of nonsense” and two thirds into it I was happy to admit – “Hey, you really have been thinking about this a lot”.</p>
<p>Maybe it is a sentiment that only or mostly developers can associate with but very often you look back onto code and refer to it very cynically as “Legacy” code. He’s argument was that “legacy” code is a result of progress in environment and personal growth (Sounds like a psychiatry session – I know – It did get better). He carried on by making suggestions as to how legacy code should be dealt with and then showed a few examples in Rails. Some thoughts suggestion:</p>
<ul>
<li>The worst mistake that a company can make is to decide to simply rewrite legacy code on impulse.</li>
<li>Legacy code should be put through iterations to improve it – They have a rule in their company that you should always leave code in a better state than what you found it in.</li>
<li>Be careful of judging code as legacy due to a change in personal taste.</li>
<li>Keep in mind that the code you write today will become legacy – face the facts.</li>
</ul>
<p>Rails developers make a big deal out of DRY (Do Not Repeat Yourself). It implies that functionality should not unnecessarily be repeated in your code. The rule of thumb is that if you have found yourself copy and pasting for the 3rd time then its time to DRY-up your code. His point was that very DRY code makes it sometimes difficult to extend the code and this can make the improvement of legacy code difficult. A bit of repetition in your code is thus not a bad thing.</p>
<p>A thought that came to my mind was – “How should the IT security consultant look at (or judge) legacy code. Firstly, code tested 2 years ago and stamped as secure might not be secure anymore (new techniques, new vulnerabilities). What, or rather, is there a recommendation on re-testing or frequency on re-testing? Secondly, what is the recommendation on finding holes in legacy code? As mentioned rewriting code is not always (very seldom) the viable solution. How should a client maintain a legacy code base from a security point of view?</p>
<p><strong>When to tell your kids about presentation caching – Matthew Deiters</strong></p>
<p>You have all heard about the 20/80 rule. You wear 20% of your clothes 80% of the time. 20% of the world’s population own 80% of the wealth. And so it turns out that 20% of an application resources are being requested 80% of the time and 80% of the http request time are being spent on the wire &#8211; thus the argument for caching and a few other tricks to speed things up.</p>
<p>From my notes and memory the following are the major points:</p>
<ul>
<li>Rails supports ETags. The application responds with an ETag in the HTTP header when a request has been made for specific resource. The browser caches the ETag and the contents. When requesting the same resource in future it sends the ETag back the server. This allows the server to check if anything on the resource has changed since the last request associated with the ETag. If it is still the same it responds with “not modified” (that take is quicker to process and send) and the browser just displays the old version.</li>
<li>Rails also supports static asset time stamping. This allows browser caching to be done based on a timestamp in the static asset request string.</li>
<li>Rails has setting “perform_caching true” that combines .js files into a single file and makes the download time quicker.</li>
<li>You can also configure your web server to gzip certain assets.</li>
<li>Because most web browsers only allows for 2 connections to run simultaneously to a single server there are advantages in distributing you static assets across multiple servers.</li>
</ul>
<p>All of the above have their little tricks and limitations that are worth investigating on implementation.</p>
<p><strong>Intellectual Scalability &#8211; Solving a Large Problem With Multiple Cooperating Rails Apps &#8211; Frederick Cheung (Texperts), Paul Butcher (Texperts)</strong></p>
<p>This was one of two presentations on serving multiple applications through a single front-end. In this case the developers designed a JavaScript heavy UI framework that presents the multiple allocations through a single front-end interface. Each application is presented in the front-end through what they call a widget. The power of the framework is in the code and a full (even partial) understanding requires a demonstration. I am making contact with the guy to see if they are willing to share the code. He did mention that they will release it publicly if there is interest.</p>
<p>Slides at <a title="http://assets.en.oreilly.com/1/event/13/Intellectual Scalability - Solving a Large Problem With Multiple Cooperating Rails Apps Presentation.ppt" href="http://assets.en.oreilly.com/1/event/13/Intellectual Scalability - Solving a Large Problem With Multiple Cooperating Rails Apps Presentation.ppt">http://assets.en.oreilly.com/1/event/13/Intellectual Scalability &#8211; Solving a Large Problem With Multiple Cooperating Rails Apps Presentation.ppt</a></p>
<p><strong>Offline Rails Applications with Google Gears and Adobe AIR &#8211; Till Vollmer (MindMeister/Codemart GmbH)</strong></p>
<p>(My notes are becoming increasingly less and I am not going to write a lot about this)<br />
This was more a Google Gears talk than a Rails talk. I have never bothered to actually have a look at Google Gears but this guy had a good talk on how they implemented it from an architectural point of view.</p>
<p>You basically design your web application to be able to operate when you are offline. You have a local SQLite database that you use when going offline and this is synchronised back to the server when you go back online. There is obviously at lot to manage:</p>
<ul>
<li>Detect on-line/off-line status</li>
<li>Clashes when local db and server are not compatible on synchronisation.</li>
</ul>
<p>My biggest thought during this talk was the amount of havoc that you can cause when the contents of the SQLite db is not validated before the automated synchronisation to the server db takes place. I think it is worth looking at.</p>
<p><strong>Security on Rails &#8211; Jonathan Weiss (Peritor GmbH)</strong></p>
<p>This is a German chap that is (amongst others) an IT security consultant. It had nothing too new about the web application security stuff – XSS, SQL injection and XSRF. He discussed in each case how this should be prevented in Rails. It was reassuring to note that our Rails development is up to his standards.</p>
<p>The interesting part of his talk was on how to finger print a Rails application. I will leave you with his slides to have a look at that: <a title="http://assets.en.oreilly.com/1/event/13/Security on Rails Presentation.pdf" href="http://assets.en.oreilly.com/1/event/13/Security on Rails Presentation.pdf">http://assets.en.oreilly.com/1/event/13/Security%20on%20Rails%20Presentation.pdf</a></p>
<p>Few other important things:</p>
<ul>
<li>Rails 2 and greater by default uses the cookie to store the session state (you can change this). This cookie is just Base64 encoded and should thus not be used to store sensitive data. A hash of the data and a secret key (you can configure this) is also stored in the cookie and this is used to check the authenticity of a cookie when send back to the server.</li>
<li>Some plugins to look at: saveERB, XSS shield and tidy_library.</li>
<li>Often times (and this is the case in some trusted plugins) the user session is not reset on logout – check for this.</li>
<li>Rails 2.1 and smaller &#8211; Despite the parameterise ability of the ActiveRecord class the limit and offset parameters in the find method where not typecased. This leaves the door open for SQL injections. This was fixed but the MySQL adapter still appears vulnerable.</li>
<li>Mass assignment (user = User.create(params) can allow for great havoc if the malicious user send extra parameters in the post request that relates for example to the user level. Use attr_protected and attr_accessible</li>
<li>DOS attacks can be launched against file upload functionalities by sending very big files. Use the web server to handle file uploads or use the web server direct the request to another application to deal with file uploads.</li>
</ul>
<p>I spoke to the guy afterwards to get an idea on what his opinion is on Rails’ maturity in terms of security. I mentioned a certain ‘trust’ in PHP due to the time it has had to mature. His reply was that Rails has been developed from a much better security perspective than Rails and is more mature to his standards.</p>
<p><strong>Functional Testing Lessons Learned &#8211; Jay Fields (DRW Trading)</strong></p>
<p>Jay mainly looked at the following three points:</p>
<ul>
<li>The place and role of writing tests</li>
<li>Comparing different test suites</li>
<li>Different types of tests</li>
</ul>
<p>He stressed the importance of testing and the purpose thereof. It is especially applicable in environments where code improvements, refactoring and growth is a constant occurrence. Testing plays a central role in making sure that the result of these actions does not break the code and that breaks in the code can be indentified as soon as possible. From a certain perspective testing is a way to document the functionality and purpose of code.</p>
<p>I picked up on the following statements two statements that I felt creates a great perspective:</p>
<ul>
<li>Testing code is just as important as application code.</li>
<li>Tests should be created that provides a positive return on investment</li>
</ul>
<p>An important point is that testing does not replace the need for manual testing – it does not replace a QA team or a testing team. Automated tests might test the intended functionality but the perspective from a person that is not involved in the development is needed.</p>
<p>The Rails framework encourages two testing approaches – Unit testing and Functional testing. Unit testing has to do with testing classes in isolation by simulating the functionality of dependencies to the outside of the class. Functional testing has to do with testing functionalities that is presented by the integration of different units. Have a look at his blog entry <a title="http://blog.jayfields.com/2007/09/rails-how-we-test.html" href="http://blog.jayfields.com/2007/09/rails-how-we-test.html">http://blog.jayfields.com/2007/09/rails-how-we-test.html</a> for more thoughts on this.</p>
<p>Other test types include integration tests, smoke tests, use case tests and automated browsers tests. I’ll leave it up to the reader to investigate these further.</p>
<p>Three testing suites were discussed:</p>
<ul>
<li>RSpec</li>
<li>test/unit</li>
<li>Selenium</li>
</ul>
<p>The factors to take into account when choosing a test suite are:</p>
<ul>
<li>Ease and simplicity of implementation</li>
<li>Flexibility to support the different types of tests</li>
<li>Ability to present the test code to non-technical project members – QA team, senior management etc.</li>
</ul>
<p>With these factors taken into account RSpec was considered the best option with test/unit in second and Selenium very unfavourable.</p>
<p>To bring the security aspect into this topic – I wonder if there is a case for security consultants to assist client developers in writing test cases for there applications that will also assist the developers in keeping a security perspective on there code.</p>
<p><strong><br />
</strong></p>
<p><strong>Small Things, Loosely Joined and Written Fast &#8211; Justin Gehtland (Relevance, Inc.)</strong></p>
<p>I think this was the best talk that I attended. Unfortunately for the reader of this article it was really one of those talks that you have had to been there. The slides was mainly a few photos to support his comical metaphors, my notes practically non-existent and an excellent demo that you’ll have to go though the code in your own time.</p>
<p>The main argument was – Big problems do not require big solutions bundled in one big fat application. Proper solutions consist of a number of small independent applications that can be developed, configured, tested and managed independently. These smaller solutions then be integrated together to tackle the big problem.</p>
<p>To use his terms – This approach will improve your productivity by improving:</p>
<ul>
<li>Testability</li>
<li>Compose-ability</li>
<li>Security</li>
<li>Scalability</li>
</ul>
<p>And, to quote him “Make small things, join them loosely, write them fast, scale them independently”</p>
<p>He had a wonderful demonstration on three Rails applications that are delivered through a single entry point using a central authentication point and a message queue for some of the communication between the independent parts.</p>
<p>Have a look at his blog entry &#8211; <a title="http://blog.thinkrelevance.com/2008/9/3/small-things-loosely-joined-written-fast" href="http://blog.thinkrelevance.com/2008/9/3/small-things-loosely-joined-written-fast">http://blog.thinkrelevance.com/2008/9/3/small-things-loosely-joined-written-fast</a></p>
<p><strong>From Rails Security to Application Security &#8211; Carsten Bormann (Universität Bremen, TZI), Steffen Bartsch (TZI, Universität Bremen)</strong></p>
<p>I am not going to attempt to cover this talk in too much depth. They touched on the topics of:</p>
<ul>
<li>Data confidentiality, integrity and authentication</li>
<li>Threat matrixes</li>
<li>Attack trees</li>
</ul>
<p>There is loads of information out there on this that makes covering the topics in this write-up irrelevant.</p>
<p>The one thing to take note of in this talk is an authorisation plugin that Steffen developed. It offers a very clean way to manage authorisation of access for different level users to all the levels of the MVC architecture. Despite offering great flexibility and full management of authorisation it has very clean way of presenting the authorisation rules to the developer, making the auditing of the rules a very easy process.</p>
<p>See the presentation slides on Steffen’s blog &#8211; <a title="http://steffenbartsch.com/blog/2008/09/from-rails-security-to-application-security/" href="http://steffenbartsch.com/blog/2008/09/from-rails-security-to-application-security/">http://steffenbartsch.com/blog/2008/09/from-rails-security-to-application-security/</a></p>
<p><strong>Writing resources_controller: Discovering REST Patterns in Rails &#8211; Ian White (Argument from Design)</strong></p>
<p>REST is getting great attention in the Rails community, in fact I will dare to say &#8211; I think the RAILS community are leaders in the RESTful approach. If I may quote Ralf Wirdemann and Thomas Baustert from RESTful Rails Development (<a title="http://media.quilime.com/files/pdf/restful_rails_en.pdf" href="http://media.quilime.com/files/pdf/restful_rails_en.pdf">http://media.quilime.com/files/pdf/restful_rails_en.pdf</a>) “REST describes an architecture paradigm for web applications that request and manipulate web resources using the standard HTTP methods GET, POST, PUT and DELETE.”. In other words &#8211; A resource (data object/model) is mapped to a URL and is managed by the standard HTTP methods.</p>
<p>Also and as mention earlier, Ruby programmers support DRY (Don’t Repeat Yourself) code.</p>
<p>Ian developed a plugin (seems like if you want to talk at Rails conference then you have to write a plugin) that provides a central Resource Controller that can manage the REST functionalities of all your other controllers. For a very thorough explanation of this see the blog &#8211; <a title="http://blog.ardes.com/resources_controller" href="http://blog.ardes.com/resources_controller">http://blog.ardes.com/resources_controller</a></p>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=71&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2008/09/11/rails-conf-2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby installer using NSIS (Part 1)</title>
		<link>http://usefulfor.com/ruby/2008/07/19/ruby-installer-in-nsis-using-hm-nis-edit-part-1/</link>
		<comments>http://usefulfor.com/ruby/2008/07/19/ruby-installer-in-nsis-using-hm-nis-edit-part-1/#comments</comments>
		<pubDate>Sat, 19 Jul 2008 19:50:49 +0000</pubDate>
		<dc:creator>siebert</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://usefulfor.com/ruby/?p=63</guid>
		<description><![CDATA[On a recent project I was challenged with the task to create a Windows installer for the application that I have been contributing to (http://dradis.sourceforge.net/). After a bit of research it seemed like our answer was in using NSIS to assist us in this task.]]></description>
			<content:encoded><![CDATA[<p>Please note that I have written an updated version of this post that can be found <a href="http://usefulfor.com/ruby/2009/02/02/nsis-installer-for-a-ruby-application-part-1-hm-nis-wizard-output/">here</a></p>
<h3>Intro</h3>
<p>On a recent project I was challenged with the task to create a Windows installer for <a title="Dradis" href="http://dradis.sourceforge.net/">Dradis</a>, an application that I have been contributing to. After a bit of research it seemed like our answer was in using <a title="http://nsis.sourceforge.net" href="http://nsis.sourceforge.net">NSIS</a> (Nullsoft Scriptable Install System) to assist us in this task.</p>
<p>NSIS in an open source platform for creating Windows installers. It has its own scripting language that you program all your installer logic in and then compiles to a Windows installer executable.</p>
<p>In this series of articles I will introduce you to:</p>
<ul>
<li>HM NIS IDE and it&#8217;s wizard (Part 1)</li>
<li>Customising the wizard code (Part 2)</li>
<li>Challenges with installing to user accounts without administrator rights (Part 3)</li>
</ul>
<p><span id="more-63"></span></p>
<h3>The goal</h3>
<p>The goal is to create an installer for Acme application. I will customise the installer code as we go along but the main components for installation are:</p>
<ul>
<li>Copying our acme_app.rb file to a location on the target machine</li>
<li>Check if Ruby is installed on the target machine. Install it if it is not the case</li>
<li>Our application uses SQLite. We need to check if the required files are installed on the target machine and install it if it is not the case.</li>
</ul>
<p>On the NSIS website you will find plenty of examples and tutorials to get you started. I am however going to jump in a little further ahead and tell you about <a title="HM NIS Edit" href="http://hmne.sourceforge.net">HM NIS Edit</a>. HM NIS Edit is an Editor/IDE to create your NSIS installers in. I came across it after a little web search and it proved itself to be a very handy tool to use on top of NSIS.</p>
<p>To create a nice installer with options, components, license etc. there is a lot of code that is generic and can fit into a framework followed by a bit of customisation. HM NSIS Edit assists you in this task by providing a wizard. It is from the wizard I&#8217;ll start my explanation.</p>
<h3>The HM NIS Edit wizard</h3>
<p>In the HM NSIS Edit application you have the typical wand and stars icon to start the wizard with. The first couple of screens is pretty straight forward and asks you a number of things about your app. The fun starts at the &#8220;Application Files&#8221; screen. It is here where you specify the different components (groups) for your application and the files associated.</p>
<h3>The application components</h3>
<p>For the purpose of my Acme application I create the following components: Ruby, SQLite and Acme app.</p>
<p><strong><em>1. Ruby</em></strong></p>
<p>For the Ruby component I do not see the point of wrapping the Ruby one click installer file in our Acme app installer. I decided I&#8217;ll make Ruby an install component but picking it for installation will download the Ruby one click installer and execute it. I create the Ruby group in the wizard and do not pick any files, we will add the meat of the download and install later.</p>
<p><strong><em>2. SQLite</em></strong></p>
<p>Now we get to the SQLite component. So we create the SQLite group in our wizard. This group consists of two parts: the dll and the Ruby gem.</p>
<p><em>sqlite3.dll</em></p>
<p>The dll is easy; it is one file that we need to copy to the system32 folder. So to the right hand side of the wizard window we click the add file icon, browse for the dll that we have ready on our machine and select the destination directory. The destination directory is the directory on the target machine where the file will be copied to. We need it in the system32 folder so we choose $SYSDIR from the drop down box.</p>
<p><em>SQLite gem</em></p>
<p>The most common way to install Ruby gem is with the command line command:</p>
<p><code>gem install GEMNAME --remote</code></p>
<p>In older GEM versions you could not however state the platform that you are installing the gem to from the command line, it is an option that is given to you just after running the &#8220;gem install GEMNAME &#8211;remote&#8221; command.</p>
<p>The above will not work very nice with our installer as we want the installer to deal with this and not require input from the user on gem installation. However you can use <code>--local</code> instead of <code>--remote</code> and just specify the local file from which the gem should be installed. In this case the installation does not require from you to supply the platform.</p>
<p>So I downloaded the sqlite3-ruby-1.2.1-mswin32.gem file from <a title="RubyForge" href="http://mirrors.cat.pdx.edu/rubyforge/rubyforge-gems/">RubyForge</a> and added it to the files to be installed as we did with the dll, however in this case just copy it to the $INSTDIR. We will add the meat to run the <code>gem install GEMNAME --remote</code> command later.</p>
<p><strong><em>3. Acme app</em></strong></p>
<p>Now we get to our acme_app.rb source file. As for the previous components we create a new component group called Acme app. After the component has been created be associate ou acme_app.rb source file with it as we did with the SQLite files. We set the $INSTDIR to be our target folder on the target machine.</p>
<p>Note &#8211; If your application code is more than one file you can select a directory tree to be associated with the component instead of just a single file at a time.</p>
<p>At this point you component list should look something similar to what you see in the figure below.</p>
<p><a href="http://usefulfor.com/ruby/files/2008/08/components.jpg"><img class="alignnone size-full wp-image-69" src="http://usefulfor.com/ruby/files/2008/08/components.jpg" alt="" width="500" height="383" /></a></p>
<p>Completing the rest of the wizard is quite straight forward. Remember that if you want to execute an executable (for instance if you want to call notepad to open a file at the end of installation) you have to give the full path to the executable (for example &#8220;$SYSDIR\notepad.exe some-text-file&#8221;).</p>
<p>Finishing the wizard will give you a code file that you can compile in HM NIS Edit and it will supply you with the install executable.</p>
<h3>That&#8217;s it for now</h3>
<p>- but there is more</p>
<p>I have left a few things out that the wizard could not do to customise our installer. I will have to do some tweaking to the code for this purpose. This will be covered in Part 2.</p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"> </span></p>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=63&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2008/07/19/ruby-installer-in-nsis-using-hm-nis-edit-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>restful_authentication howto, step-by-step (part 2)</title>
		<link>http://usefulfor.com/ruby/2008/06/06/restful_authentication-howto-step-by-step-part-2/</link>
		<comments>http://usefulfor.com/ruby/2008/06/06/restful_authentication-howto-step-by-step-part-2/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 01:36:46 +0000</pubDate>
		<dc:creator>etd</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://weblog.nomejortu.com/ruby/restful_authentication-howto-step-by-step-part-2</guid>
		<description><![CDATA[Picking it up were we left it on restful_authentication howto, step-by-step (part 1) the second article of this series is a hands on example on how to use the restful_authentication plugin.
Things that will be covered include:

remove the need of a login
the use of an activation email, the application will require it&#8217;s users to activate their [...]]]></description>
			<content:encoded><![CDATA[<p>Picking it up were we left it on <a href="/ruby/2008/05/17/restful_authentication-step-by-step-part-1/">restful_authentication howto, step-by-step (part 1)</a> the second article of this series is a hands on example on how to use the <a href="http://agilewebdevelopment.com/plugins/restful_authentication">restful_authentication</a> plugin.</p>
<p>Things that will be covered include:</p>
<ul>
<li>remove the need of a <strong>login</strong></li>
<li>the use of an <em>activation email</em>, the application will require it&#8217;s users to activate their accounts upong sign up.</li>
<li>howto get rid of the <strong>remember me</strong> functionality (just in case you don&#8217;t need it).</li>
<li>howto strengthen a bit the default security of the framework.</li>
</ul>
<p><span id="more-55"></span><br />
If you started a blank application with the first series, you can seamlessly continue with the instructions of this post from were we left it on the first part of this <em>howto</em>. Otherwise, you can grab the code of <a href="/ruby/files/2008/06/restauthz.tar.bz2">restauthz</a> application, a small rails application that I have created and that can be used as a proof of concept out of the box. Let&#8217;s get this thing going.</p>
<p>Before we start, just a gentle reminder, be sure to include <code>AuthenticationSystem</code> in <code>ApplicationController</code>:-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-identifier">include AuthenticatedSystem
</span><span class="hl-comment"># Filter the password and password_confirmation
# fields from the log files
</span><span class="hl-identifier">filter_parameter_logging</span><span class="hl-default"> :</span><span class="hl-identifier">password</span><span class="hl-default">, :</span><span class="hl-identifier">password_confirmation</span></pre></div></div>
<h3>no login, just email</h3>
<p>The first step is to remove the <code>login</code> field from the <code>User</code> migration, this will ensure that we do not use it in the code <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>We also need to remove the revelant validatiors in the <code>User</code> model. In addition to this, some changes to the <code>authenticate</code> are required:-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def self</span><span class="hl-default">.</span><span class="hl-identifier">authenticate</span><span class="hl-brackets">(</span><span class="hl-identifier">email</span><span class="hl-code">, </span><span class="hl-identifier">password</span><span class="hl-brackets">)
  </span><span class="hl-identifier">u</span><span class="hl-default"> = </span><span class="hl-identifier">find_in_state</span><span class="hl-default"> :</span><span class="hl-identifier">first</span><span class="hl-default">, :</span><span class="hl-identifier">active</span><span class="hl-default">, :</span><span class="hl-identifier">conditions</span><span class="hl-default"> =&amp;</span><span class="hl-identifier">gt</span><span class="hl-default">; {:</span><span class="hl-identifier">email</span><span class="hl-default"> =&amp;</span><span class="hl-identifier">gt</span><span class="hl-default">; </span><span class="hl-identifier">email</span><span class="hl-default">} </span><span class="hl-comment"># need to get the salt
  </span><span class="hl-identifier">u</span><span class="hl-default"> &amp;</span><span class="hl-identifier">amp</span><span class="hl-default">;&amp;</span><span class="hl-identifier">amp</span><span class="hl-default">; </span><span class="hl-identifier">u</span><span class="hl-default">.</span><span class="hl-identifier">authenticated</span><span class="hl-default">?</span><span class="hl-brackets">(</span><span class="hl-identifier">password</span><span class="hl-brackets">)</span><span class="hl-default"> ? </span><span class="hl-identifier">u</span><span class="hl-default"> : </span><span class="hl-reserved">nil
end</span></pre></div></div>
<p>We also need to update the call to this function in the <code>SessionsController</code> (line 9):-</p>
<div class="hl-surround" style="height:28px;"><div class="hl-main"><pre><span class="hl-reserved">self</span><span class="hl-default">.</span><span class="hl-identifier">current_user</span><span class="hl-default"> = </span><span class="hl-identifier">User</span><span class="hl-default">.</span><span class="hl-identifier">authenticate</span><span class="hl-brackets">(</span><span class="hl-identifier">params</span><span class="hl-brackets">[</span><span class="hl-code">:</span><span class="hl-identifier">email</span><span class="hl-brackets">]</span><span class="hl-code">, </span><span class="hl-identifier">params</span><span class="hl-brackets">[</span><span class="hl-code">:</span><span class="hl-identifier">password</span><span class="hl-brackets">])</span></pre></div></div>
<p>And that&#8217;s it. It wasn&#8217;t that difficult, was it?</p>
<h3>email activation</h3>
<p>The only thing that we are going to tweak is the templates provided by <strong>restful_authentication</strong>.</p>
<p>In <code>./app/model/user_mailer.rb</code> you can modify the email headers such as the <strong>subject</strong> and <strong>from</strong> address. The body of the emails is located under <code>./app/views/user_mailer/</code>.</p>
<p>The system sends to the users two emails, one after signup (this one contains the <em>activation link</em>) and one once the user has activated the account.</p>
<p>By default the templates contain the newly created user&#8217;s password, which is something that is controversial to say the least. I decided to get rid of the password, but this depends on your needs more than anything else.</p>
<h3>remember me</h3>
<p>Another feature that is application dependant is the use of a <em>remember me functionality</em>: a check box in the login form that would cause the application to store an authentication token in the user&#8217;s cookie so the next time the user visits the site does not have to authenticate again. I decided to nail down this example to the very basics, so no <em>remember me</em> functionality in this instance.</p>
<p>This can be accomplished by making some modifications to the <strong>AuthenticatedSystem#current_user</strong> function:</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">def </span><span class="hl-identifier">current_user
  </span><span class="hl-comment">#@current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false
  # only session based login for the time being
  </span><span class="hl-var">@current_user</span><span class="hl-default"> ||= </span><span class="hl-identifier">login_from_session </span><span class="hl-reserved">unless </span><span class="hl-var">@current_user</span><span class="hl-default"> == </span><span class="hl-reserved">false
end</span></pre></div></div>
<p>In the previous code, the <code>@current_user</code> variable is only set through the session, no HTTP Basic (careful if you have ActiveResource clients) or <em>remember me</em> cookie.</p>
<h3>security tweaks</h3>
<p><strong>password policy</strong><br />
A strong password policy is enforced by means of rails&#8217; <a href="http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M001331">validate_format_of</a>. In the <code>User</code> model:-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-reserved">class </span><span class="hl-identifier">User</span><span class="hl-quotes">  /</span><span class="hl-string">^(?=.*</span><span class="hl-special">\d</span><span class="hl-string">)(?=.*([a-z]|[A-Z]))([</span><span class="hl-special">\x</span><span class="hl-string">20-</span><span class="hl-special">\x</span><span class="hl-string">7E]){8,40}$</span><span class="hl-quotes">/</span><span class="hl-default">,
    :</span><span class="hl-identifier">message</span><span class="hl-default"> =&amp;</span><span class="hl-identifier">gt</span><span class="hl-default">; </span><span class="hl-quotes">'</span><span class="hl-string">chosen is not complex enough!</span><span class="hl-quotes">'
  </span><span class="hl-identifier">validates_format_of</span><span class="hl-default"> :</span><span class="hl-identifier">email</span><span class="hl-default">, 
    :</span><span class="hl-identifier">with</span><span class="hl-default"> =&amp;</span><span class="hl-identifier">gt</span><span class="hl-default">;</span><span class="hl-quotes"> /</span><span class="hl-string">^([a-zA-Z0-9_'+*$%</span><span class="hl-special">\^</span><span class="hl-string">&amp;amp;!</span><span class="hl-special">\.\-</span><span class="hl-string">])+</span><span class="hl-special">\@</span><span class="hl-string">(([a-zA-Z0-9</span><span class="hl-special">\-</span><span class="hl-string">])+</span><span class="hl-special">\.</span><span class="hl-string">)+([a-zA-Z0-9:]{2,4})+$</span><span class="hl-quotes">/</span><span class="hl-default">, 
    :</span><span class="hl-identifier">message</span><span class="hl-default"> =&amp;</span><span class="hl-identifier">gt</span><span class="hl-default">; </span><span class="hl-quotes">'</span><span class="hl-string">field does not look like an email.</span><span class="hl-quotes">'
  </span><span class="hl-brackets">[</span><span class="hl-code">...</span><span class="hl-brackets">]
</span><span class="hl-reserved">end</span></pre></div></div>
<p>In the code above we match both the email and the password against regular expressions to verify the syntax.</p>
<p>The regular expression for the password was taken from <a href="http://ajaxonrails.wordpress.com/2006/10/19/using-regular-expression-in-ruby-on-rails-regex-for-password-validation/">Using Regular Expression in Ruby on Rails &#8212; Regexp for Password Validation</a>:-</p>
<blockquote><p>
Lets say we have to implement the following validations to validate a password:</p>
<ul>
<li>Password should contain atleast one integer.</li>
<li>Password should contain atleast one alphabet(either in downcase or upcase).</li>
<li>Password can have special characters from 20 to 7E ascii values.</li>
<li>Password should be minimum of 8 and maximum of 40 cahracters long.</li>
</ul>
</blockquote>
<p><strong>password with salt &amp; pepper</strong></p>
<blockquote><p>
Storing a password in plaintext may result in a system compromise (<a href="http://www.owasp.org/">OWASP</a>).
</p></blockquote>
<p>Conveniently enough, <strong>restful_authentication</strong> uses a <a href="http://en.wikipedia.org/wiki/Hash_function">hash function</a> to protect user passwords: the <a href="http://en.wikipedia.org/wiki/SHA-1">SHA-1</a>. It also uses a <a href="http://en.wikipedia.org/wiki/Salting_%28cryptography%29">salt</a>. Here are however two tricks to increase the security of the default setup:</p>
<p><strong>First</strong> we are going to hash the password with salt and pepper. The salt is specific to each user and will be stored in the database along with the user&#8217;s hashed password. If an attacker can compromise the database, they would have access to both the salt and the hash and brute force attacks could be mounted by using custom scripts or <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow tables</a>. The trick here is to add a second component, the <strong>pepper</strong>. The pepper is another random string that will be used to add some extra entropy to the password hashing process. In our implementation the same pepper will be used for all the users and it will be stored in the code. If an attacker gains access to the database, no successful brute force attack can be mounted without knowing the pepper. If an attacker gains access to both the database and the code&#8230; <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>You can easily generate your <strong>pepper</strong> using something like this in code in <code>irb</code>:-</p>
<div class="hl-surround">
<div class="hl-main">
<pre>
require 'digest/sha2'
s = ''
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
1.upto(4) { |i| s &lt;&lt; chars[rand(chars.size-1)] }
s += Time.now.to_s
1.upto(4) { |i| s &lt;&lt; chars[rand(chars.size-1)] }
Digest::SHA256.hexdigest(s)
=&gt; "9fa4c6519da9d2121bc42be1d63813f591bba8ece5b753e6ceefed00f15e5342"
</pre>
</div>
</div>
<p>The random character generation was taken from <a href="http://snippets.dzone.com/posts/show/491">generate a random password</a>.</p>
<p>And <strong>second</strong>, we can upgrade the system to use the more secure SHA-256 both for the hashed password and the salt. We will keep SHA-1 for the sake of variety <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>In order to accomplish this, some modifications are needed to the <code>./app/model/user.rb</code>. First we need to include the required files:-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment"># sha1 for activation code. sha2 for the passwords
</span><span class="hl-reserved">require </span><span class="hl-quotes">'</span><span class="hl-string">digest/sha1</span><span class="hl-quotes">'
</span><span class="hl-reserved">require </span><span class="hl-quotes">'</span><span class="hl-string">digest/sha2</span><span class="hl-quotes">'</span></pre></div></div>
<p>Then the password encryption function:-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment"># We are using both, salt and peper to hash the
# password. The new password hash uses
# SHA2.hexdigest
</span><span class="hl-reserved">def self</span><span class="hl-default">.</span><span class="hl-identifier">encrypt</span><span class="hl-brackets">(</span><span class="hl-identifier">password</span><span class="hl-code">, </span><span class="hl-identifier">salt</span><span class="hl-brackets">)
  </span><span class="hl-identifier">pepper</span><span class="hl-default"> = </span><span class="hl-quotes">'</span><span class="hl-string">9fa4c6519da9d2121bc42be1d63813f591bba8ece5b753e6ceefed00f15e5342</span><span class="hl-quotes">'
  </span><span class="hl-identifier">Digest</span><span class="hl-default">::</span><span class="hl-identifier">SHA256</span><span class="hl-default">.</span><span class="hl-identifier">hexdigest</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">--#{salt}--#{password}--#{pepper}--</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">)
</span><span class="hl-reserved">end</span></pre></div></div>
<p>And the salt generation function:-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-comment"># The salt is also created using SHA256
</span><span class="hl-reserved">def </span><span class="hl-identifier">encrypt_password
  </span><span class="hl-reserved">return if </span><span class="hl-identifier">password</span><span class="hl-default">.</span><span class="hl-identifier">blank</span><span class="hl-default">?
  </span><span class="hl-reserved">self</span><span class="hl-default">.</span><span class="hl-identifier">salt</span><span class="hl-default"> = </span><span class="hl-identifier">Digest</span><span class="hl-default">::</span><span class="hl-identifier">SHA256</span><span class="hl-default">.</span><span class="hl-identifier">hexdigest</span><span class="hl-brackets">(</span><span class="hl-quotes">&quot;</span><span class="hl-string">--#{Time.now.to_s}--#{email}--</span><span class="hl-quotes">&quot;</span><span class="hl-brackets">) </span><span class="hl-reserved">if </span><span class="hl-identifier">new_record</span><span class="hl-default">?
  </span><span class="hl-reserved">self</span><span class="hl-default">.</span><span class="hl-identifier">crypted_password</span><span class="hl-default"> = </span><span class="hl-identifier">encrypt</span><span class="hl-brackets">(</span><span class="hl-identifier">password</span><span class="hl-brackets">)
</span><span class="hl-reserved">end</span></pre></div></div>
<p>In order to store the new hash, we need to increase the length of the salt and crypted password fields in the database. This can be done in the migrations file:-</p>
<div class="hl-surround">
<div class="hl-main">
<pre>
t.column :crypted_password, :string, :limit =&gt; 64
t.column :salt, :string, :limit =&gt; 64
</pre>
</div>
</div>
<h3>summary</h3>
<p>So that was it, the <a href="/ruby/files/2008/06/restauthz.tar.bz2">restauthz</a> application should cover all the needs to get you started with restful_authentication. There is still room for improvement, think the <strong>I forgot my password</strong> functionality, or a facility for your users to change their passwords, but that is definitely another story <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=55&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2008/06/06/restful_authentication-howto-step-by-step-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>restful_authentication howto, step-by-step (part 1)</title>
		<link>http://usefulfor.com/ruby/2008/05/17/restful_authentication-step-by-step-part-1/</link>
		<comments>http://usefulfor.com/ruby/2008/05/17/restful_authentication-step-by-step-part-1/#comments</comments>
		<pubDate>Fri, 16 May 2008 23:53:20 +0000</pubDate>
		<dc:creator>etd</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://weblog.nomejortu.com/ruby/restful_authentication-step-by-step-part-1</guid>
		<description><![CDATA[There are more than a hundred thousand different ways of implementing authentication in ruby on rails. Authentication in the rails world is definetly not for the faint hearted. After some random reading through the rails wiki it seemed quite clear that there is one winner: acts_as_authenticated. However, after including this plugin in one of my [...]]]></description>
			<content:encoded><![CDATA[<p>There are <a href="http://wiki.rubyonrails.com/rails/pages/Authentication">more than a hundred thousand</a> different ways of implementing authentication in ruby on rails. Authentication in the rails world is definetly not for the faint hearted. After some random reading through the rails wiki it seemed quite clear that there is one winner: <a href="http://wiki.rubyonrails.org/rails/pages/acts_as_authenticated">acts_as_authenticated</a>. However, after including this plugin in one of my secret projects to take over the world, it seems that is lacking some functionality, what I need out of the authentication framework is:</p>
<ul>
<li>A no non-sense authentication: just email and password. No bells, no wistles.</li>
<li>The system should send an <em>activation email</em> after the user signs up.</li>
</ul>
<p>Let&#8217;s explore the alternatives <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> <br />
<span id="more-53"></span></p>
<h3>The haystack&#8230;</h3>
<p>As stated elsewhere <strong>acts_as_authenticated</strong> is a neat solution that just <em>gets out of the way</em>. It is nice and easy to integrate. However, it is a bit too simple. <a href="http://rubyforge.org/projects/loginsugar/">loginsugar</a> seemed to be a suitable alternative with <a href="http://wiki.rubyonrails.org/rails/show/ActionMailer">ActionMailer</a> integration out of the box.</p>
<p>I decided to give it a try. It has a good documentation that walks you through the process of integrating it in your app, but it did not seem to be a goal too easy to accomplish <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>What I finally decided was to take specific bits and pieces of the <strong>loginsugar</strong> and integrate them with plain old <strong>acts_as_authenticated</strong>.</p>
<p>First step of the process: I created a brand new project and installed the <strong>acts_as_authenticated</strong> plugin. It was surprising to find the following line in the README file:</p>
<blockquote><p>DEPRECATED: Use restful_authentication instead.  Or, ask me for commit rights if you wish to maintain this plugin.</p>
</blockquote>
<p>&#8230;  <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_rolleyes.gif' alt=':roll:' class='wp-smiley' />  So I was right back at the begining, everybody recommended <strong>acts_as_authenticated</strong> but <strong>acts_as_authenticated</strong> recommended <a href="http://agilewebdevelopment.com/plugins/restful_authentication">restuful_authentication</a>&#8230; I thought that if <strong>acts_as_authenticated</strong> is recommending something, it has to be good <img src='http://usefulfor.com/ruby/wp-includes/images/smilies/icon_mrgreen.gif' alt=':mrgreen:' class='wp-smiley' />  And I decided to give <strong>restuful_authentication</strong> a try.</p>
<h3>&#8230; and the needle</h3>
<p>Lets get out hands dirty, create a new project and install the plugin with:-</p>
<div class="hl-surround" ><div class="hl-main"><pre>&lt;br /&gt;
$ ./script/plugin  install http://svn.techno-weenie.net/projects/plugins/restful_authentication/&lt;br /&gt;</pre></div></div>
</p>
<p>It turns out that the plugin has the <em>activation email</em> functionality out of the box, the only requirement is the use of a few command line options:-</p>
<p>
<div class="hl-surround" ><div class="hl-main"><pre>&lt;br /&gt;
$ ./script/generate authenticated&lt;br /&gt;
Usage: ./script/generate authenticated ModelName [ControllerName]&lt;/p&gt;
&lt;p&gt;Options:&lt;br /&gt;
        --skip-migration             Don't generate a migration file for this model&lt;br /&gt;
        --include-activation         Generate signup 'activation code' confirmation via email&lt;br /&gt;
        --stateful                   Use acts_as_state_machine.  Assumes --include-activation&lt;br /&gt;
        --rspec                      Force rspec mode (checks for RAILS_ROOT/spec by default)&lt;br /&gt;</pre></div></div>
</p>
<p>We need to include the <code>--include-activation</code> for the email, which in turn requires <code>--stateful</code>. The idea is that you are going to associate a small <a href="http://en.wikipedia.org/wiki/State_Machine">state machine</a> to each user. From signed up, to pending; after the user actives the account, the status changes to active, etc.</p>
<p>It is quite neat. However it has the drawback that requires another plugin: <a href="http://agilewebdevelopment.com/plugins/acts_as_state_machine">acts_as_state_machine</a>, but more on that later.</p>
<p>In order to generate your user model and your session controller, you need to issue the following:-</p>
<p>
<div class="hl-surround" ><div class="hl-main"><pre>&lt;br /&gt;
$ ./script/generate authenticated user sessions \&lt;br /&gt;
                --include-activation \&lt;br /&gt;
                --stateful&lt;br /&gt;</pre></div></div>
</p>
<p>This generates the required files. It also creates the routes to the user and session resources in <code>./conf/routes.rb</code>:-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">&lt;</span><span class="hl-identifier">br</span><span class="hl-quotes"> /</span><span class="hl-string">&gt;
#[...]&lt;br </span><span class="hl-quotes">/</span><span class="hl-default">&gt;
</span><span class="hl-identifier">map</span><span class="hl-default">.</span><span class="hl-identifier">resources</span><span class="hl-default"> :</span><span class="hl-identifier">users</span><span class="hl-default">&lt;</span><span class="hl-identifier">br</span><span class="hl-quotes"> /</span><span class="hl-string">&gt;
map.resource :session&lt;br </span><span class="hl-quotes">/</span><span class="hl-default">&gt;
</span><span class="hl-comment">#[...]&lt;br /&gt;</span></pre></div></div>
</p>
<p>However, as the README file suggests we need to modify the <code>:users</code> resource as follows:-</p>
<div class="hl-surround" ><div class="hl-main"><pre>&lt;br /&gt;
map.resources :users, :member =&gt; { :suspend =&gt; :put, :unsuspend =&gt; :put, :purge =&gt; :delete }&lt;br /&gt;</pre></div></div>
</p>
<p>An extra line in <code>./config/environment.rb</code> is also required (make sure you include it inside the <code>Rails::Initializer.run</code> block):-</p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">&lt;</span><span class="hl-identifier">br</span><span class="hl-quotes"> /</span><span class="hl-string">&gt;
config.active_record.observers = :user_observer&lt;br </span><span class="hl-quotes">/</span><span class="hl-default">&gt;</span></pre></div></div>
</p>
<p>The next step is to install the <strong>acts_as_state_machine</strong> plugin and to run <code>rake db:migrate</code> to initialize the database:-</p>
<p>
<div class="hl-surround" ><div class="hl-main"><pre><span class="hl-default">&lt;</span><span class="hl-identifier">br</span><span class="hl-quotes"> /</span><span class="hl-string">&gt;
$ .</span><span class="hl-quotes">/</span><span class="hl-identifier">script</span><span class="hl-quotes">/</span><span class="hl-string">plugin install http:</span><span class="hl-quotes">//</span><span class="hl-string">elitists.textdriven.com</span><span class="hl-quotes">/</span><span class="hl-identifier">svn</span><span class="hl-quotes">/</span><span class="hl-string">plugins</span><span class="hl-quotes">/</span><span class="hl-identifier">acts_as_state_machine</span><span class="hl-quotes">/</span><span class="hl-string">trunk&lt;br </span><span class="hl-quotes">/</span><span class="hl-default">&gt;
</span><span class="hl-brackets">[</span><span class="hl-code">...</span><span class="hl-brackets">]</span><span class="hl-default">&lt;</span><span class="hl-identifier">br</span><span class="hl-quotes"> /</span><span class="hl-string">&gt;
$ rake db:migrate&lt;br </span><span class="hl-quotes">/</span><span class="hl-default">&gt;</span></pre></div></div>
</p>
<p>Now you are set. Feel free to run <code>rake</code> that all the tests will pass without warnings. Only one tip from the <a href="http://railscasts.com/episodes/67">restful_authentication railscast</a>: to get short urls for <code>signup</code>, <code>login</code> and <code>logout</code> add the following to your <code>./config/routes.rb</code>:</p>
<div class="hl-surround" ><div class="hl-main"><pre>&lt;br /&gt;
map.signup '/signup', :controller =&gt; 'users', :action =&gt; 'new'&lt;br /&gt;
map.connect '/activate/:activation_code', :controller =&gt; 'users', :action =&gt; 'activate'&lt;br /&gt;
map.login '/login', :controller =&gt; 'sessions', :action =&gt; 'new'&lt;br /&gt;
map.logout '/logout', :controller =&gt; 'sessions', :action =&gt; 'destroy'&lt;br /&gt;</pre></div></div>
</p>
<h3>Fine tune</h3>
<p>So here we are all set with the authentication framework in place. From here on it is about customization and fine tunning. Note that the <em>activation email</em> feature requires an either an email server running on the same box or some ActionMailer configuration in order for it to work.</p>
<p>In the second part of this series we will go back to our basic need: get rid of the <strong>login</strong> field (we only need an email). <del>This and other tweaks will be demonstrated in a tiny app that fully implements the concepts explained here.</del> Part 2 is here! <a href="/ruby/2008/06/06/restful_authentication-howto-step-by-step-part-2/">restful_authentication howto, step-by-step (part 2)</a>.</p>
<img src="http://usefulfor.com/ruby/?ak_action=api_record_view&id=53&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://usefulfor.com/ruby/2008/05/17/restful_authentication-step-by-step-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
