<?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>Stupid Idea &#187; Code</title>
	<atom:link href="http://www.stupididea.com/category/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.stupididea.com</link>
	<description></description>
	<lastBuildDate>Mon, 29 Mar 2010 15:16:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Non-Rails Autotest + RSpec + LibNotify + Linux</title>
		<link>http://www.stupididea.com/2009/03/15/non-rails-autotest-rspec-libnotify-linux/</link>
		<comments>http://www.stupididea.com/2009/03/15/non-rails-autotest-rspec-libnotify-linux/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 02:41:11 +0000</pubDate>
		<dc:creator>method</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://www.stupididea.com/?p=208</guid>
		<description><![CDATA[Each of those terms actually means something! If you don&#8217;t know what any one of those terms means, then you probably won&#8217;t enjoy this post. It&#8217;s surprising that something so cool and so central to the Ruby TDD world as &#8230; <a href="http://www.stupididea.com/2009/03/15/non-rails-autotest-rspec-libnotify-linux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Each of those terms actually means something! If you don&#8217;t know what any one of those terms means, then you probably won&#8217;t enjoy this post.</p>
<p>It&#8217;s surprising that something so cool and so central to the Ruby TDD world as <a href="http://zentest.rubyforge.org/ZenTest/">Autotest</a> is completely undocumented. Autotest with Rails and <a href="http://rspec.info/">RSpec</a> just works, and there are many googleable examples of how to add hooks for using Growl or libnotify. I couldn&#8217;t find any reliable advice for how to use Autotest with a non-Rails project and how to use RSpec instead of Unit/Test. The libnotify part is easy once the other two are solved, but I&#8217;ll share what I have going on anyway. This information may be available in pieces somewhere else, but I&#8217;ll just put it all here to help the other lost googlers.</p>
<p>The first thing to know is that <a href="http://blog.nicksieger.com/articles/2007/01/30/rspec-autotest-for-standalone-projects">this blog post</a> is out of date. Autotest now speaks RSpec as one of its native &#8220;styles&#8221;. The trick is that you have to tell autotest about this style by creating a file called <strong>autotest/discover.rb</strong> in your project root. This contains:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Autotest.<span style="color:#9900CC;">add_discovery</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#996600;">&quot;rspec&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The second thing to know is that Autotest looks in your <code>lib/</code> folder for your files and in your <code>spec/</code> folder for your tests, which should be called<br />
<code>file_name_spec.rb</code>.</p>
<p>There&#8217;s not much more to know. You can add awesome heads-up notification using libnotify. You need to get <code>libnotify-bin</code> using something like <code>sudo apt-get install libnotify-bin</code>. Then in the root of your project directory create an .autotest file like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> <span style="color:#6666ff; font-weight:bold;">Autotest::GnomeNotify</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Time notification will be displayed before disappearing automatically</span>
  EXPIRATION_IN_SECONDS = <span style="color:#006666;">2</span>
  ERROR_STOCK_ICON = <span style="color:#996600;">&quot;gtk-dialog-error&quot;</span>
  SUCCESS_STOCK_ICON = <span style="color:#996600;">&quot;gtk-dialog-info&quot;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Convenience method to send an error notification message</span>
  <span style="color:#008000; font-style:italic;">#</span>
  <span style="color:#008000; font-style:italic;"># [stock_icon]   Stock icon name of icon to display</span>
  <span style="color:#008000; font-style:italic;"># [title]        Notification message title</span>
  <span style="color:#008000; font-style:italic;"># [message]      Core message for the notification</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">notify</span> stock_icon, title, message
    options = <span style="color:#996600;">&quot;-t #{EXPIRATION_IN_SECONDS * 1000} -i #{stock_icon}&quot;</span>
    <span style="color:#CC0066; font-weight:bold;">system</span> <span style="color:#996600;">&quot;notify-send #{options} '#{title}' <span style="color:#000099;">\&quot;</span>#{message}<span style="color:#000099;">\&quot;</span>&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:red</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>at<span style="color:#006600; font-weight:bold;">|</span>
    example_text = <span style="color:#996600;">&quot;&quot;</span>
    num_examples = <span style="color:#006666;">0</span>
    examples = at.<span style="color:#9900CC;">files_to_test</span>.<span style="color:#9900CC;">each_pair</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>key, values<span style="color:#006600; font-weight:bold;">|</span>
      example_text <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#996600;">&quot;- #{key}<span style="color:#000099;">\n</span>&quot;</span> 
      values.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>value<span style="color:#006600; font-weight:bold;">|</span>
        num_examples <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
        example_text <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#996600;">&quot;  * #{value}<span style="color:#000099;">\n</span>&quot;</span> 
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    notify ERROR_STOCK_ICON, <span style="color:#996600;">&quot;Tests failed&quot;</span>, <span style="color:#996600;">&quot;&lt;b&gt;#{num_examples} examples failed in #{at.files_to_test.size} files&lt;/b&gt;<span style="color:#000099;">\n</span>#{example_text}&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:green</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>at<span style="color:#006600; font-weight:bold;">|</span>
    notify SUCCESS_STOCK_ICON, <span style="color:#996600;">&quot;All tests passed, good job!&quot;</span>, <span style="color:#996600;">&quot;&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>I&#8217;ve modified mine to have very verbose notifications. I got it from <a href="http://ph7spot.com/articles/getting_started_with_autotest">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stupididea.com/2009/03/15/non-rails-autotest-rspec-libnotify-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails and Ext non-Ajax Signup Form with Password Confirmation</title>
		<link>http://www.stupididea.com/2008/07/02/rails-and-ext-non-ajax-signup-form/</link>
		<comments>http://www.stupididea.com/2008/07/02/rails-and-ext-non-ajax-signup-form/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 01:08:43 +0000</pubDate>
		<dc:creator>method</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://www.stupididea.com/?p=98</guid>
		<description><![CDATA[This is, uh, a technical post. Probably there are others who want to do the same somewhat senseless thing: use Ext to do form validation while keeping a boring non-Ajax post-and-response. The bottom line is that Ext favors doing it &#8230; <a href="http://www.stupididea.com/2008/07/02/rails-and-ext-non-ajax-signup-form/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is, uh, a technical post.</p>
<p>Probably there are others who want to do the same somewhat senseless thing: use Ext to do form validation while keeping a boring non-Ajax post-and-response. The bottom line is that Ext favors doing it the Ajax way, and the Ajax way isn&#8217;t that hard to set up with Rails (just handle the form submission as normal but return JSON or XML to signal success or failure). But if you&#8217;re like me and working on a deadline, there can be a cognitive burden to switching to Ajax posting that you might want to avoid. Paradoxically, you might find yourself wasting a lot of time trying to figure out how to do it the &#8220;old-fashioned&#8221; way. Well, here&#8217;s one working standard-submission Signup Form, with fancy validations and all the kinks worked out.</p>
<p>Here&#8217;s the top half of the file <code>users/new.html.erb</code>, which is nearly the same as the code generated by restful-authentication:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">password</span> = <span style="color:#0066ff; font-weight:bold;">@user</span>.<span style="color:#9900CC;">password_confirmation</span> = <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">error_messages_for</span> <span style="color:#ff3333; font-weight:bold;">:user</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
&lt;div id=&quot;no-js-form&quot;&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#5A0A0A; font-weight:bold;">form_for</span> <span style="color:#ff3333; font-weight:bold;">:user</span>, <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> users_path, <span style="color:#ff3333; font-weight:bold;">:html</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:id <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup-form&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span>
    &lt;p&gt;
        &lt;label for=&quot;login&quot;&gt;
            Real Name
        &lt;/label&gt;
        &lt;br/&gt;
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">text_field</span> <span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup_name_field&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/p&gt;
    &lt;p&gt;
        &lt;label for=&quot;login&quot;&gt;
            User Name
        &lt;/label&gt;
        &lt;br/&gt;
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">text_field</span> <span style="color:#ff3333; font-weight:bold;">:login</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup_login_field&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/p&gt;
    &lt;p&gt;
        &lt;label for=&quot;email&quot;&gt;
            Email
        &lt;/label&gt;
        &lt;br/&gt;
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">text_field</span> <span style="color:#ff3333; font-weight:bold;">:email</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup_email_field&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/p&gt;
    &lt;p&gt;
        &lt;label for=&quot;password&quot;&gt;
            Password
        &lt;/label&gt;
        &lt;br/&gt;
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#5A0A0A; font-weight:bold;">password_field</span> <span style="color:#ff3333; font-weight:bold;">:password</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup_password_field&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/p&gt;
    &lt;p&gt;
        &lt;label for=&quot;password_confirmation&quot;&gt;
            Confirm Password
        &lt;/label&gt;
        &lt;br/&gt;
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#5A0A0A; font-weight:bold;">password_field</span> <span style="color:#ff3333; font-weight:bold;">:password_confirmation</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup_password_confirmation_field&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/p&gt;
    &lt;p&gt;
        &lt;label for=&quot;password_confirmation&quot;&gt;
            Role
        &lt;/label&gt;
        &lt;br/&gt;
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#CC0066; font-weight:bold;">select</span> <span style="color:#ff3333; font-weight:bold;">:role</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;consumer&quot;</span>,<span style="color:#996600;">&quot;consumer&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;vendor&quot;</span>,<span style="color:#996600;">&quot;vendor&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup_role_field&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/p&gt;
    &lt;p&gt;
        <span style="color:#006600; font-weight:bold;">&lt;%</span>= submit_tag <span style="color:#996600;">'Sign up'</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;signup_submit_button&quot;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
    &lt;/p&gt;
    <span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span>
&lt;/div&gt;
&lt;div id=&quot;js-form-panel&quot;&gt;
&lt;/div&gt;</pre></div></div>

<p>The only differences are a div wrapping the form (&#8220;no-js-form&#8221;) and the &#8220;js-form-panel&#8221; at the end. You&#8217;re going to laugh at me, but this form is buzzword-friendly; it&#8217;s <strong>unobtrusive</strong> in an ugly way. If javascript is turned on, the form will work, and the following will fail:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #006600; font-style: italic;">/* 
     Thanks to:
     http://www.extjswithrails.com/2008_03_01_archive.html for standardSubmit tip (hard to find!)
     http://extjs.com/forum/showthread.php?t=23068 for password confirmation
     Anyone else I stole semantics from
     */</span>
    <span style="color: #006600; font-style: italic;">// Look, I'm copying over the authenticity token to send in the JS-generated form. LOL!</span>
    <span style="color: #003366; font-weight: bold;">var</span> authenticity_token <span style="color: #339933;">=</span> document<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'forms'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'authenticity_token'</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">value</span><span style="color: #339933;">;</span>
&nbsp;
    Ext.<span style="color: #660066;">onReady</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'no-js-form'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">var</span> myForm<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">function</span> submitHandler<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            form <span style="color: #339933;">=</span> myForm.<span style="color: #660066;">getForm</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            form_as_dom <span style="color: #339933;">=</span> form.<span style="color: #660066;">getEl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">dom</span><span style="color: #339933;">;</span>
            form_as_dom.<span style="color: #660066;">action</span> <span style="color: #339933;">=</span> form.<span style="color: #660066;">url</span><span style="color: #339933;">;</span>
            form_as_dom.<span style="color: #660066;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        myForm <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">FormPanel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
            monitorValid<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            standardSubmit<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            url<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;/users&quot;</span><span style="color: #339933;">,</span>
            applyTo<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;js-form-panel&quot;</span><span style="color: #339933;">,</span>
            title<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Signup as a New User&quot;</span><span style="color: #339933;">,</span>
            width<span style="color: #339933;">:</span> <span style="color: #CC0000;">310</span><span style="color: #339933;">,</span>
            autoHeight<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            items<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">TextField</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                allowBlank<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                msgTarget<span style="color: #339933;">:</span> <span style="color: #3366CC;">'side'</span><span style="color: #339933;">,</span>
                <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;user[name]&quot;</span><span style="color: #339933;">,</span>
                id<span style="color: #339933;">:</span> <span style="color: #3366CC;">'js_signup_name_field'</span><span style="color: #339933;">,</span>
                fieldLabel<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Real Name&quot;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">TextField</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                allowBlank<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                vtype<span style="color: #339933;">:</span> <span style="color: #3366CC;">'alphanum'</span><span style="color: #339933;">,</span>
                msgTarget<span style="color: #339933;">:</span> <span style="color: #3366CC;">'side'</span><span style="color: #339933;">,</span>
                <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;user[login]&quot;</span><span style="color: #339933;">,</span>
                id<span style="color: #339933;">:</span> <span style="color: #3366CC;">'js_signup_login_field'</span><span style="color: #339933;">,</span>
                fieldLabel<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Username&quot;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">TextField</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                allowBlank<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                vtype<span style="color: #339933;">:</span> <span style="color: #3366CC;">'email'</span><span style="color: #339933;">,</span>
                msgTarget<span style="color: #339933;">:</span> <span style="color: #3366CC;">'side'</span><span style="color: #339933;">,</span>
                <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;user[email]&quot;</span><span style="color: #339933;">,</span>
                id<span style="color: #339933;">:</span> <span style="color: #3366CC;">'js_signup_email_field'</span><span style="color: #339933;">,</span>
                fieldLabel<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Email&quot;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">TextField</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                allowBlank<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                inputType<span style="color: #339933;">:</span> <span style="color: #3366CC;">'password'</span><span style="color: #339933;">,</span>
                vType<span style="color: #339933;">:</span> <span style="color: #3366CC;">'password'</span><span style="color: #339933;">,</span>
                msgTarget<span style="color: #339933;">:</span> <span style="color: #3366CC;">'side'</span><span style="color: #339933;">,</span>
                <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;user[password]&quot;</span><span style="color: #339933;">,</span>
                id<span style="color: #339933;">:</span> <span style="color: #3366CC;">'js_signup_password_field'</span><span style="color: #339933;">,</span>
                fieldLabel<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Password&quot;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">TextField</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                fieldLabel<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Password Confirm:&quot;</span><span style="color: #339933;">,</span>
                allowBlank<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
                inputType<span style="color: #339933;">:</span> <span style="color: #3366CC;">'password'</span><span style="color: #339933;">,</span>
                <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;user[password_confirmation]&quot;</span><span style="color: #339933;">,</span>
                initialPasswordField<span style="color: #339933;">:</span> <span style="color: #3366CC;">'signup_password_field'</span><span style="color: #339933;">,</span>
                vType<span style="color: #339933;">:</span> <span style="color: #3366CC;">'password'</span><span style="color: #339933;">,</span>
                msgTarget<span style="color: #339933;">:</span> <span style="color: #3366CC;">'side'</span><span style="color: #339933;">,</span>
                id<span style="color: #339933;">:</span> <span style="color: #3366CC;">'js_signup_password_confirmation_field'</span><span style="color: #339933;">,</span>
                fieldLabel<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Confirm Password&quot;</span><span style="color: #339933;">,</span>
                validator<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>value<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
                    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span>value <span style="color: #339933;">==</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;js_signup_password_field&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">value</span><span style="color: #009900;">&#41;</span> 
<span style="color: #339933;">||</span> <span style="color: #3366CC;">&quot;Your passwords do not match&quot;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">Hidden</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;authenticity_token&quot;</span><span style="color: #339933;">,</span>
                value<span style="color: #339933;">:</span> authenticity_token
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">form</span>.<span style="color: #660066;">Hidden</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
                <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;user[role]&quot;</span><span style="color: #339933;">,</span>
                value<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;consumer&quot;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
            buttons<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#123;</span>
                handler<span style="color: #339933;">:</span> submitHandler<span style="color: #339933;">,</span>
                text<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Signup&quot;</span><span style="color: #339933;">,</span>
                formBind<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#93;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

<p>The noteworthy steps are: first, I hide the &#8216;no-js-form&#8217;, then I copy the authenticity_token that gets generated by a rails form to put in the js-generated form.  Then, <code>standardSubmit : true</code> is the config option that makes a FormPanel <strong>not</strong> submit as an XmlHttpRequest.  The funny code in the submitHandler is getting the underlying form object and calling submit on it, but as I write this it doesn&#8217;t make sense why both would be necessary. Finally, <code>formbind : true</code> causes the submit button to be deactivated while there are failing validations, and there&#8217;s some handy code for making sure that the password_confirmation matches password (totally lifted from somewhere else, see above).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stupididea.com/2008/07/02/rails-and-ext-non-ajax-signup-form/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setup for Alexandria Development: Part II</title>
		<link>http://www.stupididea.com/2007/12/19/87/</link>
		<comments>http://www.stupididea.com/2007/12/19/87/#comments</comments>
		<pubDate>Wed, 19 Dec 2007 20:06:35 +0000</pubDate>
		<dc:creator>method</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Technical]]></category>

		<guid isPermaLink="false">http://www.stupididea.com/?p=87</guid>
		<description><![CDATA[(…after too much grief today installing Mephisto and mucking with Apache virtualhosts; I’ll get Part I back from the ether eventually) Update: Done. Update: This is a post moved over from the short-lived Mephisto blog, and ported back in time. &#8230; <a href="http://www.stupididea.com/2007/12/19/87/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><small>(…after too much grief today installing Mephisto and mucking with Apache virtualhosts; I’ll get Part I back from the ether eventually) <strong>Update</strong>: Done. <strong>Update</strong>: This is a post moved over from the short-lived Mephisto blog, and ported back in time.</small></p>
<p>First of all, the alexandria binary is just a ruby script that does a require &#8216;alexandria&#8217; and runs Alexandria.main.</p>
<p>Alexandria.main is a method on the Alexandria ‘module’ that is used throughout the code (modules are ‘namespaces’ to avoid naming conflicts). This method is found in lib/alexandria.rb:</p>
<pre lang="ruby>
module Alexandria
# ... bunch of constants used in the 'about' dialogue
  def self.main
    $DEBUG = !ENV['DEBUG'].nil?
    $DEBUG = true if ARGV.include? "--debug"
    if $DEBUG
      Alexandria.log.level = Logger::DEBUG
    end
    Alexandria.log.debug { "Initializing Alexandria..." }

    ENV['http_proxy'] = nil if !ENV['http_proxy'].nil? \
    and URI.parse(ENV['http_proxy']).userinfo.nil?
    Alexandria::UI.main
  end
# ... bunch of requires below here
end
</pre>
<p>As you should be able to see, this method isn’t doing anything but setting up some global variables (like $DEBUG) and logging, and doing something weird with http_proxy. The real line is Alexandria::UI.main. That’s in lib/alexandria/ui.rb:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Pango
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">ellipsizable</span>?
    <span style="color:#0066ff; font-weight:bold;">@ellipsizable</span> <span style="color:#006600; font-weight:bold;">||</span>= Pango.<span style="color:#9900CC;">constants</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'ELLIPSIZE_END'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Alexandria
  <span style="color:#9966CC; font-weight:bold;">module</span> UI
    <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">main</span>
      <span style="color:#6666ff; font-weight:bold;">Gnome::Program</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'alexandria'</span>, VERSION<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">app_datadir</span> =
        <span style="color:#6666ff; font-weight:bold;">Config::MAIN_DATA_DIR</span>
      Icons.<span style="color:#9900CC;">init</span>
      MainApp.<span style="color:#9900CC;">new</span>
      Gtk.<span style="color:#9900CC;">main</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Gtk.main is the main loop of a gtk program. You set up your windows and widgets before running it, and it makes them all spin until you exit. So, after Icons.init runs (guess what that does), MainApp.new does all the work from now on.</p>
<p>The Pango code above this is interesting for seeing some Ruby syntax and features. Pango is a text-rendering and layout library inside gtk. The code is adding an elipsizable? “question” method (return true/false) to the Pango module. self.elipsizable? means that it’s defining a class method, a method on a class that doesn’t depend on instance data. ||= is a way of saying, “set the variable to this unless it’s already been set to something else (ie, it’s not nil)”.</p>
<p>Unfortunately, MainApp.new is in the massive MainApp class at lib/alexandria/ui/main_app.rb. This class does a lot (too much). The main thing it does is handle all the callbacks from the main window and its widgets. Let’s just take a look at the top:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> Alexandria
  <span style="color:#9966CC; font-weight:bold;">module</span> UI
    <span style="color:#9966CC; font-weight:bold;">class</span> MainApp <span style="color:#006600; font-weight:bold;">&lt;</span> GladeBase
      attr_accessor <span style="color:#ff3333; font-weight:bold;">:main_app</span>, <span style="color:#ff3333; font-weight:bold;">:actiongroup</span>, <span style="color:#ff3333; font-weight:bold;">:appbar</span>
      <span style="color:#9966CC; font-weight:bold;">include</span> Logging
      <span style="color:#9966CC; font-weight:bold;">include</span> GetText
      GetText.<span style="color:#9900CC;">bindtextdomain</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Alexandria::TEXTDOMAIN</span>, <span style="color:#0000FF; font-weight:bold;">nil</span>, <span style="color:#0000FF; font-weight:bold;">nil</span>, <span style="color:#996600;">&quot;UTF-8&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">module</span> Columns
        COVER_LIST, COVER_ICON, TITLE, TITLE_REDUCED, AUTHORS,
        ISBN, PUBLISHER, PUBLISH_DATE, EDITION, RATING, IDENT,
        NOTES, REDD, OWN, WANT, TAGS = <span style="color:#006600; font-weight:bold;">&#40;</span>0..16<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_a</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      <span style="color:#008000; font-style:italic;"># The maximum number of rating stars displayed.</span>
      MAX_RATING_STARS = <span style="color:#006666;">5</span>
&nbsp;
      <span style="color:#9966CC; font-weight:bold;">def</span> initialize
        <span style="color:#9966CC; font-weight:bold;">super</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;main_app.glade&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#0066ff; font-weight:bold;">@prefs</span> = Preferences.<span style="color:#9900CC;">instance</span>
        load_libraries
        initialize_ui
        on_books_selection_changed
        restore_preferences
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#008000; font-style:italic;">#... snip</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#008000; font-style:italic;"># ... snip</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>A couple points here. MainApp inherits from GladeBase. The attr_accessor is a declaration that makes the @main_app, @actiongroup and @appbar instance variables publicly readable and settable. super(&#8220;main_app.glade&#8221;) calls the initialize method on GladeBase with the glade file that contains the definitions for all the widgets Alexandria uses. The names of the methods tell you about what they do (good!). Because these methods need to know about what the user’s preferences are, @prefs has been made available before they are called.</p>
<p>To understand what MainApp is doing, it seems like we need to understand what GladeBase is.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Alexandria
  <span style="color:#9966CC; font-weight:bold;">module</span> UI
    <span style="color:#9966CC; font-weight:bold;">class</span> GladeBase
      <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span>
        file = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Alexandria::Config::DATA_DIR</span>, <span style="color:#996600;">'glade'</span>, filename<span style="color:#006600; font-weight:bold;">&#41;</span>
        glade = GladeXML.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>file, <span style="color:#0000FF; font-weight:bold;">nil</span>, <span style="color:#6666ff; font-weight:bold;">Alexandria::TEXTDOMAIN</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>handler<span style="color:#006600; font-weight:bold;">|</span> method<span style="color:#006600; font-weight:bold;">&#40;</span>handler<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
        glade.<span style="color:#9900CC;">widget_names</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>name<span style="color:#006600; font-weight:bold;">|</span>
          <span style="color:#9966CC; font-weight:bold;">begin</span>
            instance_variable_set<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;@#{name}&quot;</span>.<span style="color:#9900CC;">intern</span>, glade<span style="color:#006600; font-weight:bold;">&#91;</span>name<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#9966CC; font-weight:bold;">rescue</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>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So GladeBase is using GladeXML to get the widgets out of the xml file and load them into memory. It then iterates through them, *adding them to MainApp (instance_variable_set is doing the work). So if there’s a widget called @main_menu, MainApp will get this variable to work with. These widgets work exactly as though they had been created “by hand”.</p>
<p>If you’ve been following, take a look at load_libraries and see if the code there makes sense. Here’s a short snippet:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">      <span style="color:#9966CC; font-weight:bold;">def</span> load_libraries
        completion_models = CompletionModels.<span style="color:#9900CC;">instance</span>
        <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@libraries</span>
          <span style="color:#0066ff; font-weight:bold;">@libraries</span>.<span style="color:#9900CC;">all_regular_libraries</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>library<span style="color:#006600; font-weight:bold;">|</span>
            <span style="color:#9966CC; font-weight:bold;">if</span> library.<span style="color:#9900CC;">is_a</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>Library<span style="color:#006600; font-weight:bold;">&#41;</span>
              library.<span style="color:#9900CC;">delete_observer</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span>
              completion_models.<span style="color:#9900CC;">remove_source</span><span style="color:#006600; font-weight:bold;">&#40;</span>library<span style="color:#006600; font-weight:bold;">&#41;</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
          <span style="color:#9966CC; font-weight:bold;">end</span>
          <span style="color:#0066ff; font-weight:bold;">@libraries</span>.<span style="color:#9900CC;">reload</span>
        <span style="color:#9966CC; font-weight:bold;">else</span>
          <span style="color:#008000; font-style:italic;">#On start</span>
&nbsp;
          <span style="color:#0066ff; font-weight:bold;">@libraries</span> = Libraries.<span style="color:#9900CC;">instance</span>
          <span style="color:#0066ff; font-weight:bold;">@libraries</span>.<span style="color:#9900CC;">reload</span>
<span style="color:#008000; font-style:italic;"># ...</span></pre></div></div>

<p>This is where things start to get confusing. load_libraries is also being used to reload libraries, so first it checks to see if @library has been defined already (refactoring opportunity). In the normal case, Libraries gets called by by invoking Libraries.instance. To understand this, you have to know that Libraries uses a factory class method to make sure that Libraries only gets created once (making the Libraries instance a “singleton”).</p>
<p>At the bottom of load_libraries is some interesting code:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># ...</span>
        <span style="color:#0066ff; font-weight:bold;">@libraries</span>.<span style="color:#9900CC;">all_regular_libraries</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>library<span style="color:#006600; font-weight:bold;">|</span>
          library.<span style="color:#9900CC;">add_observer</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          completion_models.<span style="color:#9900CC;">add_source</span><span style="color:#006600; font-weight:bold;">&#40;</span>library<span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#008000; font-style:italic;"># ...</span></pre></div></div>

<p>This is telling each library in @libraries (the Libraries singleton) to add self as an “observer”. What does this mean? It means that class Library is “observable”. To see what that means you have to look at Library. First let’s look at Libraries, in lib/alexandria/library.rb:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">class</span> Libraries
    attr_reader <span style="color:#ff3333; font-weight:bold;">:all_libraries</span>, <span style="color:#ff3333; font-weight:bold;">:ruined_books</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#CC00FF; font-weight:bold;">Observable</span>
    <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#CC00FF; font-weight:bold;">Singleton</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># ... snip</span>
&nbsp;
    <span style="color:#008000; font-style:italic;">#######</span>
    private
    <span style="color:#008000; font-style:italic;">#######</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize
      <span style="color:#0066ff; font-weight:bold;">@all_libraries</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> notify<span style="color:#006600; font-weight:bold;">&#40;</span>action, library<span style="color:#006600; font-weight:bold;">&#41;</span>
      changed
      notify_observers<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span>, action, library<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Libraries is including the Observable and Singleton modules to give it special methods (in Python these are called “mixins”). Singleton gave it the instance method. Observable is giving it the notify_observers method. What this method does is “call up” all the observers of this instance by calling their update methods.</p>
<p>Libraries has many Librarys (it’s a little weird to give a class a plural name). Each library is an observer of Libraries. Library is also Observable:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> Library <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC0066; font-weight:bold;">Array</span>
    <span style="color:#9966CC; font-weight:bold;">include</span> Logging
<span style="color:#008000; font-style:italic;"># ...</span>
    <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#CC00FF; font-weight:bold;">Observable</span></pre></div></div>

<p>As we saw above, MainApp adds itself as an observer to each library. If you look on MainApp you’ll see that it has an update method:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> update<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>ary<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># ...</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>*ary means that it accepts an array as its argument. This method gets called from many places in Library, like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">        source_library.<span style="color:#9900CC;">notify_observers</span><span style="color:#006600; font-weight:bold;">&#40;</span>source_library,
                                        BOOK_REMOVED,
                                        book<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>That’s all for now. To learn more about Observers read <a href="http://ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html">this</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stupididea.com/2007/12/19/87/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
