<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>John Duff's Blog</title>
    <link href="http://jduff.github.com/atom.xml" rel="self"/>
    <link href="http://jduff.github.com/"/>
    <updated>2019-03-20T00:12:27+00:00</updated>
    <id>http://jduff.github.com/</id>
    
    
    <entry>
        <title>Values, or quirks, of John Duff</title>
        
        <link href="http://jduff.github.com/2013/10/06/values/"/>
        <updated>2013-10-06T00:00:00+00:00</updated>
        <id>jduff.github.com:/2013/10/06/values</id>
        <content type="html">p=. !/images/posts/2013-10-06/values.jpg(Values)!

A few months ago I was introduced to this blog post by &quot;Luc Levesque&quot;:http://luclevesque.com/ titled &quot;How to help new employees be rockstars, a new approach&quot;:http://luclevesque.com/post/15881999207/how-to-help-new-employees-be-rockstars-a-new-approach. In this post Luc talks about his &quot;Blueprint to Luc and his Quirks&quot; which outlines the things that are important to him and some of his particular quirks. Luc then gives this to his new employees and goes over it with them when they start so that they understand a bit more about him and how he works. The idea is that if there are no surprises, all the expectations and potential quirks are put out there straight away, then there will be less questions about how someone new should react or how Luc will react to particular actions.

I thought this was a great idea and a tool that I could make use of for myself at &quot;Shopify&quot;:http://shopify.com. This should be considered a constant work in progress, I am constantly changing the way I work and what I take on, so it only makes sense that some of my values and quirks will change along with that.

h3. The Values, or quirks, of John Duff

*Caring*
I care about Shopify and what we are doing. I jump on things that need to be done, dig into problems and make Shopify better. I&#39;m around when issues come up. I fight for code quality and correct solutions.

*Responsiveness*
Being responsive allows us to move at incredible speed. I might not get back to your email or question a minute later (often I will), but you will hear something within the day. Making sure people have the information they need is super important to me. I use my phone for email, code review and everything in between so that I can always respond.

*Ownership*
When I tackle a problem I try to understand every aspect of it. I think about the solution and what it will mean in the long term. There are endless interesting things to do at Shopify, but completing one of them is worth more than starting ten. Have the determination to see things that matter through to completion.

*Growth*
I am always trying to improve and am constantly pushing myself. I take on as much as I can handle, then I ask for a bit more. By pushing myself and what I am capable of, I am learning and growing - and so is Shopify.

*Passion and Drive*
I love what I do. Shopify is my startup, it is as important to me as anything I would start on my own. I am invested in our success and the success of everyone on the team.

*Doing it*
If I see something broken, I fix it. If someone needs help, I help them. I don&#39;t complain, I get in and do something about it. I do what I think is right first and ask for permission later.

*Insatiable Curiosity*
I ask questions about what I am doing if I&#39;m not sure. I am always open to new ideas or solutions. I like to back things up with data or alternatives and question the necessity of features and changes. Every decision is mutable.

I found it a great exercise to even just come up with these values, let alone share them with everyone. Big thanks to &quot;Luc&quot;:http://luclevesque.com/ for providing the inspiration for this and &quot;Cam Gregg&quot;:https://twitter.com/CamGregg for suggesting I give this a shot.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Riding the Monorail</title>
        
        <link href="http://jduff.github.com/2013/06/05/riding-the-monorail/"/>
        <updated>2013-06-05T00:00:00+00:00</updated>
        <id>jduff.github.com:/2013/06/05/riding-the-monorail</id>
        <content type="html">p=. !{max-width:80%}/images/posts/2013-06-05/monorail.jpg(Monorail)!

A few months ago I had the amazing opportunity to speak at &quot;BigRubyConf&quot;:http://www.bigrubyconf.com. This is a new ruby conference all about people doing big things with ruby and it was amazing. It was great to get together and talk to people who are dealing with the same or similar problems that we do at &quot;Shopify&quot;:http://www.shopify.com with running large Rails applications.

One interesting thing I started to notice when talking to all these developers with applications at a similar scale to &quot;Shopify&quot;:http://www.shopify.com (code and/or traffic wise) is they often referred to it as their &#39;monorail&#39;. This came up again a couple of times when I was at &quot;RailsConf&quot;:http://www.railsconf.com as well. This was a new thing to me and as I talked to more people the meaning of this term became clearer and clearer.

When people used the term &#39;monorail&#39; they were referring to their single, core rails application. This is usually the application that the company started with. This is also the application that they are often chipping away at to turn into services. This is all well and good, the interesting part to me was that almost everyone who referred to their &#39;monorail&#39; did so in a negative way. This was the application that was really hard to deal with, or that they were breaking apart into services or the code was really complicated and scary.

So, back up a bit, I said we have a similar sized application at &quot;Shopify&quot;:http://www.shopify.com but we don&#39;t refer to it as our &#39;monorail&#39;. We have a few services around it, supplementary apps etc, but still we don&#39;t call the largest of them a &#39;monorail&#39;. What do we call it? It is &#39;Shopify Core&#39;. Another interesting point is we don&#39;t refer to &#39;Shopify Core&#39; in a negative way, I am extremely proud of this application and the code that it holds. I tell all developers, even non developers, that this holds the answers to all the questions you may have about &quot;Shopify&quot;:http://www.shopify.com or how to do just about anything in Ruby or Rails. &quot;Chances are the problem you are trying to solve has been solved in Shopify Core&quot;. Since &quot;Shopify&quot;:http://www.shopify.com has been in development for almost a decade, started even before version 1.0 of Rails, then it is likely the git history holds the solution to most Ruby / Rails problems in ANY version of Rails. I find this incredible.

I guess the big question to ask is why do we look at Shopify Core so differently? I would imagine the applications have a similar amount of code and complexity, what makes us different? I think a big part of this is the fact that &quot;Shopify&quot;:http://www.shopify.com has been built and is still being driven by a team that holds a lot of value in writing quality code. We even recently started a rotating team of developers where when you are on that team your mandate is to reduce technical debt and improve the quality of the code base. This is time when we don&#39;t work on features and make the code base better. Awesome.

Now, we&#39;re not all magical developers that write perfect code. Far from it. I think the difference is that we are able to and encouraged to go back and improve things. I&#39;ve heard Tobi talk often enough about how while he was learning to program his mentor would often rip apart his code and ask him to throw it away and write it again. This leads you to not being tied to the code you write; it&#39;s just a tool to get a task done. This is a concept that Tobi and the rest of the team tries to ingrain in developers. Once you get this it is much easier to throw away a piece of code and rewrite it. It also helps that the core development team that wrote most of the code that &quot;Shopify&quot;:http://www.shopify.com launched with is still at the company.

Do I have a good answer for why we look at Shopify Core differently? Not really. I have no concrete reason for why look at our core code base so differently than other companies. It might have to do with the focus on quality, or maybe not being tied to the code you write. It might be the type of people we hire, or the culture of the company itself, I really don&#39;t know. To be honest it doesn&#39;t matter to me that much; I&#39;m happy that I work on a code base that I can be proud of and that I enjoy working with everyday, that&#39;s all that really matter to me.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>One Month in At Shopify!</title>
        
        <link href="http://jduff.github.com/2011/04/29/one-month-in-at-shopify/"/>
        <updated>2011-04-29T00:00:00+00:00</updated>
        <id>jduff.github.com:/2011/04/29/one-month-in-at-shopify</id>
        <content type="html">Like the headline says, I&#39;m a month into my new job at &quot;Shopify&quot;:http://shopify.com and it&#39;s going great! I thought people might be interested in hearing what it&#39;s like getting started there.

h3. What is Shopify?

You haven&#39;t heard of Shopify? Where have you been?? Just kidding, it&#39;s okay if you haven&#39;t heard of them before :). Shopify is a web application that lets you set up an online store to sell your goods. It integrates with a tone of services for acceptings payments, shipping and anything else you might need to run an online store. This is all done using amazing technologies like &quot;Ruby on Rails&quot;:http://rubyonrails.org/, &quot;jQuery&quot;:http://jquery.com/, &quot;Redis&quot;:http://redis.io/, &quot;AWS&quot;:http://aws.amazon.com/ and much more. Did I mention we&#39;re location in the &quot;ByWard Market&quot;:http://en.wikipedia.org/wiki/Byward_Market in downtown Ottawa? Yes, it is awesome.

h3. The First Day

So, my first day. The hours are pretty loose, people come in anywhere between 8 and 10am, I like to come in around 9 am myself. So I come in and I&#39;m met by Brittany in HR and we start out with a bit of paperwork, then the fun begins. It starts out with getting a big gift bag with my &#39;welcome package&#39; and what a welcome it is. Gift cards, some chocolate, a notebook and some Shopify schwage. Then we walk over to the one free desk in the main dev area, or &#39;The Pit&#39;, where I will be sitting. A nice big Cinema Display is already sitting there, but no laptop, we had to go over to the Apple Store and get a new one of those.

Once I&#39;m all set with a desk and computer I spent a little time getting things installed, &quot;my dotfiles&quot;:https://github.com/jduff/dotfiles setup and Shopify checked out running. Next up I spent some time with Dennis Theisen who points me to a couple of bugs in the &quot;Partners Area&quot;:http://www.shopify.com/partners of Shopify. I spent the rest of the day fixing the bugs Dennis assigned me and a few more things that I found along the way. I got to put some bug fixes into code review and the code went into the master branch that day and in production the next. I&#39;ve got to say that is pretty satisfying; first day in and already committing code.

h3. Day Two

For my second day I spent the morning pair programming with &quot;Jesse Storimer&quot;:http://jstorimer.com/, continuing on the invoicing refactoring that I was helping him with during my interview pairing. It&#39;s always fun working with Jesse, I always learn something new and on top of that he&#39;s a VIM guy as well :). After the pairing I spent some time fixing up some of the other bugs I found in the &quot;Partners Area&quot;:http://www.shopify.com/partners the day before. I&#39;m probably skipping over all the fun stuff like going out to lunch in the &quot;ByWard Market&quot;:http://en.wikipedia.org/wiki/Byward_Market, talking with some of my awesome new coworkers and all that stuff, but be sure lots of fun stuff is happening everyday.

h3. The rest of the Month

The rest of the month has went by crazy fast and I&#39;ve already gotten a chance to work on a lot of different things. I&#39;ve done a little bit of work on &quot;ActiveMerchant&quot;:https://github.com/Shopify/active_merchant, added SSL to the &quot;Partners Area&quot;:http://www.shopify.com/partners, fixed a few IE and other bugs, some work with invoicing, Google Base and a little bit of work for the &quot;contest we just launched&quot;:http://www.shopify.com/contest. A pretty busy month, but that&#39;s the way I like it. Oh ya, I&#39;m also working on a &quot;Shopify App&quot;:http://www.shopify.com/partners/apps in my Friday afternoon time. It has been great so far and I&#39;m looking forward to every new day of it.

If any of this sounds pretty cool to you &quot;we are hiring&quot;:http://www.shopify.com/careers for a number of different positions. If you want to know more just give me a shout or send in your resume.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>tmdb_party 0.9.0 Released</title>
        
        <link href="http://jduff.github.com/2011/03/14/tmdb_party-0_9_0-released/"/>
        <updated>2011-03-14T00:00:00+00:00</updated>
        <id>jduff.github.com:/2011/03/14/tmdb_party-0_9_0-released</id>
        <content type="html">Over the weekend I spent a little bit of time cleaning up some of the code and adding a few new features to my gem gem for talking to &quot;themoviedb.org&quot;:http://www.themoviedb.org/, &quot;tmdb_party&quot;:https://github.com/jduff/tmdb_party. If you&#39;ve never heard of themoviedb.org you should really check it out. It&#39;s a lot like &quot;IMDB&quot;:http://www.imdb.com/ but it is completely user generated and has an &quot;open api&quot;:http://api.themoviedb.org/2.1 that anyone can use.

So, what&#39;s new in 0.9.0? Well, under the covers I did a &quot;bunch&quot;:https://github.com/jduff/tmdb_party/commit/92a4700e83ca34035ce03e65814103135e020f5a of &quot;house&quot;:https://github.com/jduff/tmdb_party/commit/bfb1778adae53ad21966bfa3a5cddc6e6f640d9a &quot;cleaning&quot;:https://github.com/jduff/tmdb_party/commit/87e6d5ee58fe36255cb2f1ab7dc3fce06d97b5f6, moved some files around and &quot;removed some useless extensions&quot;:https://github.com/jduff/tmdb_party/commit/f76cfaf3903341413524f5ea5353676ad8c53576 to core classes that were used internally and just cluttering up your classes. Nothing too special there, but should make the code a lot easier to understand and maintain.

I also managed to implement two new features that I&#39;m pretty happy about. The first one is based on some work I noticed in forks by &quot;willchang&quot;:https://github.com/willchang and &quot;razielgn&quot;:https://github.com/razielgn. They had both implemented the &quot;Movie.browse&quot;:http://api.themoviedb.org/2.1/methods/Movie.browse method from the api, but because of my recent changes I couldn&#39;t pull either of them very cleanly. Since it was a pretty straightforward change I just added it myself, but kudos to those guys for making me realize it was missing. Here&#39;s a little example of what you can do with this new method:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;tmdb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TMDBParty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;key&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;browse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;Transformers&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:rating_min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:min_votes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

There&#39;s a number of different options, all of which can be found in the &quot;api docs&quot;:http://api.themoviedb.org/2.1/methods/Movie.browse.

The other feature I added is something I find really cool. This comes from talking to &quot;John Tajima&quot;:http://twitter.com/#!/redronin who told me about this cool idea of being able to generate a unique hash from a video file which you can use to identify the video. It turns out that &quot;themoviedb.org&quot;:http://www.themoviedb.org/ api already supports searching based on the file hashes when using the &quot;Media.getInfo&quot;:http://api.themoviedb.org/2.1/methods/Media.getInfo method. So I went ahead and grabbed the &quot;hashing algorithm&quot;:http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes, made a few changes and &quot;here we are&quot;:https://github.com/jduff/tmdb_party/commit/e1a67bdbd1f003cbb590f6ca9bbfec639616566d. Here&#39;s how we use it:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;tmdb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TMDBParty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;key&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;transformers.avi&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_file_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This will generate the hash for the given file and use that in the query to &quot;Media.getInfo&quot;:http://api.themoviedb.org/2.1/methods/Media.getInfo returning all the information for whatever movie that might be. Now you can easily figure out what all those randomly named files on your disk really are.

The last thing I wanted to point out was some work that &quot;Mange&quot;:https://github.com/Mange did awhile back adding support for retrieving results in different languages, lots more tests, person search and whole bunch more. Almost all of the methods take an optional final parameter for the language you want your results in:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;tmdb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TMDBParty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;key&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;transformers&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;fr&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

So that&#39;s all there is for now, thanks again to everyone who has contributed to this project with code, ideas, comments and everything else. If you need help getting started check out the &quot;readme&quot;:https://github.com/jduff/tmdb_party or give me a shout and I&#39;ll gladly help you out.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings Jan 27 2011</title>
        
        <link href="http://jduff.github.com/2011/01/27/learnings-Jan-27-2011/"/>
        <updated>2011-01-27T00:00:00+00:00</updated>
        <id>jduff.github.com:/2011/01/27/learnings-Jan-27-2011</id>
        <content type="html">Wow, it&#39;s been a long time since I&#39;ve posted some learnings. Or anything for that matter. Well, I&#39;ve been saving them up so here&#39;s a few from a little while back. Hopefully I&#39;ll be getting back into the swing of things and start writing some real posts. For now, this is it.


* When doing a screen recoding with Quicktime in Snow Leopard before starting the recording there&#39;s a little drop down to the right that can be used to select which microphone to use. A nice walkthrough can be found &lt;a href=&#39;http://www.icreatemagazine.com/tips/tutorial-record-your-screen-in-quicktime-x/&#39;&gt;here&lt;/a&gt;.

* with jQuery.extend the first hash is modified, the result is also returned:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;one&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;one&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;two&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;two&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;two&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;three&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}...)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;one&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;one&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;two&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;three&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* -k option to IExplorer will start it in full screen kiosk mode

* ActionController::Base.helpers gives you access to the Rails html helpers (div_for, content_tag, etc)

* link_to &quot;something&quot;, :controller=&gt;:something, :action=&gt;&quot;...&quot; will map to :controller=&gt;&quot;devise/something&quot; if called when rendering a devise view. Use dynamic helper methods (ex. something_path) to get around this issue.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 39 2010</title>
        
        <link href="http://jduff.github.com/2010/11/24/learnings-for-week-39-2010/"/>
        <updated>2010-11-24T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/11/24/learnings-for-week-39-2010</id>
        <content type="html">* If you need to access Git on a remote machine and can&#39;t add an ssh key from that machine to the server adding a few options to the .ssh/config should do the trick:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;User jduff
Host git.server.com&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;If you then ssh to the machine passing the -A option (to forward the agent) git should work perfectly.

* In windows Run =&gt; \\tsclient (Terminal Server Client) will list network drives

* With Rails 3 unobtrusive Javascript (using &lt;a href=&#39;http://github.com/rails/jquery-ujs&#39;&gt;jquery-ujs&lt;/a&gt;) adding &#39;data-remote=true&#39; and &#39;action=URL&#39; attributes any input element can be made to do an ajax request without any extra work.

* &lt;a href=&#39;http://github.com/tomas-stefano/infinity_test&#39;&gt;infinity_test&lt;/a&gt; is an alternative to &lt;a href=&#39;http://ph7spot.com/musings/getting-started-with-autotest&#39;&gt;Autotest&lt;/a&gt; that uses &lt;a href=&#39;http://github.com/mynyml/watchr&#39;&gt;Watchr&lt;/a&gt; and &lt;a href=&#39;http://rvm.beginrescueend.com&#39;&gt;RVM&lt;/a&gt; allowing you to easily run your tests against multiple rubies at once.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 38 2010</title>
        
        <link href="http://jduff.github.com/2010/11/06/learnings-for-week-38-2010/"/>
        <updated>2010-11-06T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/11/06/learnings-for-week-38-2010</id>
        <content type="html">Not much for learnings for a couple weeks so skipping a few.

* Rails error messages can be cleaned up so that the user isn&#39;t overloaded by adding the simple helper described &lt;a href=&#39;http://codebeef.com/removing-duplicate-error-messages-in-rails&#39;&gt;here&lt;/a&gt;

* Setting up an app to authenticate with Facebook using &lt;a href=&#39;http://github.com/plataformatec/devise&#39;&gt;Devise&lt;/a&gt; is really straight forward. We have a sample Rails 3 app &lt;a href=&#39;http://github.com/jduff/facebook_devise&#39;&gt;right here&lt;/a&gt; that you can check out.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 36 2010</title>
        
        <link href="http://jduff.github.com/2010/10/27/learnings-for-week-36-2010/"/>
        <updated>2010-10-27T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/10/27/learnings-for-week-36-2010</id>
        <content type="html">* Google provides some modern &lt;a href=&#39;http://code.google.com/webfonts&#39;&gt;webfonts&lt;/a&gt; that anyone can use through their &lt;a href=&#39;http://code.google.com/apis/webfonts/docs/getting_started.html&#39;&gt;font api&lt;/a&gt;.

* SQL Authentication can be turned on for SQL Server through the Management Console under the Server Properties. More details can be found &lt;a href=&#39;http://kbase.gfi.com/showarticle.asp?id=KBID002804&#39;&gt;here&lt;/a&gt;.

* Using the &quot;Facebooker2&quot;:http://github.com/mmangino/facebooker2 gem you must call &#39;fetch&#39; on the Facebook user to get their user details.&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;current_facebook_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fetch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* Posting to a users feed is really easy with &quot;Facebooker2&quot;:http://github.com/mmangino/facebooker2&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;current_facebook_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;feed_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Mogli&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* You can prevent Parallels from automatically switching to Coherence mode by changing the Startup View in Startup and Shutdown options for the VM. More details &lt;a href=&#39;http://download.parallels.com/desktop/v5/docs/en/Parallels_Desktop_Users_Guide/26728.htm&#39;&gt;here&lt;/a&gt;.

* Came across an article with &lt;a href=&#39;http://www.queness.com/post/402/15-css-tips-and-tricks&#39;&gt;15 CSS Tips and Tricks&lt;/a&gt; that a had a few interesting points (IE6 PNG with filters) that I hadn&#39;t known about.

* Rails 3 respond_with calls as_json on objects when returning a json response instead of to_json

* Rails 3 respond_with returns &quot; &quot; on successful update or delete calls. jQuery has trouble parsing this as json so always fails. On the jQuery side this can be fixed by adding this line (I came up with this based some of the suggestions in &lt;a href=&#39;http://www.kreusch.com.br/2010/03/30/rails-3-responders-jquery-1-4-and-empty-json-results&#39;&gt;this article&lt;/a&gt;:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajaxSetup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;dataFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;{}&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Introducing Todoly.net</title>
        
        <link href="http://jduff.github.com/2010/10/24/introducing-todoly/"/>
        <updated>2010-10-24T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/10/24/introducing-todoly</id>
        <content type="html">So, I&#39;ve been really slacking with the blogging lately, I haven&#39;t even been posting my learnings which is a 10 minute process at most. Hopefully I can get back in the habit, no promises though. Okay, so what have I been up to the last little while? Well, I&#39;ve been working on a little side project app that I recently put up and wanted to talk about a little bit.

h2. What is it?

Well from the post title you can probably guess it is called &quot;Todoly&quot;:http://todoly.net and can by found at &quot;todoly.net&quot;:http://todoly.net. &quot;Todoly&quot;:http://todoly.net is a really simple todo list application with very few features and is happy that way. I can hear you now, &quot;Why did you bother writing another todo list app, have you not heard of X, Y or Z?&quot;. Because I wanted to dammit, that&#39;s why.

h2. Background

More than just wanting to write something I did have a few specific goals that writing &quot;Todoly&quot;:http://todoly.net has helped me to achieve.

# Build something using Rails 3.
# Try out my &quot;Rails App Template&quot;:http://github.com/jduff/rails-templates and expand on what is included in it.
# Actually finish something and get it deployed publicly.

&quot;Todoly&quot;:http://todoly.net has done all these things for me and more. I&#39;ve been able to play around with some of the cool new things in Rails 3 like the new &quot;query interface&quot;:http://m.onkey.org/2010/1/22/active-record-query-interface, &quot;unobtrusive javascript&quot;:http://railscasts.com/episodes/205-unobtrusive-javascript, &quot;responders&quot;:http://weblog.rubyonrails.org/2009/8/31/three-reasons-love-responder and much, much more. I&#39;ve found a number of bugs in my &quot;app template&quot;:http://github.com/jduff/rails-templates and have a few ideas on things I can add to make it more complete. Last, but not least, I got to try out deploying an app to &quot;Heroku&quot;:http://http://heroku.com/ (which was amazingly simple) and have it running in the wild.

This last point was really important to me and was the main reason for choosing a simple todo list application. I&#39;ve worked on a number of side projects over the years but never actually released a working application because I got bored with the project, had another idea or life distract me or whatnot. I&#39;ve released lots of bits and pieces to my &quot;github account&quot;:http://github.com/jduff but it feels very different being able to finish a project and put it out there.

h2. What&#39;s under the hood?

&quot;Todoly&quot;:http://todoly.net is a pretty straight forward Rails 3 application running locally under MySQL and under PostgreSQL on &quot;Heroku&quot;:http://heroku.com in production. I used a number of gems and open source projects include, but not limited to:

* &quot;jQuery&quot;:http://http://jquery.com/
* &quot;Devise&quot;:http://github.com/plataformatec/devise for authentication.
* &quot;Simple Form&quot;:http://github.com/plataformatec/simple_form to simplify HTML form development.
* &quot;CanCan&quot;:http://github.com/ryanb/cancan for authorization.
* &quot;HTML 5 boilerplate&quot;:http://github.com/paulirish/html5-boilerplate (actually &quot;my own fork&quot;:http://github.com/jduff/html5-boilerplate that I made for Rails apps)

Did I mention that the source for the whole project is up on GitHub so you can &quot;check it out yourself&quot;:http://github.com/jduff/todoly if you want. This has already led to some cool stuff, like a friend of mine taking the idea for the app and implementing the same features in &quot;Node.js&quot;:http://http://nodejs.org/. You can take a look at that on GitHub as well, &quot;right here&quot;:http://github.com/glongman/node-todo.

h2. Why is Todoly better than X, Y or Z?

In all honesty it probably isn&#39;t any better than the other, countless, todo list applications out there. I have been using it regularly for a little while though and like it for a number of reasons.

The main reason I like it is the interface is really simple. It&#39;s all about adding tasks and completing them, so that&#39;s what the interface helps you to do. I added a cool little feature that lets you focus on a groups of tasks by selecting the tag you&#39;re interested in. I find this to be all I really need to keep track of what I need to do.

Since I have the code and can push a new release whenever I want if there is ever something I need from the application I can just add it. Since the project is open source you can &quot;fork it&quot;:http://http://github.com/jduff/todoly and do the same. I&#39;ll gladly pull in new features and bug fixes and release them to the main &quot;Todoly.net&quot;:http://todoly.net website as well.

h2. Where to now?

I have a number of features I would like to add to the application such as task reordering, making a better homepage and making some tweaks to clean up the UI a little more. I probably wont get to those until it becomes a problem with my everyday use.

Until then I&#39;m going to start working on a native iPhone application that talks to &quot;Todoly&quot;:http://todoly.net. I fixed up the styling the other day so that it works pretty well in Safari on the iPhone but going with the same premise for the &quot;Todoly&quot;:http://todoly.net web application, I want to actually finish and release an iPhone app. I&#39;ve already started and the source will also go up on GitHub once I make a little more progress. I&#39;m also going to try and make it so you can point the iPhone application to a different url for it&#39;s data, so if you want to run your own &quot;Todoly&quot;:http://todoly.net somewhere else or run &quot;glongmans version&quot;:http://github.com/glongman/node-todo it should &quot;Just Work&quot; (tm) with those backends.

I&#39;m also curious about making a Rails app an Oauth2 provider so I might build this into &quot;Todoly&quot;:http://todoly.net to start playing around with that. There doesn&#39;t seem to be a whole lot of up to date information on doing this so it would be nice to get a good example or even extract a gem out of the work.

Anyways, that&#39;s all I have to say about &quot;Todoly&quot;:http://todoly.net at the moment. Please check it out and let me know what you think, either in the comments here or by sending me an email at jduff@todoly.net.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 34 2010</title>
        
        <link href="http://jduff.github.com/2010/09/17/learnings-for-week-34-2010/"/>
        <updated>2010-09-17T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/09/17/learnings-for-week-34-2010</id>
        <content type="html">* In the latest version of X11 (on Snow Leopard at least) there is an option in the preferences to allow clicks to go through windows. This makes applications like Gimp actually usable in OS X since you don&#39;t have to click twice anymore (once to activate the window and another time to click the actual tool or menu you wanted)

* The Asterisk background command can take multiple files to play, each joined by &#39;&amp;&#39;

* Adhearsions get_digits, :play[&quot;file1&quot;, &quot;file2&quot;...] plays the files in order and is interruptible by pressing a key, much like the Asterisk background command.

* If naming a class/module/file with the same name as something in the Ruby Standard Library they should be scoped by a unique name to prevent clashes.

* Rails adds &#39;collection_ids&#39; method to models that have a belongs_to association. This gets you all the ids of the associated objects in an array. ex:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;user_ids&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

 * If you&#39;re having trouble with the Glassfish Admin not loading it could be it&#39;s trying to check for updates over the network. We found some good instructions on &lt;a href=&#39;http://http://techmythoughts.blogspot.com/2010/08/glassfish-v3-admin-console-taking-too.html&#39;&gt;how to disable this&lt;/a&gt; by editing the glassfish domain.xml and removing some jars. Note that in our setup the xml file was at &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;%GLASSFISH_HOME/glassfish/domains/domain1/config/domain.xml&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

# Update the &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;%GLASSFISH_HOME/glassfish/domains/domain1/domain.xml&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;java-config&amp;gt;&lt;/span&gt; 
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;jvm-options&amp;gt;&lt;/span&gt;-Dcom.sun.enterprise.tools.admingui.NO_NETWORK=true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/jvm-options&amp;gt;&lt;/span&gt;   
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/java-config&amp;gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
# Remove update tool jar (Backup and remove this JAR)
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;%GLASSFISH_HOME/glassfish/modules/console-updatecenter-plugin.jar&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
# Delete this dir:
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;%GLASSFISH_HOME/glassfish/domains/domain1/osgi-cache%GLASSFISH_HOME/glassfish/domains/domain1/generated&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* To follow redirects with curl add the -L option&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;curl &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; http://example.com&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* We watch a new &lt;a href=&#39;http://vimeo.com/14435288&#39;&gt;webcast on JRuby&lt;/a&gt; that highlights a few interesting features, most notable being that the next version of JRuby and warbler will allow you to build a executable jar file with a embedded web server. This is also interesting because you can have it only package class files so you don&#39;t need to distribute your source with the application.

* Also from the JRuby webcast some interesting tools:

# &lt;a href=&#39;https://visualvm.dev.java.net/&#39;&gt;VisualVM&lt;/a&gt; for profiling your java or jruby applications.
# &lt;a href=&#39;http://cupi2.uniandes.edu.co/web/javadoc/j2se/1.5.0/docs/tooldocs/share/jps.html&#39;&gt;jps&lt;/a&gt; to show java process status.
# &lt;a href=&#39;http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/tooldocs/share/jstack.html&#39;&gt;jstack&lt;/a&gt; to print the stack of a running java process.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 33 2010</title>
        
        <link href="http://jduff.github.com/2010/09/11/learnings-for-week-33-2010/"/>
        <updated>2010-09-11T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/09/11/learnings-for-week-33-2010</id>
        <content type="html">* If you want to test that that an exception is raised and then test the message that is easily accomplished with assert_raise:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assert_raise&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ArgumentError&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#something&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert_match&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/something/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;message&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* If you&#39;re working on an older Rails project (pre Rails 2.1)  you will be missing config.gem for Gem dependency management. If you have multiple versions of gems on the machine you can still load a specific version by using rubygems:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;rubygems&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;RedCloth&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;~&amp;gt;3.0&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* Rails doesn&#39;t check authenticity tokens on GET requests and doesn&#39;t ever check them in the functional tests. More info on Rails authenticity token &lt;a href=&quot;http://stackoverflow.com/questions/941594/understand-rails-authenticity-token&quot;&gt;here&lt;/a&gt;.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Kernel Panic, TimeMachine to the Rescue!</title>
        
        <link href="http://jduff.github.com/2010/09/02/kernel-panic-timemachine-to-the-rescue/"/>
        <updated>2010-09-02T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/09/02/kernel-panic-timemachine-to-the-rescue</id>
        <content type="html">A couple weeks ago I sat down at my computer after dinner to do a little bit of work and was greeted with a very, very sluggish machine. This isn&#39;t normal with my Macbook so I tried shutting down a few applications and pull up Activity Monitor to see what was chewing up the cycles. This seemed to be too much for the machine and it completely locked up, what next? Well, the only thing I could do, hold down the power button until it shut off and try turning it back on (&quot;did you try turning it off and on again?&quot;:http://en.wikiquote.org/wiki/The_IT_Crowd#Yesterday.27s_Jam_.5B1.1.5D).

At this point I wasn&#39;t too worried, and sat waiting for OS X to load. Waiting. And Waiting. And Waiting. It just sat there spinning away. This is quite the dilemma. I hopped onto my iPhone and Goggled to see if there was a way to start up to a command prompt. I found &quot;this link&quot;:http://support.apple.com/kb/ts1417 which had a bunch of information, including holding command-s to boot to single user mode.

Off and On again, this time booting to single user mode and the command prompt. The same link mentioned running &#39;/sbin/fsck&#39; (file system check) to fix any problems with the file system. I ran it. A billion errors, half a billion couldn&#39;t be fixed. Great... Well, it says you may need to run it multiple times to fix everything, so I run it again. And again. And again. Shit.

Maybe I should try reseting the PRAM like &quot;this link says&quot;:http://support.apple.com/kb/ht1379. Off and On again. Kernel Panic. Off and On. Kernel Panic. Shit. (Kernel Panic is the OS X equivalent to a Windows Blue Screen. They are rare so it is likely you have never seen one, but you can check it out &quot;here&quot;:http://support.apple.com/kb/HT1392?viewlocale=en_US)

Well, now I&#39;m screwed. At least I have Apple Care, into the Mac shop it goes.

&quot;Did you try turning it Off and On again?&quot;, she asks.
&quot;Yep. I tried running the file system check, I tried reseting the PRAM and I turned it Off and On a dozen times,&quot; I told her.
&quot;Well, I&#39;ll just try reseting the PRAM,&quot; she said. &quot;Oh, ya, Kernel Panic. That&#39;s not good. We&#39;ll take a look and let you know what we can do.&quot;

Later that day, the Mac Store calls. &quot;You need a new hard drive, we&#39;ll be sending your old one to Apple and probably get a new one in 3-5 business days.&quot;
&quot;You don&#39;t have them in stock?&quot; I asked.
&quot;No, we don&#39;t stock the brand Apple uses and to keep it covered by the warranty we have to use one of theirs,&quot; the girl from The Mac Store says.

Four days later and I&#39;m bringing my Macbook home with it&#39;s fresh new hard drive. I pop in my Snow Leopard disk and watch some TV while OS X reinstalls. Once it finishes I&#39;m asked if I want to import user settings or restore from a Time Machine backup. Hell Yes, I&#39;ll restore from the Time Machine backups I started doing ONE WEEK EARLIER! A couple hours later and I could barely remember that my hard drive had failed and I had a new one in my machine. All my Applications were restored. All my settings. Heck, even my desktop wallpaper came back.

The only thing that I had to reinstall was parallels, and that&#39;s because I ignored the folder where the Windows VM was saved (it seems like it wouldn&#39;t have worked from a restore anyways). The moral of the story is spend $60 on a 500 gig hard drive and USE Time Machine. I&#39;ve ignored a number of places on my machine to keep the backup a little smaller and taking less time, you can do the same (with my setup it is PROVEN that you can still restore and get everything back):

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;~/.Trash
/.Trashes
/Library/Audio
~/Library/Caches
/Library/Caches
~/Downloads
~/Movies
~/Documents/Parallels
~/Music/iTunes/iTunes Music/Podcasts&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Currently I have 20 days of backups and 300 gigs remaining on the drive. Do it.

I have to note that my little dialog with the girl at the Mac shop was a little contrived. They were actually really helpful and did a great job bringing my Macbook (and me) back to life. 
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 31 2010</title>
        
        <link href="http://jduff.github.com/2010/08/24/learnings-for-week-31-2010/"/>
        <updated>2010-08-24T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/08/24/learnings-for-week-31-2010</id>
        <content type="html">Here&#39;s my learnings from a couple weeks ago.

* &quot;jQAPI&quot;:http://www.jqapi.com/ - alternate location for JQuery documentation. Also provides offline versions you can download as &quot;HMTL&quot;:http://www.jqapi.com/jqapi-latest.zip or an &quot;Adobe Air application&quot;:http://github.com/downloads/erikzaadi/jqapi/jQAPI-1.4.2.air?v=11072010.

* &quot;Homebrew&quot;:http://mxcl.github.com/homebrew/ is a package manager for OS X. Packages are defined by formulas that are simple Ruby scripts which is stored in Git underneath.

* Older browsers &quot;do not have a native JSON parser&quot;:http://stackoverflow.com/questions/1364842/json-is-not-defined-chrome but this can be patched with &lt;a href=&quot;http://www.JSON.org/js.html&quot;&gt; a little bit of javascript from json.org&lt;/a&gt;. We ran into this when working with &lt;a href=&quot;http://javascript.neyric.com/wireit/&quot;&gt;WireIt&lt;/a&gt; which does include the &lt;a href=&quot;http://developer.yahoo.com/yui/json/&quot;&gt;Yahoo JSON parser&lt;/a&gt;, but doesn&#39;t actually use it everywhere. Adding in the version from json.org works as a stopgap before digging through all of WireIt.

* Ran into an issue calling to_json on a an object that has a carrierwave attachment and have &lt;a href=&quot;http://github.com/jnicklas/carrierwave/issues/closed#issue/41&quot;&gt;commented on an issue for it&lt;/a&gt;. I am running Rails3 RC2 and using FileSystem storage. To get around this I&#39;m simply excluding the file attachment from the to_json:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;recipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:except&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:photo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 30 2010</title>
        
        <link href="http://jduff.github.com/2010/08/17/learnings-for-week-30-2010/"/>
        <updated>2010-08-17T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/08/17/learnings-for-week-30-2010</id>
        <content type="html">Well, I&#39;ve been slacking again, here&#39;s the learnings from a couple weeks ago.

* IE must &quot;haveLayout for opacity&quot;:http://joseph.randomnetworks.com/archives/2006/08/16/css-opacity-in-internet-explorer-ie/ (alpha filter) to work. You can use the IE zoom rule to give an element layout if needed:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;zoom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* To add custom Date/Time formats in Rails:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DATE_FORMATS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%A, %B %d, %Y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DATE_FORMATS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:article&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%A, %B %d, %Y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
Don&#39;t forget to add your custom formats to Date as well, they use a different hash. This can then be used like so:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;today&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:article&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* When using Paypal buttons you can change the Currency that is used by &quot;adding a hidden field&quot;:https://www.paypal.com/us/cgi-bin/webscr?cmd=p/sell/mc/mc_wa-outside:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hidden&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;currency_code&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CAD&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* The Rails Request object has a number of useful methods for &quot;finding the url that was used for the request&quot;:http://programming-tut.blogspot.com/2010/06/ruby-on-rails-request-url.html:&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;host_with_port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;path&lt;/span&gt;           &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/controller/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;            &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:/&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 29 2010</title>
        
        <link href="http://jduff.github.com/2010/08/01/learnings-for-week-29-2010/"/>
        <updated>2010-08-01T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/08/01/learnings-for-week-29-2010</id>
        <content type="html">This past week I had learnings all over the place; javascript, rails, oracle, css and probably more that I&#39;ve already forgotten.

* Interesting post by Remy Sharp on &quot;Throttling Javascript Function Calls&quot;:http://remysharp.com/2010/07/21/throttling-function-calls/ &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;throttle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;timer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;clearTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;timer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;timer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
Usage: &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;input.username&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keypress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;throttle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// do the Ajax request&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;250&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
This will require there to be 250ms between a keypress before it will execute the given function. Useful for things like Autocomplete where you don&#39;t want an AJAX request to fire until the person stops typing.

* To access the Host machine from a VirtualBox Windows VM &#39;\\vboxsvr\share&#39; . You can also turn on Windows filesharing and access the VM from the Host.

* When Rails (as of 2.3.5) runs the &#39;environment&#39; Rake task it sets the global variable $rails_rake_task = true. Since most tasks depend on the environment you can use this to do slightly different behavior if your code is running within a Rake task.

* Oracle DB &quot;treats blank strings in VARCHAR/VARCHAR2 columns as NULL&quot;:http://stackoverflow.com/questions/203493/why-does-oracle-9i-treat-an-empty-string-as-null

* IE has a property &#39;hasLayout&#39; that determines &quot;how to draw and bound elements&quot;:http://www.satzansatz.de/cssd/onhavinglayout.html. Some elements &quot;have layout by default&quot;:http://www.satzansatz.de/cssd/onhavinglayout.html#wherefrom and others do not. Sometimes when an element does not have layout you can see odd behavior, like lists being numbered incorrectly or margins collapsing. To fix this you can &quot;add certain css properties&quot;:http://www.satzansatz.de/cssd/onhavinglayout.html#prop to elements so that they will gain layout. &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
Height is a property that will have an element gain layout but sometimes you might still want the element to auto expand. Setting the height to 1% will give the element layout as well as allowing it to expand with its content. This is known as the Holly Hack. **Note: hasLayout may not be an issue anymore as of IE8.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 28 2010</title>
        
        <link href="http://jduff.github.com/2010/07/29/learnings-for-week-28-2010/"/>
        <updated>2010-07-29T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/07/29/learnings-for-week-28-2010</id>
        <content type="html">* To get ActionMailer to work with GMail I needed to add the :enable_starttls_auto: true option &quot;to the mailer configuration&quot;:http://www.justinball.com/2009/06/25/sending-email-with-ruby-on-rails-2-3-2-and-gmail/

* You can &quot;add global gem options to ~/.gemrc&quot;:http://stackoverflow.com/questions/1381725/how-to-make-no-ri-no-rdoc-default-for-gem-install, which is just a yml file
** ex. gem: --no-ri --no-rdoc

* SQLServer compatibility mode doesn&#39;t make the server behave exactly what is specified, rather, it pulls in any functionality that may have been deprecated in the later releases (I think)

* &quot;SendGrid&quot;:http://sendgrid.com/, &quot;Google Apps&quot;:https://www.google.com/a/, &quot;AuthSMTP&quot;:http://www.authsmtp.com/ are paid services that can be used for sending email so you don&#39;t need to do it through your own server (or if you&#39;re on EC2 and can&#39;t reliably send mail from your server)
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 27 2010</title>
        
        <link href="http://jduff.github.com/2010/07/25/learnings-for-week-27-2010/"/>
        <updated>2010-07-25T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/07/25/learnings-for-week-27-2010</id>
        <content type="html">Late again, I know, but here&#39;s my learnings from a couple weeks ago.

* If you need to use the Rails url helpers within a model or even script/console you just need these two lines: &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActionController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;UrlWriter&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;default_url_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DEFAULT_HOST&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* Alternatively within script/console you can use the &quot;&#39;app&#39; or &#39;helper&#39; variables to interact with the application&quot;:http://stackoverflow.com/questions/151030/how-do-i-call-controller-view-methods-from-the-console-in-rails &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;number_to_currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;2342.33&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* If you want some piece of code to run after each request  you can use a &quot;&#39;config.to_prepare&#39; block&quot;:http://toolmantim.com/thoughts/environments_and_the_rails_initialisation_process. This might be useful if you have classes reloading in development and want to set settings after they have reloaded.

* Git can sometimes consider text files to be binary if they have Null characters at the end. You can still diff these files with this command: &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git diff &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

* Super cool OS X soft phone &quot;Telephone&quot;:http://www.pure-mac.com/downloads/telephonedl.html

* Facebook applications must be created on a Personal Account, they can not be created with a Business Account.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 26 2010</title>
        
        <link href="http://jduff.github.com/2010/07/13/learnings-for-week-26-2010/"/>
        <updated>2010-07-13T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/07/13/learnings-for-week-26-2010</id>
        <content type="html">* Git interactive rebase can reorder commits (just reorder them in the file)
* &quot;No such device eth0&quot; after cloning VMWare Image
** run &#39;sudo mv /etc/udev/rules.d/70-persistent-net.rules /etc/udev/rules.d/70-persistent-net.rules.old&#39; and then restart the machine to fix the problem. Found &quot;here&quot;:http://muffinresearch.co.uk/archives/2008/07/13/vmware-siocsifaddr-no-such-device-eth0-after-cloning/.
* &quot;Any word completion with vim&quot;:http://vim.wikia.com/wiki/Any_word_completion
** type some characters then ctrl-N or ctrl-P (next or previous match)
* &quot;EngineYard App Cloud&quot;:http://www.engineyard.com/products/appcloud makes a lot of mundane server admin tasks very simple and still allowing complete customization with chef scripts or with root access on the server.
* Many EC2 IPs are on Spam blacklists. Use a thirdparty such as gmail to do the emailing for you.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 25 2010</title>
        
        <link href="http://jduff.github.com/2010/07/07/learnings-for-week-25-2010/"/>
        <updated>2010-07-07T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/07/07/learnings-for-week-25-2010</id>
        <content type="html">* Checking if a javascript function exists in the page:
** typeof functionName == &#39;function&#39;
* &quot;Tig&quot;:http://gitready.com/advanced/2009/07/31/tig-the-ncurses-front-end-to-git.html?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed:+git-ready+(git+ready:+daily+git+tips) a simple command-line yet visual interface to Git
* Filename completion in Vim with ctrl-x then ctrl-f
* Had issues with parts of the page not redrawing correctly, the culprit was a position: relative - not really sure why.
* jQuery delegate method is the &#39;new&#39; way to do live events, cleaner syntax and promotes using a context so the events don&#39;t have to bubble all the way up the DOM. &quot;Learning JQuery&quot;:http://www.learningjquery.com/2010/03/using-delegate-and-undelegate-in-jquery-1-4-2 has a pretty good explanation.

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 24 2010</title>
        
        <link href="http://jduff.github.com/2010/07/04/learnings-for-week-24-2010/"/>
        <updated>2010-07-04T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/07/04/learnings-for-week-24-2010</id>
        <content type="html">* Latest Rails 3 beta doesn&#39;t work in ruby 1.9.1, as stated in &quot;the release notes&quot;:http://guides.rails.info/3_0_release_notes.html#rails-3-requires-at-least-ruby-187
* Mongrel doesn&#39;t build in Ruby 1.9.2.preview3 on Snow Leopard (for me at least)
* Factory Girl factories don&#39;t autoload in Rails 3 anymore, do it yourself or use &quot;factory_girl_rails gem&quot;:http://github.com/thoughtbot/factory_girl_rails
* Colored grep: grep --color=auto
* Vim visual block I ctrl-r-+ to insert copied text
* IRB.conf[:SAVE_HISTORY] = 100
* :set spell in Vim to &quot;turn on spell checking&quot;:http://tips.webdesign10.com/vim/how-use-vims-spellchecker
* &quot;Ruby do...while loop&quot;:http://stackoverflow.com/questions/136793/is-there-a-do-while-loop-in-ruby begin; code; end while(true)

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 23 2010</title>
        
        <link href="http://jduff.github.com/2010/06/23/learnings-for-week-23-2010/"/>
        <updated>2010-06-23T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/06/23/learnings-for-week-23-2010</id>
        <content type="html">* Recently needed to ignore some files that were already being tracked by git. &quot;This Link&quot;:http://pivotallabs.com/users/rolson/blog/articles/1278-ignoring-tracked-files-in-git helped me out.
** git update-index --assume-unchanged config/database.yml
* HTML5 &#39;type=search&#39; renders a nice search box and degrades to a simple input in older browsers.
* HTML5 &#39;placeholder=text&#39; renders placeholder text into an input that goes away when you click into it.
* case; when &#39;one&#39;, &#39;two&#39;; to match &#39;one&#39; or &#39;two&#39; in a Ruby case statement.
* Rails hide_action :action_name in a controller will prevent the action from being routed to.
* jQuery &quot;input&quot; event gets fired when typing, pasting, cutting etc. from an input field.
* jQuery live != livequery plugin. Main difference is live can only bind an event handler to the matching elements, livequery can run a function every time another element matches.
* &quot;http://www.quickdiff.com&quot;:http://www.quickdiff.com super easy online tool to diff text.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 22 2010</title>
        
        <link href="http://jduff.github.com/2010/06/15/learnings-for-week-22-2010/"/>
        <updated>2010-06-15T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/06/15/learnings-for-week-22-2010</id>
        <content type="html">* grep -rl &#39;structure_dump&#39; . to recursivly search through a folder for the given string. mvim `grep..` to open them up.
* alias ls=&#39;ls -GF&#39; so that ls is colored in all consoles.
* &quot;nvarchar in SQLServer&quot;:http://msdn.microsoft.com/en-us/library/ms186939.aspx takes a limit from 0 to 4000 OR the keyword MAX. MAX != 4000, it is actually much larger.
* When using Rails and the JDBC adapter queries SQLServer for nvarchar columns it gets the value back for limit, which when created with MAX is much larger than a limit you can use. This comes up when trying to create the database from schema.rb (testing).
* &quot;Phocus&quot;:http://github.com/mynyml/phocus gem to temporarily focus some tests, ignoring all others, even across test classes.
* &quot;Harmony&quot;:http://github.com/mynyml/harmony provides a simple DSL to execute javascript + DOM code within ruby.
* &quot;Holy Grail&quot;:http://github.com/mynyml/holygrail execute browser-less, console-based, javascript + DOM code right from within your Rails test suite.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 21 2010</title>
        
        <link href="http://jduff.github.com/2010/06/05/learnings-for-week-21-2010/"/>
        <updated>2010-06-05T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/06/05/learnings-for-week-21-2010</id>
        <content type="html">* A couple of interesting resources for getting rid of alias_method_chain in your code &quot;here&quot;:http://gist.github.com/413965 and &quot;here&quot;:http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/
** The basic idea in both of these is to create a module that defines the method you want to chain and call super in your redefinition. When you include the module into your class the modules method is insterted right above the instance&#39;s class in the inheritance tree.
* jQuery &quot;nextAll&quot;:http://api.jquery.com/nextAll/ and &quot;prevAll&quot;:http://api.jquery.com/prevAll/ functions to get all following/previous siblings of each element in the set of matched elements
** &quot;next&quot;:http://api.jquery.com/next/, &quot;nextUntil&quot;:http://api.jquery.com/nextUntil/, &quot;prev&quot;:http://api.jquery.com/prev/ and &quot;prevUntil&quot;:http://api.jquery.com/prevUntil/ are in the same family
* cmd-shift-t reopens last closed tab in the web browser (chrome, firefox, safari).
* A selected like &#39;input + label&#39; matches all the labels that are directly beside an input. There is no way, with the same markup, to target the inputs directly beside a label (&#39;input - label&#39; someday, maybe?)
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>DSLs FTW!</title>
        
        <link href="http://jduff.github.com/2010/05/30/dsls-ftw/"/>
        <updated>2010-05-30T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/05/30/dsls-ftw</id>
        <content type="html">I love programming in Ruby. It&#39;s amazing how powerful and expressive the language can be. One of the best parts about Ruby is how easy it is to whip up a DSL (Domain Specific Language) to help clean up you code and hopefully make it more enjoyable (readable, understandable) to work with. I recently had the chance to cleanup some messy, hard to understand code with a really simple and easy to understand DSL and I thought it might be useful to share the basics doing something like this.

h3. What We&#39;re Working With

For this example lets say you&#39;re writing some code that builds an html page. Lets say you have a class for each html element and a page is made up of a heiarchy of these html elements. The code to build a simple page might look something like this:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTMLPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FormElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;new-user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/user/new&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wrapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DivElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;wrapper&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;LabelElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;InputElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;InputElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Save&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Okay, so you might not actually do something like this in reality but if you did and you were defining a bunch of pages and wanted to adjust each of them it would probably get confusing really fast. Even this simple example is a little hard to read as is...the Input is in the Form? Oh ya, it&#39;s in the wrapper Div which is inside the Form. Confusing!

h3. What will the DSL Look Like?

When I&#39;m looking at some ugly code that I want to clean up I like to step back a little and write some code the way I want it to look and then work on making my DSL or whatever work towards that goal.

I would much rather be writing the stuff about in a way that looks something like this:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/user/new&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;new-user&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;wrapper&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Name&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Save&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

To me something like that is a lot easier to follow, especially with something hierarchical like html or xml.

So that&#39;s all well and good, but this looks pretty different than the code we had earlier, it might be a lot of work to build something to do this. Is it really work all that effort just so our code looks a little better? In all honesty it depends on the situation. If you have code like this on one little spot it might not be worth the effort. But writting a lot of unclear code all over the place then replacing it with a readable DSL will gain you many High Fives from future developers. Besides, it really isn&#39;t that much work and DSLs are too cool to pass up, so lets get to it.

h3. Building the DSL

Lets start out with something simple that will just define and return a couple of our elements.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLPageDSL&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTMLPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FormElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DivElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;InputElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;LabelElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This little bit of code gives us the main structure of our DSL. It doesn&#39;t quit work yet since there&#39;s no way to set the parent attribute on each of the elements. Lets take care of that.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLPageDSL&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTMLPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FormElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DivElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;InputElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;LabelElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Okay, wo what I&#39;m doing here is just keeping track of whatever the current container element is and setting it to @current so that the elements being defined within the block can set it&#39;s parent attribute. Lets take a look at what using our DSL might look like so far:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/user/new&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;new-user&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;wrapper&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Name&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Save&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

That looks pretty close now! I have to be honest though, I cheated and made a little change so that this would be possible:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;HTMLPageDSL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTMLPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLPageDSL&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

So I moved the page method outside of our DSL class and made it create an instance of HTMLPageDSL. We then call instance_eval giving the HTMLPageDSL object the block to evaluate.

The last thing I want to do is add a bit of syntax magic so we don&#39;t have to type quite as much. At the moment we&#39;re passing all the attributes as a hash, but in my initial example I could pass some options directly, without a hash.

First we add the following methods to HTMLPageDSL

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLPageDSL&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extract_options!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each_with_index&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sym&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# From Rails ActiveSupport&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extract_options!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

After that we can use it in our DSL methods to let us pass array arguments or a hash to the method call.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLPageDSL&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(type)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;InputElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

And that&#39;s it. Now we can pass the type as the first argument to the call to input and any other options as a hash, or everything as a hash if we want.

h3. Conclusion

So there we have it, a nice simple example of creating a DSL. This example isn&#39;t perfect, that&#39;s for sure, but it does show how to get started and how simple it can be.

Full Example Code:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;HTMLPageDSL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTMLPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;instance_eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLPageDSL&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(action)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FormElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DivElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(type)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;InputElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setup_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(text)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;LabelElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup_options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extract_options!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each_with_index&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_sym&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# From Rails ActiveSupport&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;extract_options!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# These classes added for completness so the example will run&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLPage&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:children&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@children&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HTMLElement&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;children&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FormElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTMLElement&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:children&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@children&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DivElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTMLElement&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:children&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@children&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InputElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTMLElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LabelElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;HTMLElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Example Usage&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/user/new&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;new-user&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;wrapper&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Name&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Save&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 20 2010</title>
        
        <link href="http://jduff.github.com/2010/05/26/learnings-for-week-20-2010/"/>
        <updated>2010-05-26T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/05/26/learnings-for-week-20-2010</id>
        <content type="html">* If, for whatever reason, your Win XP install doesn&#39;t show Remote Desktop in the start menu running &#39;mstsc&#39; will start it up.
* Until &quot;recently&quot;:http://github.com/jnunemaker/httparty/commit/179ef878808686b7f286174404023b1e1616f5f9 you couldn&#39;t access the raw response from HTTParty. This can be confusing but most of the data can be found using proxied methods on the HTTParty::Response (code, headers, body, message).
* Two very cool gems for simplifying html forms in rails: &quot;simple_form&quot;:http://github.com/plataformatec/simple_form and &quot;formtastic&quot;:http://github.com/justinfrench/formtastic. I&#39;m using simple_form in a project right now and loving it.
* &quot;rr&quot;:http://github.com/btakita/rr seems to have a problem with mocked class methods sticking around between test calls. &quot;Issue opened&quot;:http://github.com/btakita/rr/issues#issue/35.
* Rails 3 respond_with helps clean up controllers by packaging up the standard respond_to cases for html, json, xml etc into one method. It&#39;s also very extendable (&quot;responders gem&quot;:http://github.com/plataformatec/responders has some nice ones).
* Getting &quot;devise&quot;:http://github.com/plataformatec/devise to authenticate by email or login is less trickier than it seems. &quot;Matt Tanase&quot;:http://www.howradical.com/getting-devise-to-accept-a-username-or-email has a nice little post on how to do it. The key is remembering to change your initializer to have &#39;config.authorization_keys :login&#39; in it.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 19 2010</title>
        
        <link href="http://jduff.github.com/2010/05/20/learnings-for-week-19-2010/"/>
        <updated>2010-05-20T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/05/20/learnings-for-week-19-2010</id>
        <content type="html">* &quot;csshx&quot;:http://code.google.com/p/csshx/ - a tool to allow simultaneous control of multiple SSH sessions
* sql server management studio (not express) can be used to generate scripts for a sql server database to recreate tables and data
* The pattern of using modules to provide interface implementations used by the &quot;paperclip gem&quot;:http://github.com/thoughtbot/paperclip is extreamly powerful

</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Making the Switch to VIM</title>
        
        <link href="http://jduff.github.com/2010/05/13/making-the-switch-to-vim/"/>
        <updated>2010-05-13T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/05/13/making-the-switch-to-vim</id>
        <content type="html">Well, after a couple years of using Textmate (and liking it for the most part) I&#39;ve decided to change editors and have happily been using VIM for the last couple weeks. Why VIM? Nothing in particular stands out really. One of my co-workers is a big fan of it, I have to use it once and awhile when on the servers and emacs seemed to be a big pain in the ass :).

Here&#39;s a few of the plugins I&#39;ve installed that helped make me feel more at home in VIM:

&quot;NERDTree&quot;:http://www.vim.org/scripts/script.php?script_id=1658
This plugin gives you a project tree that you can use to navigate your project tree. I also mapped the ` key to toggle the tree making it super easy to open and close.

&quot;fuzzy finder&quot;:http://www.vim.org/scripts/script.php?script_id=1984 and &quot;fuzzy finder textmate&quot;:http://github.com/jamis/fuzzyfinder_textmate
These two plugins give the same functionality as cmd-t in Textmate, letting you quickly open files in the project. I mapped this to ,+t and ,+r to refresh the list.

&quot;rails vim&quot;:http://www.vim.org/scripts/script.php?script_id=1567
This gives a while pile of shortcuts and helpers for working with rails.

&quot;snipMate&quot;:http://www.vim.org/scripts/script.php?script_id=2540
Just like it sounds, this plugin gives you snippets much like Textmate has. Put that together with &quot;the snippets&quot;:http://github.com/scrooloose/snipmate-snippets from scrooloose (Martin Grenfell) and we have access to lots of cool shortcuts.

These are the main plugins I added. I also included a shortcut to use ACK for search and a number of other little scripts and shortcuts to make myself more productive. I&#39;ve got the whole set of &quot;config files&quot;:http://github.com/jduff/vimfiles up on github so you can use it, fork it, change it all you want.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 18 2010</title>
        
        <link href="http://jduff.github.com/2010/05/12/learnings-for-week-18-2010/"/>
        <updated>2010-05-12T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/05/12/learnings-for-week-18-2010</id>
        <content type="html">Learnings for the past week.

* more vim fun
** zf5j to fold the next 5 lines
** zo to open a fold
** zc to close a fold
** c in visual block to substitute
** ctrl+_ to complete html tag (with closetag plugin)
** ctrl+w+_ to maximize splits vertically
** ctrl+w+| to maximize splits horizontally
** ctrl+w+= to equalize splits
* after_initialize in a ruby model if you want something to happen when both new or create are called
* instance_eval can be given a block. This is really powerful if you want to whip up a quick DSL to clean up some code (highly recommended).
* Devise authentication plugin dropped support for MongoMapper until it conforms to ActiveModel (MongoMapper is in turn waiting until Rails 3 is final before making this change)



</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 17 2010</title>
        
        <link href="http://jduff.github.com/2010/05/05/learnings-for-week-17-2010/"/>
        <updated>2010-05-05T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/05/05/learnings-for-week-17-2010</id>
        <content type="html">Learnings for the past week.

* vim (I made the switch this week!)
** ctrl+v to enter visual mode (useful for block comments)
** :sp to split a window
** :vsp for vertical split
** :A for alternate file (rails plugin)
** snipmate for awesome snippets (&quot;plugin&quot;:http://www.vim.org/scripts/script.php?script_id=2540, &quot;snippets&quot;:http://github.com/scrooloose/snipmate-snippets)
** * searches for current word
** :%s/search/replace/modifiers
*** if you leave search blank it uses your previous search
*** g modifier for global search, c to confirm each replacement (very useful!)
* autotest doesn&#39;t run in ruby 1.9.1
** It fails for me saying &quot;set a breakpoint in malloc_error_break to debug&quot; and that&#39;s about all
* ruby -e &quot;code to run&quot;
* assert_select(&#39;input&#39;, 0) doesn&#39;t work, need to use (assert_select &#39;input&#39;, :count=&gt;0)
** This is confusing since assert_select(&#39;input&#39;, 5) works just fine

That&#39;s it for this week. If I find some time I&#39;ll post my vim config and talk about that a bit and maybe discuss what I did about autotest not working.
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Learnings for Week 16 2010</title>
        
        <link href="http://jduff.github.com/2010/04/27/learnings-for-week-16-2010/"/>
        <updated>2010-04-27T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/04/27/learnings-for-week-16-2010</id>
        <content type="html">Learnings for the past week. It was a busy one.

* rvm uninstall leaves build files
** rvm remove gets rid of everything
* Firefox on Ubuntu gets thin black borders around images that are resized in html/css
** Adding some transparency to the edges of the images fixes 
* rails i18n translation keys can&#39;t have &#39;.&#39; in them, even if escaped
* -webkit-user-select/-moz-user-select:none; to disable selection on a webpage
* Webkit doesn&#39;t allow keyboard entry to 0 height inputs
* Firefox and Webkit don&#39;t allow keyboard entry to invisible inputs (display:none)
* jQuery fadeOut doesn&#39;t work on some (circle, line) svg elements in Webkit
* jQuery.keypad on multiple inputs should check if the keyboard target is changing before updating the keypad (huge performance gains)
* git cherry lists commits that don&#39;t exist in another branch. Compares the changeset, not commit ids
* gem install -f will install gem even if dependencies can&#39;t be met
* apt-get build-dep ruby1.8 will get you all the ruby build dependencies
* git checkout -t -b BRANCH origin/BRANCH will checkout and track a remote branch
</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>JavaScript: The Most Versatile Programming Language</title>
        
        <link href="http://jduff.github.com/2010/04/10/javascript-the-most-versatile-programming-language/"/>
        <updated>2010-04-10T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/04/10/javascript-the-most-versatile-programming-language</id>
        <content type="html">I&#39;ve been spending quite a bit of time programming JavaScript lately, not only using &quot;jQuery&quot;:http://jquery.com/ and writing simple jQuery plugins but also building some &#39;classes&#39; to organize the larger application code. As I&#39;ve been going I&#39;ve been trying to learn how to really write javascript well, following best practices and using &quot;JavaScript programming patterns&quot;:http://www.klauskomenda.com/code/javascript-programming-patterns/#module as much as possible. I&#39;ve been blown away with how versatile JavaScript really is.

You can see examples of just how powerful the language is by looking at some of the popular JavaScript frameworks that are out there and just how differently they do things.

Take this extremely simple piece of &quot;jQuery&quot;:http://jquery.com/ code:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;#my-div&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;awesome&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Have you ever thought about how this works? The first bit, _$(&#39;#my-div&#39;)_, is selecting your element from the DOM using jQuerys CSS selector engine &quot;Sizzle&quot;:http://github.com/jeresig/sizzle. What you get back is a DOM element that is wrapped by a jQuery object. You can then call any jQuery method or methods added by plugins on this object, such as the _addClass_ method. The method then manipulates the DOM element or whatever the method is supposed to be doing (in this case adding the class &#39;awesome&#39;).

Now lets contrast this with how the same thing would work with &quot;Prototype&quot;:http://www.prototypejs.org/.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;my-div&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addClassName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;awesome&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This code looks very similar to how we did things with &quot;jQuery&quot;:http://jquery.com/ but underneath the behaviour is very different. Again _$(&#39;my-div&#39;)_ is selecting the element from the DOM but with &quot;Prototype&quot;:http://www.prototypejs.org/ you get back the actual DOM element, not an object wrapped by something else. All the &quot;Prototype&quot;:http://www.prototypejs.org/ methods have been added directly onto the objects that they are intended for (Array methods added to the Array object, DOM methods added to DOM objects etc). When you call _addClassName_ it is being called on the DOM element itself and adding the class &#39;awesome&#39;.

I find this to be pretty amazing. The code you write is basically the same but the underlying way the framework goes about implementing the behaviour is so very different. &quot;jQuery&quot;:http://jquery.com/ is all about augmenting the elements and adding the behaviour you when you make the method calls. &quot;Prototype&quot;:http://www.prototypejs.org/ on the other hand has extended the JavaScript language and objects as soon as you load it into the page. Two very different approaches to solving the same problem.

This has just been a little peak into the different approaches you can take to solving problems with JavaScript. I highly recommend trying out a different framework than you normally use and seeing how they do things, it will open your eyes to solutions you might never have thought of before.</content>
        <author>
            <name>John Duff</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Throwing a UINavigationController, UITabBarController and UISearchBar Together</title>
        
        <link href="http://jduff.github.com/2010/03/09/throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together/"/>
        <updated>2010-03-09T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/03/09/throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together</id>
        <content type="html">In my &quot;last blog post&quot;:http://jduff.github.com/2010/03/01/building-a-searchview-with-uisearchbar-and-uitableview/ I did a tutorial on building a SearchView using _UISearchBar_ and _UITableView_. This time around I&#39;m going to talk about mixing together a _UINavigationController_, _UITabBarController_ and _UISearchBar_ together to see what we get. For this post I&#39;m starting out with a brand new project and doing everything from there, but it should be trivial to do this in the same project as last time (that&#39;s actually what I did the first time around). As always, if all you care about is the code &quot;be my guest&quot;:http://jduff.github.com/2010/03/09/throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together/#-2010-03-09-throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together-full-code, but be warned, we&#39;re doing a lot more in Interface Builder this time.

h3. Background

Okay, so what exactly are we going to build this time? We&#39;re going to start with a Tab Bar application which is going to have a _UINavigationController_ as one of its View Controllers. Once we get this all set up we&#39;re going to add a _UISearchBar_ as the _navigationItem_ of the initial view.

When we&#39;re all done we&#39;ll have something like this:


p=. !{max-height:500px}/images/posts/2010-03-09/uisearchbar_simulator.png(Search Bar in Navigation Item)!!{max-height:500px}/images/posts/2010-03-09/add_table_view_controller_simulator_2.png(Details View)! 

So we have the _UISearchBar_ in the _navigationItem_ and when we push another View Controller onto the stack it slides over nicely to give you the back button.

h3. Setting up the Project

As I said earlier I am starting with a Tab Bar application but you should be able to use any starting point for the application you would like. I wont go into the details of creating the initial project but once you&#39;re ready to go and have a _UITabBarController_ in there (the Tab Bar application gives one to you) open up the Main Window Nib and take a look at it.

p=. !{max-height:400px}/images/posts/2010-03-09/initial_ib.png(Initial View from Interface Builder)! 

This is pretty straight forward, we have the _UITabBarController_ and it has a couple of View Controllers that it switches between. If you run the app right now this is what you would see:

p=. !{max-height:500px}/images/posts/2010-03-09/initial_simulator.png(Initial Simulator Rub)! 

Simple. Lets add the _UINavigationController_

h3. Adding the Navigation Controller to the Mix

Okay, lets switch back to Interface Builder and drop the _UINavigationController_ into the Nib *inside of* the _UITabBarController_. Here&#39;s what we&#39;re looking at after that:

p=. !{max-height:400px}/images/posts/2010-03-09/add_nav_controller_ib.png(Add the Navigation Controller)! 

Notice how it&#39;s inside the _UITabBarController_ and another button was added to the Tab Bar? Next we want to add another View for the _UINavigationController_ to display. I just created a new _UITableViewController_ (Xcode File -&gt; New File) from Xcode and added it to the project.

p=. !{max-height:400px}/images/posts/2010-03-09/add_table_view_controller_xcode.png(Add Table View to the Project)! 

With that added we switch back to Interface Builder and change the class for the _UIViewController_ that is inside the _UINavigationController_.

p=. !{max-height:400px}/images/posts/2010-03-09/add_table_view_controller_ib.png(Change the View Controller Class)!

All we had to do is select the current View Controller in the Nib and then in the Identity Inspector select our new Class in the Class drop down.

Now when we run the project we see our Table View show up along with the Navigation Bar.

p=. !{max-height:500px}/images/posts/2010-03-09/add_table_view_controller_simulator.png(Search View Faded with Results)!  

Okay, we&#39;re just about done. Next we&#39;re going to add that Search Bar to the Navigation Bar.

h3. Pushing the Search Bar into the Navigation Bar

Alright, time to actually get in and add some code! Lets get into Xcode and open up that Table View Controller we created and add a few lines to the _viewDidLoad_ method.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;//  TableViewController.m

#import &quot;TableViewController.h&quot;

@implementation TableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
	
	// Creating the UISearchBar and adding it to the 
	// UINavigationController
	UISearchBar *theSearchBar = [[UISearchBar alloc]
	    initWithFrame:CGRectMake(0.0f,0.0f,320.0f,0.0f)];
	[theSearchBar sizeToFit];
	self.navigationItem.titleView = theSearchBar;
	self.navigationItem.titleView.autoresizingMask = 
	    UIViewAutoresizingFlexibleWidth;
	[theSearchBar release];
}

@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

The main thing to take note of here is that we&#39;re adding the Search Bar to the _navigationItem.titleView_ and then setting the _autoresizingMask_ on it to be flexible. This might seem like a bit of a hack, and it very well might be, but it does the job. I also called _sizeToFit_ on my SearchBar so that it would expand to fit the whole bar. Let&#39;s take a look.

p=. !{max-height:500px}/images/posts/2010-03-09/uisearchbar_simulator.png(Search Bar in Navigation Item)!

There we have it! Now when you select an item from the Table View and push another View Controller onto the stack the Search Bar slides out of the way for the back Bar Item. If you take a look at the full code below you&#39;ll see how to do this.

Something to note, if you want to change the color of the Navigation Bar you will also want to set the tint on the Search Bar so it fits in.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;theSearchBar.tintColor = [UIColor colorWithRed:0.0f green:0.0f 
    blue:0.0f alpha:0.5f];&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This will set the tint to be black, very much like the &#39;Black Opaque&#39; style that can be set on may UI elements.

h3. Conclusion

There we go, we have a Tab Bar with a Navigation Bar for one of the items and we&#39;ve pushed a Search Bar into the Navigation Bar. I&#39;ve included the code below along with some of the generated methods for the Table View Controller that I hooked up. If you have any suggestions or feedback please &quot;leave a comment&quot;:http://jduff.github.com/2010/03/09/throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together/#comments!

&lt;a id=&#39;-2010-03-09-throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together-full-code&#39; &gt;&lt;/a&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;//
//  TableViewController.m

#import &quot;TableViewController.h&quot;
#import &quot;FirstViewController.h&quot;


@implementation TableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
	
	// Creating the UISearchBar and adding it to the UINavigationController
	UISearchBar *theSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f,0.0f,320.0f,0.0f)];
	[theSearchBar sizeToFit];
	self.navigationItem.titleView = theSearchBar;
	self.navigationItem.titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
	[theSearchBar release];
}

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn&#39;t have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren&#39;t in use.
}

- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}


#pragma mark Table view methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @&quot;Cell&quot;;
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    
    cell.textLabel.text = @&quot;first cell&quot;;
	
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
	FirstViewController *anotherViewController = [[FirstViewController alloc] initWithNibName:@&quot;SecondView&quot; bundle:nil];
	[self.navigationController pushViewController:anotherViewController animated:YES];
	[anotherViewController release];
}

- (void)dealloc {
    [super dealloc];
}


@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Building a SearchView with UISearchBar and UITableView</title>
        
        <link href="http://jduff.github.com/2010/03/01/building-a-searchview-with-uisearchbar-and-uitableview/"/>
        <updated>2010-03-01T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/03/01/building-a-searchview-with-uisearchbar-and-uitableview</id>
        <content type="html">h3. Background

I&#39;ve been working away on some iPhone programming lately and one of this first things I wanted to add to my app was a view for searching. What I wanted was to have a view that loads with the curser in the _UISearchBar_ ready to go and to only load the results when the user presses the &#39;Search&#39; button. The rest of this blog post will go through putting all this together. At the end you will have a Search View very similar to the one in the &quot;Flixster App&quot;:http://itunes.apple.com/gb/app/movies/id284235722?mt=8&amp;ign-mpt=uo%3D2 and hopefully the knowhow to customize it further. If you would rather skip the step by step and jump right to the code &quot;be my guest&quot;:http://jduff.github.com/2010/03/01/building-a-searchview-with-uisearchbar-and-uitableview/#-2010-03-01-building-a-searchview-with-uisearchbar-and-uitableview-full-code.

h3. Search View Requirements

# On load have the curser in the _UISearchBar_ ready for user input.
# Search is only done once the &#39;Search&#39; button is pressed.
# When entering the query any previous results should not be clickable.

Here&#39;s a look at what we&#39;re going to end up with: 

p=. !{max-width:300px}/images/posts/2010-03-01/second_search.png(Search View Faded with Results)! 

As a side note, if you&#39;re just looking for a simple type-ahead style search (kind of like what is used in the App Store or Contacts App) you might want to take a look at the Search Bar and Search Display Controller that can be added from Interface Builder. I found it super easy to use for the simple case just described, but very difficult to customize for anything else.

h3. Getting Started

I&#39;ll leave it up to you to do the basic setup for your app, I started with a Tab Bar application for mine but you can use whatever you like. I then created a Nib for the Search View and a corresponding SearchViewController.h/m that extends from _UIViewController_ (more on the code for these files later on). With that done we jump into Interface builder to drop our _UISearchBar_ and _UITableView_ into our Nib. It should look something like what I have here:

p=. !{max-width:300px}/images/posts/2010-03-01/ib.png(Search View - Interface Builder)!

Next up we want to add some _IBOutlets_ in our SearchViewController.h so that we can refer to the UI elements we just added from our code. I am going to make these properties as per the &quot;Memory Management Guidelines&quot;:http://developer.apple.com/iphone/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmNibObjects.html from Apple. I&#39;m also going to define a _NSMutableArray_ to hold the data to display in the _UITableView_.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;//
//  SearchViewController.h
//
#import &amp;lt;UIKit/UIKit.h&amp;gt;

@interface SearchViewController : UIViewController{
    NSMutableArray *tableData;
    
    UITableView *theTableView;
    UISearchBar *theSearchBar;
}
@property(retain) NSMutableArray *tableData;

@property (nonatomic, retain) IBOutlet UITableView *theTableView;
@property (nonatomic, retain) IBOutlet UISearchBar *theSearchBar;

@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

If you didn&#39;t get XCode to generate this file for you make sure you include the import for UIKit.h.

Now we will quickly jump back to Interface Builder and hook those IBOutlets up before we forget. You&#39;ll also want to make the _UISearchBar_ and _UITableView_ delegate to the _SearchViewController_ so that we can handle the callbacks there.

With the Nib all set up lets make sure we synthesize those properties in SearchViewController.m and release the variables in our dealloc method.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;//
//  SearchViewController.m
//
#import &quot;SearchViewController.h&quot;

@implementation SearchViewController
@synthesize tableData;

@synthesize theSearchBar;
@synthesize theTableView;

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableData =[[NSMutableArray alloc]init];
}

- (void)viewDidAppear:(BOOL)animated {
    [self.theSearchBar becomeFirstResponder];
    [super viewDidAppear:animated];
}

- (void)dealloc {
    [theTableView release], theTableView = nil;
    [theSearchBar release], theSearchBar = nil;
    [tableData dealloc];
    [super dealloc];
}
@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

I also snuck a little bit of code into _viewDidLoad_ and _ViewDidAppear_; the former just initializing the tableData _NSMutableArray_ and the later making our _UISearchBar_ first responder. Making it the first responder causes the _UISearchBar_ to get focus as soon as the view loads so that the user can start entering their query right away.

That&#39;s a pretty good start, lets make sure it builds and see what we get when we run our app before going on.

p=. !{max-width:300px}/images/posts/2010-03-01/viewLoaded.png(Search View Loaded)!

h3. Implementing the Protocols

We made the _SearchViewController_ the delegate for both the _UISearchBar_ and the _UITableView_ so are going to implement the _UISearchBarDelegate_ and _UITableViewDataSource_ Protocols. First we need to add the Protocols to the SearchViewController.h header file.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;//
//  SearchViewController.h
//
#import &amp;lt;UIKit/UIKit.h&amp;gt;

@interface SearchViewController : UIViewController
 &amp;lt;UISearchBarDelegate, UITableViewDataSource&amp;gt; {
	// Instance variables defined earlier
}
// Properties defined earlier

@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Now we implement the methods in SearchViewController.m. There are a number of callback methods defined by the _UISearchBarDelegate_ Protocol but we&#39;re only interested in three: _searchBarTextDidBeginEditing_, _searchBarCancelButtonClicked_ and _searchBarSearchButtonClicked_.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    [searchBar setShowsCancelButton:YES animated:YES];
    self.theTableView.allowsSelection = NO;
    self.theTableView.scrollEnabled = NO;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This method is called whenever the _UISearchBar_ gets focus. When this happens we want to show the &#39;Cancel&#39; button (animated:YES makes it slide in nicely) and disable the _UITableView_.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    searchBar.text=@&quot;&quot;;
    
    [searchBar setShowsCancelButton:NO animated:YES];
    [searchBar resignFirstResponder];
    self.theTableView.allowsSelection = YES;
    self.theTableView.scrollEnabled = YES;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

When the &#39;Cancel&#39; button is pressed we want to clear the _UISearchBar_ text and hide the button. We also want the _UISearchBar_ to resignFirstResponder status so that the keyboard hides and then enable the _UITableView_.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // You&#39;ll probably want to do this on another thread
    // SomeService is just a dummy class representing some 
    // api that you are using to do the search
    NSArray *results = [SomeService doSearch:searchBar.text];
	
    [searchBar setShowsCancelButton:NO animated:YES];
    [searchBar resignFirstResponder];
    self.theTableView.allowsSelection = YES;
    self.theTableView.scrollEnabled = YES;
	
    [self.tableData removeAllObjects];
    [self.tableData addObjectsFromArray:results];
    [self.theTableView reloadData];
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

The last _UISearchBarDelegate_ Protocol method is the callback for the &#39;Search&#39; button being pressed. This is where we actually perform the search and add the results to the _UITableView_. The rest of this method implementation is the same as when the &#39;Cancel&#39; button is pressed.

Finally we need to implement the _UITableViewDataSource_ Protocol methods. I&#39;m not going to go into a whole lot of detail here since there&#39;s &quot;lots of info&quot;:http://www.iphonesdkarticles.com/2009/01/uitableview-indexed-table-view.html &quot;out there&quot;:http://icodeblog.com/2008/07/26/iphone-programming-tutorial-hello-world/ on &quot;implementing a _UITableView_&quot;:http://adeem.me/blog/2009/05/19/iphone-programming-tutorial-part-1-uitableview-using-nsarray/.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section {
    return [tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *MyIdentifier = @&quot;SearchResult&quot;;
    UITableViewCell *cell = [tableView
     dequeueReusableCellWithIdentifier:MyIdentifier];
	
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] 
         initWithStyle:UITableViewCellStyleDefault 
         reuseIdentifier:MyIdentifier] autorelease];
    }
	
    id *data = [self.tableData objectAtIndex:indexPath.row];
    cell.textLabel.text = data.name;
    return cell;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

We&#39;ve done lots of work now and it&#39;s probably a good idea to make sure everything still builds. You should see something like this when you run the app:

p=. !{max-width:300px}/images/posts/2010-03-01/results.png(Search View with Results)! 

At this point we&#39;ve hit all three marks in the requirements I outlined earlier and we could call it quits. We could, but I think we could do a little bit more to help make the _UITableView_ actually seem like it&#39;s disabled when you go to search.

h3. Fading out the UITableView

If you take another look at the &quot;Flixster App&quot;:http://itunes.apple.com/gb/app/movies/id284235722?mt=8&amp;ign-mpt=uo%3D2 or even the initial screenshot I have in this post you will notice that when you are in &#39;search mode&#39; the background of the screen is faded black. This effect helps to show the user that the _UITableView_ is in fact disabled.

To get this behaviour I add and remove another _UIView_ and adjust the opacity in an Animation so that in fades in smoothly. The first thing we need to do is create an instance variable and property for this _disableViewOverlay_ as I called it and initialize it when the view loads.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;#import &quot;SearchViewController.h&quot;

@implementation SearchViewController
@synthesize disableViewOverlay;
// Additional variable synthesizes

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableData =[[NSMutableArray alloc]init];
    self.disableViewOverlay = [[UIView alloc]
     initWithFrame:CGRectMake(0.0f,44.0f,320.0f,416.0f)];
    self.disableViewOverlay.backgroundColor=[UIColor blackColor];
    self.disableViewOverlay.alpha = 0;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

I&#39;ll leave it to you to figure out what to put in SearchViewController.m. Now that we have this _UIView_ all set up all we have to do is fade it in when the _UISearchBar_ gets focus. This was actually really easy to do, I just needed to add the _disableViewOverlay_ as a subview and then use _beginAnimations/commitAnimations_ for the fading.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    // Existing code
    
    // Fading in the disableViewOverlay
    self.disableViewOverlay.alpha = 0;
    [self.view addSubview:self.disableViewOverlay];
	
    [UIView beginAnimations:@&quot;FadeIn&quot; context:nil];
    [UIView setAnimationDuration:0.5];
    self.disableViewOverlay.alpha = 0.6;
    [UIView commitAnimations];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    // Existing code
    
    // Removing the disableViewOverlay
    [disableViewOverlay removeFromSuperview];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // Existing code
    
    // Removing the disableViewOverlay
    [disableViewOverlay removeFromSuperview];
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

At the end of _searchBarTextDidBeginEditing_ we added the code to fade in the _disableViewOverlay_, then at the end of _searchBarCancelButtonClicked_ and searchBarSearchButtonClicked we remove the _disableViewOverlay_.

If you&#39;ve been following along you might notice a bit of a &quot;code smell&quot;:http://en.wikipedia.org/wiki/Code_smell coming from these last three methods. There&#39;s a lot of code duplication which I don&#39;t really like so I actually re-factored these three methods and created another method that all of them can call. The resulting re-factored code looks like this:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    [self searchBar:searchBar activate:YES];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    searchBar.text=@&quot;&quot;;
    [self searchBar:searchBar activate:NO];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // SomeService is just a dummy class representing some 
    // api that you are using to do the search
    NSArray *results = [SomeService doSearch:searchBar.text];
	
    [self searchBar:searchBar activate:NO];
	
    [self.tableData removeAllObjects];
    [self.tableData addObjectsFromArray:results];
    [self.theTableView reloadData];
}

- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active{	
    self.theTableView.allowsSelection = !active;
    self.theTableView.scrollEnabled = !active;
    if (!active) {
        [disableViewOverlay removeFromSuperview];
        [searchBar resignFirstResponder];
    } else {
        self.disableViewOverlay.alpha = 0;
        [self.view addSubview:self.disableViewOverlay];
		
        [UIView beginAnimations:@&quot;FadeIn&quot; context:nil];
        [UIView setAnimationDuration:0.5];
        self.disableViewOverlay.alpha = 0.6;
        [UIView commitAnimations];
		
        // probably not needed if you have a details view since you 
        // will go there on selection
        NSIndexPath *selected = [self.theTableView 
            indexPathForSelectedRow];
        if (selected) {
            [self.theTableView deselectRowAtIndexPath:selected 
                animated:NO];
        }
    }
    [searchBar setShowsCancelButton:active animated:YES];
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

That cleans things up nicely. Now when you run the app you should have the main view fade out smoothly when you enter the _UISearchBar_ just like mine below:

p=. !{max-width:300px}/images/posts/2010-03-01/second_search.png(Search View Faded with Results)! 

h3. Conclusion

There we have it, a nice Search View that you have full control over. I&#39;ve included the full code with inline comments below, have at it! If you have any suggestions or feedback please &quot;leave a comment&quot;:http://jduff.github.com/2010/03/01/building-a-searchview-with-uisearchbar-and-uitableview/#comments!

&lt;a id=&#39;-2010-03-01-building-a-searchview-with-uisearchbar-and-uitableview-full-code&#39; &gt;&lt;/a&gt;
SearchViewController.h

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;//
//  SearchViewController.h
//
#import &amp;lt;UIKit/UIKit.h&amp;gt;

@interface SearchViewController : UIViewController
 &amp;lt;UISearchBarDelegate, UITableViewDataSource&amp;gt; {
	NSMutableArray *tableData;
	
	UIView *disableViewOverlay;
	
	UITableView *theTableView;
	UISearchBar *theSearchBar;
}

@property(retain) NSMutableArray *tableData;
@property(retain) UIView *disableViewOverlay;

@property (nonatomic, retain) IBOutlet UITableView *theTableView;
@property (nonatomic, retain) IBOutlet UISearchBar *theSearchBar;

- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active;

@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;


SearchViewController.m


&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;//
//  SearchViewController.m
//
#import &quot;SearchViewController.h&quot;

@implementation SearchViewController
@synthesize tableData;
@synthesize disableViewOverlay;
@synthesize theSearchBar;
@synthesize theTableView;


// Initialize tableData and disabledViewOverlay 
- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableData =[[NSMutableArray alloc]init];
    self.disableViewOverlay = [[UIView alloc]
     initWithFrame:CGRectMake(0.0f,44.0f,320.0f,416.0f)];
    self.disableViewOverlay.backgroundColor=[UIColor blackColor];
    self.disableViewOverlay.alpha = 0;
}

// Since this view is only for searching give the UISearchBar 
// focus right away
- (void)viewDidAppear:(BOOL)animated {
    [self.theSearchBar becomeFirstResponder];
    [super viewDidAppear:animated];
}

#pragma mark -
#pragma mark UISearchBarDelegate Methods

- (void)searchBar:(UISearchBar *)searchBar
    textDidChange:(NSString *)searchText {
  // We don&#39;t want to do anything until the user clicks 
  // the &#39;Search&#39; button.
  // If you wanted to display results as the user types 
  // you would do that here.
}

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    // searchBarTextDidBeginEditing is called whenever 
    // focus is given to the UISearchBar
    // call our activate method so that we can do some 
    // additional things when the UISearchBar shows.
    [self searchBar:searchBar activate:YES];
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    // searchBarTextDidEndEditing is fired whenever the 
    // UISearchBar loses focus
    // We don&#39;t need to do anything here.
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    // Clear the search text
    // Deactivate the UISearchBar
    searchBar.text=@&quot;&quot;;
    [self searchBar:searchBar activate:NO];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // Do the search and show the results in tableview
    // Deactivate the UISearchBar
	
    // You&#39;ll probably want to do this on another thread
    // SomeService is just a dummy class representing some 
    // api that you are using to do the search
    NSArray *results = [SomeService doSearch:searchBar.text];
	
    [self searchBar:searchBar activate:NO];
	
    [self.tableData removeAllObjects];
    [self.tableData addObjectsFromArray:results];
    [self.theTableView reloadData];
}

// We call this when we want to activate/deactivate the UISearchBar
// Depending on active (YES/NO) we disable/enable selection and 
// scrolling on the UITableView
// Show/Hide the UISearchBar Cancel button
// Fade the screen In/Out with the disableViewOverlay and 
// simple Animations
- (void)searchBar:(UISearchBar *)searchBar activate:(BOOL) active{	
    self.theTableView.allowsSelection = !active;
    self.theTableView.scrollEnabled = !active;
    if (!active) {
        [disableViewOverlay removeFromSuperview];
        [searchBar resignFirstResponder];
    } else {
        self.disableViewOverlay.alpha = 0;
        [self.view addSubview:self.disableViewOverlay];
		
        [UIView beginAnimations:@&quot;FadeIn&quot; context:nil];
        [UIView setAnimationDuration:0.5];
        self.disableViewOverlay.alpha = 0.6;
        [UIView commitAnimations];
		
        // probably not needed if you have a details view since you 
        // will go there on selection
        NSIndexPath *selected = [self.theTableView 
            indexPathForSelectedRow];
        if (selected) {
            [self.theTableView deselectRowAtIndexPath:selected 
                animated:NO];
        }
    }
    [searchBar setShowsCancelButton:active animated:YES];
}


#pragma mark -
#pragma mark UITableViewDataSource Methods

- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section {
    return [tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *MyIdentifier = @&quot;SearchResult&quot;;
    UITableViewCell *cell = [tableView
     dequeueReusableCellWithIdentifier:MyIdentifier];
	
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] 
         initWithStyle:UITableViewCellStyleDefault 
         reuseIdentifier:MyIdentifier] autorelease];
    }
	
    id *data = [self.tableData objectAtIndex:indexPath.row];
    cell.textLabel.text = data.name;
    return cell;
}

#pragma mark -
#pragma mark Memory Management Methods

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn&#39;t have a superview.
    [super didReceiveMemoryWarning];	
    // Release any cached data, images, etc that aren&#39;t in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [theTableView release], theTableView = nil;
    [theSearchBar release], theSearchBar = nil;
    [tableData dealloc];
    [disableViewOverlay dealloc];
    [super dealloc];
}

@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>February 23rd OGRE Meetup Recap</title>
        
        <link href="http://jduff.github.com/2010/02/24/february-23-ogre-meetup-recap/"/>
        <updated>2010-02-24T00:00:00+00:00</updated>
        <id>jduff.github.com:/2010/02/24/february-23-ogre-meetup-recap</id>
        <content type="html">I&#39;d like to thank everyone who came out to the latest meeting, we had quite the turnout! A few new faces as well which is always great.

For anyone who doesn&#39;t know &quot;OGRE&quot; stands for &quot;Ottawa Group of Ruby Enthusiasts&quot;. We&#39;re a local group that gets together on the fourth Tuesday of each month to talk about Ruby, programming, cool projects and sometimes even Python. We&#39;re a fairly diverse group from professional Ruby developers, to tinkerers, people just starting out and everything in between. Check out the &quot;website&quot;:http://www.ottawaruby.ca/ and the &quot;google group&quot;:http://groups.google.ca/group/ogre-list for more info.

This past Tuesday we had Don Kelly and Julie Hache giving a couple presentations. To recap:

# Don Kelly talked about TreeTop (&quot;http://treetop.rubyforge.org/&quot;:http://treetop.rubyforge.org/) and LLVM (&quot;http://llvm.org/&quot;:http://llvm.org/) giving us a short example of writing a very simple language with both. He also spent a bit of time showing us the SEXP parser and interpreter (&quot;http://github.com/karfai/sexp&quot;:http://github.com/karfai/sexp) that he was working on with both of those tools. Very cool stuff.


# Julie Hache gave a presentation on some of the stuff that has changed with Rails 3 and what the upgrade process is going to look like. She also walked through how we can get setup and playing with Rails 3 right now with the beta (&quot;http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release/&quot;:http://weblog.rubyonrails.org/2010/2/5/rails-3-0-beta-release/). Julie also mentioned a book that Jeremy McAnally just released with over 100 pages of info on the Rails 3 upgrade process (&quot;http://www.railsupgradehandbook.com/&quot;:http://www.railsupgradehandbook.com/). Jeremy knows his stuff so I&#39;m sure it will be $12 well spent.


At the end of the night Bryan Larsen gave another mention of the recent Hobo release (&quot;http://hobocentral.net/blog/2010/02/23/hobo-1-0-released/&quot;:http://hobocentral.net/blog/2010/02/23/hobo-1-0-released/) so we should all check that out.


Once again, thanks to Julie and Don for doing the presentations and thanks for everyone who came out. We look forward to seeing all of you next month!</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Expanding my Skills</title>
        
        <link href="http://jduff.github.com/2009/11/23/expanding-my-skills/"/>
        <updated>2009-11-23T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/11/23/expanding-my-skills</id>
        <content type="html">In the last couple months I&#39;ve been thinking a bit about expanding the skills I have into some different areas. I&#39;ve been working with Ruby on Rails almost exclusively for over three years and have gotten to know the ins and outs pretty well. I love Ruby and Rails, but I&#39;m getting that itch to play with something new. I&#39;ve been playing around with iPhone development a bit (though I&#39;ve been slacking) and find that to be really interesting, but I decided the other day to try something different to fill this need (I will continue to play with iPhone stuff, it&#39;s just too cool to let go).

Javascript will be my next conquest. Writing Javascript with &quot;jQuery&quot;:http://jquery.com/ to be exact. I&#39;ve had my love for &quot;jQuery&quot;:http://jquery.com/ reignited and it complements the other web development skills I already have. I&#39;d like to think I&#39;m already pretty good with &quot;jQuery&quot;:http://jquery.com/, I&#39;ve been using it for various projects for awhile now, but my goal is to learn it in and out; all the best practices and neat tricks as well as the limitations and how to overcome them.

To do this I&#39;m going to start out by trying my hand at writing a few &quot;jQuery plugins&quot;:http://docs.jquery.com/Plugins/Authoring of my own and try to integrate jQuery into any work I might be doing. To start out I&#39;ve been reading a few blogs and have come across a &quot;really great plugin pattern&quot;:http://www.learningjquery.com/2007/10/a-plugin-development-pattern that I&#39;m going to follow for most of my stuff.

h3. jQuery Plugin Pattern: Giving it jQuery

First thing we want to start with is giving our plugin access to jQuery. This sounds like a no brainer but you have to be careful since the jQuery helper method ($) can be redefined and therefore isn&#39;t guaranteed to exist. To overcome this the pattern below is usually used.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// plugin code here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This might look a little scary, but all we&#39;re doing is defining a function that takes a parameter. We&#39;re then calling the function right away passing in jQuery. Now we can use $ in our plugin without worry!

h3. Playing Nice: Returning jQuery

When using a jQuery plugin there are a couple of things that users come to expect. The two main things is that the plugin should be able to work on an array of objects and at the end it should return the jQuery object to allow chain ability. Accomplishing this is very easy with the code below.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// define the plugin&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// iterate through the matched elements&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// returning this at the end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;// plugin logic here&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

h3. Giving the User Control: Plugin Options and Defaults

The next thing we&#39;re going to want to give our plugins is a way for the user to pass in options to override the defaults. I also like the way the &quot;jQuery UI plugins&quot;:http://jqueryui.com/ give you public access to the defaults so that you can set them once instead of every time the plugin is called. &quot;Learning jQuery&quot;:http://www.learningjquery.com/2007/10/a-plugin-development-pattern has some code to do just that and looks something like what I have below.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// define the plugin&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// extend the default options with those provided&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// extending an empty object prevents overriding of &lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// our defaults object&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// plugin defaults&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;red&#39;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This code lets our plugin users do a couple interesting things. First thing is they can pass options to plugin like below.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;h1&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;black&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

What is more interesting is the fact that instead of having to pass the same options in every time they could set the defaults at the start and be done with it, only passing in options that differ from their own defaults.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;black&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;h1&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// plugin default color is black&lt;/span&gt;
  
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;h1&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;orange&#39;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// override the defaults&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This gives the users a lot of flexibility and helps them to keep their code nice and &quot;DRY&quot;:http://en.wikipedia.org/wiki/Don%27t_repeat_yourself.

h3. Giving the User Control: Exposing Public Functions

Sometimes it makes sense to expose plugin functions to the user so that they can override the implementation with their own. This might not be needed for all plugins, but I think it would be useful for most. 

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// use the helper function&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;something&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
      
      &lt;span class=&quot;c1&quot;&gt;// plugin logic here&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// public helper function that can be overridden by the user&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do something that helps&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This gives the user a lot of control over how the plugin behaves. Again, it doesn&#39;t make sense for all plugins but when sometimes it can be a real life saver. All the user has to do to provide their own implementation to the helper function is to redefine it like below.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do something different&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

The big benefit to this that I see over having a callback is that you could save the original function and use it in your implementation, something like this.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do something different with the results&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This lets you build upon the original implementation if you want to, meaning less repeated code.

h3. Wrapping Up

Well, that pretty much does it for how I want my jQuery plugins to be structured. I&#39;ve left out a bunch of stuff that beginners should probably take a look at, &quot;these&quot;:http://www.learningjquery.com/2007/10/a-plugin-development-pattern &quot;links&quot;:http://docs.jquery.com/Plugins/Authoring should help if you&#39;re interested.

I&#39;ve got the full template below and I&#39;ve also put it up on &quot;Github&quot;:http://github.com/jduff/jquery-plugin-template with a few more comments, feel free to fork it and send me updates.


&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// define the plugin&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// extend the default options with those provided&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// extending an empty object prevents overriding &lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// of our defaults object&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// iterate through the matched elements&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// returning this at the end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// use the helper function&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;something&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
      
      &lt;span class=&quot;c1&quot;&gt;// plugin logic here&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// public helper function that can be overridden by the user&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;helper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do something that helps&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// plugin defaults&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;red&#39;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>mySQL, Rails and OS X Fun</title>
        
        <link href="http://jduff.github.com/2009/10/28/mysql-rails-and-os-x-fun/"/>
        <updated>2009-10-28T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/28/mysql-rails-and-os-x-fun</id>
        <content type="html">In the last little while I started working on a Rails project that had been targeting an older version of mySQL. I ran into a few confusing problems while getting started so I thought I&#39;d bring together all the various mySQL and Rails related info I came across to fix my problems into one place.

h3. Problem: ActiveRecord failing with a default field value of blank

This is a problem that a few people have posted on &quot;ruby-forum&quot;:http://www.ruby-forum.com/topic/197243 without getting much of a response, but what is there pointed me in the right direction. The main problem is that older versions of mySQL (pre 5.0.45 I believe) treat a NULL value inserted into a string column as a blank string. Newer versions of mySQL fix this issue but this fix causes some confusing behaviour.

What happens in the older version is maybe you forget to pass a value for that NOT NULL string; mySQL happily treats that as a blank string and gives you no errors. When you upgrade mySQL to a version that &#39;fixes&#39; this you end up with all kinds of errors because the constraint isn&#39;t being met anymore.

h4. Solution

Well, if you don&#39;t actually need the constraint remove it, otherwise explicitly send a value so the constraint is met. Update your tests and validations so you&#39;re passing and checking that the correct values are being passed.

h3. Problem: Error: uninitialized constant MysqlCompat::MysqlRes

Another one that also shows up on a &quot;ruby forum post&quot;:http://www.ruby-forum.com/topic/192550. The root of this problem is that on OS X the mysql gem has to be told where the installed mySQL libraries are and which architecture your machine is.

h4. Solution

I found the solution &quot;here&quot;:http://wonko.com/post/how-to-install-the-mysqlruby-gem-on-mac-os-x-leopard but had to modify the gem install slightly for my 64 bit machine.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;env &lt;span class=&quot;nv&quot;&gt;ARCHFLAGS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-arch x86_64&quot;&lt;/span&gt; gem install mysql &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--with-mysql-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/mysql &lt;span class=&quot;nt&quot;&gt;--with-mysql-lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/mysql/lib &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--with-mysql-include&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/mysql/include
  &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This might be slightly different depending on where mysql ended up on your machine and your machines architecture.

h3. Problem: mySQL can&#39;t install because a newer version exists

Or, removing mySQL for real. While dealing with my first problem I tried installing and uninstalling different versions of mySQL along the way the mySQL install got angry because some files weren&#39;t removed and wouldn&#39;t install the version I wanted.

h4. Solution

I managed to get mySQL off my machine by combining the approaches from a &quot;blog post&quot;:http://akrabat.com/2008/09/11/uninstalling-mysql-on-mac-os-x-leopard/ and an answer found on &quot;Stack Overflow&quot;:http://stackoverflow.com/questions/1436425/how-do-you-uninstall-mysql-from-mac-os-x/1447758#1447758. Before doing this I did run the mySQL uninstaller, but it seems to leave some goodies behind.

In the end it boiled down to running the following commands:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rm /usr/local/mysql
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /usr/local/mysql&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /Library/StartupItems/MySQLCOM
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /Library/PreferencePanes/My&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
  edit /etc/hostconfig and removed the line &lt;span class=&quot;nv&quot;&gt;MYSQLCOM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-YES-&lt;/span&gt;
  rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; ~/Library/PreferencePanes/My&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /Library/Receipts/mysql&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /Library/Receipts/MySQL&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rm &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /var/db/receipts/com.mysql.&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

I know it&#39;s a lot of mumbo jumbo, but mySQL seems to hook itself in all over the place and this, in the end, did seem to get rid of everything.

h3. Conclusion

Well, that&#39;s all I&#39;ve got for mySQL right now. It was a pretty frustrating trip, but in the end I managed to find a solution to all the problems and now it&#39;s all in one place for all of time.

As a side note I&#39;m really starting to find &quot;Stack Overflow&quot;:http://stackoverflow.com to be an incredibly useful resource. Sometimes it might even save time trying a quick search there before hitting up Google.</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Startup Boot Camp Reflection</title>
        
        <link href="http://jduff.github.com/2009/10/27/startup-boot-camp-reflection/"/>
        <updated>2009-10-27T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/27/startup-boot-camp-reflection</id>
        <content type="html">As I mentioned in an &quot;earlier post&quot;:http://jduff.github.com/2009/10/15/startup-boot-camp/ I attended this local Ottawa event called &quot;Startup Boot Camp&quot;:http://www.theottawanetwork.com/startup-boot-camp/ on the weekend. Well, I&#39;ve got to say, this was one of the most interesting events I&#39;ve ever been to. Let me break down how the weekend went a little bit.

h3. Day 1 (Friday 6pm - 9pm)

The first day started out with an introduction to the event, sponsors, organizers and all that jazz. The didn&#39;t waste any time and moved onto the pitches. There were 8 ideas presented by some really energetic people ranging from major hardware, software or a combination of the two. 

After voting on the pitches the bottom two were dropped and everyone split off around whichever idea they found most interesting. The teams ranged from 6-13 people with backgrounds in software, hardware, marketing, sales, business development etc. 

After getting to know my team a little bit we headed home to rest up a little bit and get ready from the rest of the weekend.

h3. Day 2 (Saturday 9am - 6pm)

Today everyone gathered together in the main room to be introduced to some of the mentors that would be available to help us develop our pitches. We had financial experts, accountants, lawyers, operations experts, human resources consultants, pretty much everything you might need to get a business started. 

After the quick introduction everyone split off into their groups to start working any of the kinks out of their startup with the help of the mentors. I&#39;ve got to say, the experts they brought in were just phenomenal. This event was well worth it just to be able to spend some time with these people and to draw from all the experiences they have had.

By mid afternoon we had most of the details figured out so we decided to individually take a look at the slide deck we needed to put together and jot down some ideas. By the end of the day we had a pretty good idea of what we needed in the deck but still stuck around after 6 to go over things a little bit more and split up some &#39;homework&#39;.

h3. Day 3 (Sunday 9am - 6pm)

Again, we started out with an introduction to a new set of mentors, no messing around now though so we quickly broke off and got down to work. Today was all about putting the slide deck together, making it look good and making sure we had answers to all the questions the panel might ask. Around 1pm we started practicing the presentation and tweaking anything we still could based on the mentors comments.

At 3pm everyones back in the room for the pitches in front of the panel. I found it really interesting how the presentations really seemed to reflect on the team behind them. One team had an industrial designer as the lead so their slide deck was super slick, they even had small prototypes that they handed out to the judges. Other side decks really showed the technical expertise of their group with detailed diagrams and flow charts on how their products would work.

After presenting the judges asked some great questions and before announcing the winner provided some feedback to each group on what they really needed to look at to make their product work. All of this advice was right on the money and, I would imagine, will help these startups move forward in the future.

h3. In Closing

Well, in the end my team didn&#39;t win the final prize but I think everyone involved did get a lot out of the event, I know I did. My teammates were an amazing group of people that I was really glad to have met and spent the weekend working with, the mentors and judges gave a huge amount of advice that would be next to impossible to easily get otherwise and I had all kinds of fun.

Big thanks goes out to &quot;Rick O&#39;Conner&quot;:http://twitter.com/rickoco and the rest of the &quot;Ottawa Network&quot;:http://www.theottawanetwork.com for putting together this event. Word is they&#39;re already looking to do a repeat of the &quot;Startup Boot Camp&quot;:http://www.theottawanetwork.com/startup-boot-camp/ in March so be ready to sign up, I know I will be!


</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Ruby Tidbits: Cutting out the Block with an &amp;proc</title>
        
        <link href="http://jduff.github.com/2009/10/19/ruby-tidbits-cutting-out-the-block-with-an-ampersand/"/>
        <updated>2009-10-19T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/19/ruby-tidbits-cutting-out-the-block-with-an-ampersand</id>
        <content type="html">I find one of the most useful &#39;tricks&#39; in Ruby is to use the &#39;&amp;&#39; character to convert Ruby Proc objects into a block. What exactly does this mean? Well, the best way to explain it is with a couple of examples.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(one two three)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;collect!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;upcase&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ONE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TWO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;THREE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;


This is a pretty simple block of code, all we&#39;re doing is converting an array of words to uppercase. Now say we&#39;re good ruby programmers and want to keep our code readable and concise, how does this stand up? Well, it is a simple block so it is fairly readable, but how about we take a look at the same piece of code using the &#39;&amp;&#39; method to convert a proc into a block.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(one two three)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;collect!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:upcase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ONE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TWO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;THREE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

These two blocks do the exact same thing, but I find the second method to dramatically improve the readability even in this simple example.

So, what&#39;s really going on here? Well Ruby sees the &#39;&amp;&#39; so it wants to convert the Proc to a block. Since we have a Symbol on the other side Ruby type converts it to a proc by calling to_proc on the Symbol which returns a Proc that takes one argument and calls the method named by the symbol on that object. The implementation of to_proc on the Symbol class might look something like this:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

The actual implementation is a little more complicated, allowing multiple arguments etc, but you get the idea.

You can also use this method with a normal Proc object instead of just with a Symbol, making something like this possible:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;collect!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inspect&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Pretty cool isn&#39;t it? I&#39;ve been using the Symbol technique for awhile now to keep my code concise and readable, I never even thought about using a Proc until doing a little bit of research for this article. If you want to know more about all of this check out &quot;Understanding Ruby blocks, Procs and methods&quot;:http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/ by Eli Bendersky, I based some of my examples off of his article.</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Releasing a Gem with Gemcutter</title>
        
        <link href="http://jduff.github.com/2009/10/17/releasing-a-gem-with-gemcutter/"/>
        <updated>2009-10-17T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/17/releasing-a-gem-with-gemcutter</id>
        <content type="html">The other day &quot;Jon Maddox&quot;:http://github.com/maddox sent me a message on Github to see if I was thinking of putting my gem &quot;tmdb_party&quot;:http://github.com/jduff/tmdb_party up on &quot;Gemcutter&quot;:http://gemcutter.org/, the new RubyGem host on the block. At the time I hadn&#39;t really thought much about doing this thought what the heck? It didn&#39;t seem like it was too difficult so I thought I&#39;d put it to the test around midnight on a Saturday night.

Well, I have got to say, this was probably the easiest thing I&#39;ve ever done. I was going into this thinking it wouldn&#39;t be too difficult but I was still impressed with how it went.

# The first step is to sign up for a Gemcutter account &quot;right here&quot;:http://gemcutter.org/session/new which takes about 10 seconds.
# The next step is to update your Jeweler Rakefile to add the Gemcutter task. I&#39;ve included a sample of what my Rakefile looks like below.
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;jeweler&#39;&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Jeweler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;tmdb_party&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Jeweler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GemcutterTasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LoadError&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Jeweler not available. Install it: sudo gem install jeweler&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
# Now all you need to do is push your gem the new task and provide your Gemcutter credentials
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;rake gemcutter:release&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

That&#39;s it, now my tmdb_party gem is &quot;up on Gemcutter&quot;:http://gemcutter.org/gems/tmdb_party. On a side note, if you&#39;re not using &quot;Jeweler&quot;:http://github.com/technicalpickles/jeweler/ to manage and release your gems you really should, it makes releasing a gem incredibly simple.

Now go put your gems up on &quot;Gemcutter&quot;:http://gemcutter.org/!

&lt;i&gt;update:
&quot;Jon&quot;:http://github.com/maddox just reminded me that if you don&#39;t want to add the Jeweler task it&#39;s still just one simple command to release your gem:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gem push pkg/tmdb_party_0.4.0.gem&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Boom! Released! Thanks for the reminder Jon!&lt;/i&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Project Idea: Fake Server</title>
        
        <link href="http://jduff.github.com/2009/10/16/project-idea-fake-server/"/>
        <updated>2009-10-16T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/16/project-idea-fake-server</id>
        <content type="html">While working on the &quot;Presence assignments&quot;:http://jduff.github.com/2009/10/14/presence-3/ for the &quot;Stanford iPhoneU course&quot;:http://www.stanford.edu/class/cs193p/cgi-bin/index.php I noticed that they did something really interesting to make interacting with the &quot;Twitter API&quot;:http://apiwiki.twitter.com/ a little bit easier. They setup a server that responded to actions similar to Twitter with some sample data. This really helped out so that when messing around during development so that Twitter wasn&#39;t annoyed with all the requests.

While working with this dummy server they set up I got thinking that something like this might be useful when developing other API mashups. I don&#39;t think Stanford wants to set something like this up for all the apis out there though, so what about a Gem that does something like this?

What I&#39;m thinking of is a very simple gem that basically runs a &quot;Sinatra&quot;:http://www.sinatrarb.com/ app which mimics a Twitter or Google Maps or some other api. These &#39;mock apis&#39; could be plugins that could easily be pulled into the gem and run locally. I could see running commands like &#39;fakeserver install Twitter git://github.com/jduff/fake-twitter.git&#39; and this would install a git clone so that it can be kept up to date. Then you could run the fake server with &#39;fakeserver Twitter&#39; and then you&#39;d have a local server that mocked Twitters API.

I did a little bit of searching and still haven&#39;t really come across anything that does what I am thinking. There is this project, &quot;mock-server&quot;:http://github.com/djanowski/mock-server that is kind of like &quot;FakeWeb&quot;:http://github.com/chrisk/fakeweb but you define the mocks by writing actions like you do with &quot;Sinatra&quot;:http://www.sinatrarb.com/. This is kind of what I&#39;m thinking of except it doesn&#39;t run a server, but the general idea is pretty much the same.

I&#39;m not sure if there is another project that does what I am thinking of but I might start working on something like this. If anyone has any ideas or suggestions leave a comment and let me know.

</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Startup Boot Camp</title>
        
        <link href="http://jduff.github.com/2009/10/15/startup-boot-camp/"/>
        <updated>2009-10-15T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/15/startup-boot-camp</id>
        <content type="html">A couple weeks ago I heard about an event called &quot;Startup Boot Camp&quot;:http://www.theottawanetwork.com/startup-boot-camp/ that is happening in Ottawa October 23-25th. The idea is to bring together a number of startup minded individuals and form teams around startup ideas. You then take the weekend to work on the idea and at the end the best one gets a prize to be used to incorporate the business. Here is an excerpt from the &quot;blog post announcing the event&quot;:http://www.theottawanetwork.com/startup-boot-camp/.

bq. The event will place 75-100 people into functional business teams around ideas for businesses. The participants, composed of developers, business managers, start-up enthusiasts, marketing gurus, accountants, lawyers, graphic artists and other roles will work together during the week end. At the end of 54 hours, they will have turned a business idea into a business plan ready to start on the Monday. A review panel at the end of Sunday’s presentation’s will determine which of the opportunities is the best developed and award a prize of $5,000 as the first seed money to start the business (e.g. incorporation costs, start a website, etc.). Similar networking events have evolved very successfully in other parts of North America with this one being the first in Ottawa.

I&#39;ve just signed up and anyone else who might be interested should &quot;do the same&quot;:http://tonstartupoct09.eventbrite.com/. Even if you don&#39;t win the prize and &quot;land your dream job&quot;:http://jduff.github.com/2009/10/08/my-ideal-job/ it should be a great opportunity to meet with like minded individuals and have some fun.</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Presence 3</title>
        
        <link href="http://jduff.github.com/2009/10/14/presence-3/"/>
        <updated>2009-10-14T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/14/presence-3</id>
        <content type="html">As I said in an &quot;earlier post&quot;:http://jduff.github.com/2009/09/28/iphoneu/ I&#39;ve been working on learning Objective-C, more specifically, programming for the iPhone. Well, I just finished off my latest Stanford iPhone assignment, Presence 3. As always you can find it up on github, there&#39;s a branch for &quot;assignment 1&quot;:http://github.com/jduff/Presence/tree/v1, &quot;assignment 2&quot;:http://github.com/jduff/Presence/tree/V2 and now &quot;assignment 3&quot;:http://github.com/jduff/Presence/tree/V3.

A couple of very key concepts were introduced for this assignment including threading, modal views and text input.

h3. Threading

Threading is one of the most important things to learn when doing iPhone programming. For this assignment the main idea was to have any network requests (loading any of the Twitter data) happen in another thread with a spinner showing that something is happening. There are a number of ways to move tasks off the main thread in Objective-C that abstract things away from using threads directly.

So far I have found using NSOperations to be the easiest way to deal with threads. One way to create an NSOperation is by creating a subclass and using an instance of that object in your code. My image loading operation for Presence 3 is below.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;@interface ImageLoadingOperation : NSOperation {
	NSURL *imageURL;
	id target;
	SEL selector;
}
- (id) initWithImageURL:(NSURL *)url target:(id)theTarget 
                                   selector:(SEL)theSelector;
@end

@implementation ImageLoadingOperation

- (void) main {
  NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
  UIImage *image = [[UIImage alloc] initWithData:imageData];
  
  if(image == nil){
    image = [[UIImage alloc] init];
  }
  NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:image, 
                          @&quot;image&quot;, imageURL, @&quot;url&quot;, nil];
	
  [target performSelectorOnMainThread:selector 
                           withObject:result 
                        waitUntilDone:NO];
	
  [imageData release];
  [image release];
}
@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

To create an NSOperation subclass the first thing you need to do is override the main method, that&#39;s where the bulk of your code for the background thread will go. Once the work you need to do is finished you need to send the results back to the main thread with the method &#39;performSelectorOnMainThread:withObject:waitUntilDone:&#39; passing the result and a boolean to say whether this thread should block until the selector is performed.

Now that we have an operation defined we need to create an instance and use it. It&#39;s pretty much the same as using any other object, the only difference is that you need to add the operation to an operation queue and it deals with scheduling and all that.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;operationsQueue = [[NSOperationQueue alloc] init];

ImageLoadingOperation *operation = [[ImageLoadingOperation alloc] 
  initWithImageURL: url
  target:self
  selector:@selector(didFinishLoadingImageWithResult:)];
[operationsQueue addOperation:operation];
[operation release];&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

Everything here is pretty straight forward, you create an operations queue (which can be used for many different types of operations) and then add the operation instance to the queue to be executed.

Another way to use operations for threading is by using the NSInvocationOperation class. It&#39;s a implementation of NSOperation that you can use instead of having to subclass it yourself. All you have to do is remember to call &#39;performSelectorOnMainThread:withObject:waitUntilDone:&#39; in the method given as the selector parameter.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;NSInvocationOperation *operation = [[NSInvocationOperation alloc]
  initWithTarget:self
  selector:@selector(sendMessage:)
  object:text];

[operationsQueue addOperation:operation];
[operation release];&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

h3. Modal Views

Modal Views are fairly common on the iPhone, it&#39;s a view that can be popped up in the stack and has to be dismissed before getting back to any previous interactions. Think of when you&#39;re composing an email or adding a contact; the view that shows when doing those actions is presented modally.

Any view controller (or navigation controller since it&#39;s a subclass) can be presented modally with one simple method call.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;[self presentModalViewController:composeView animated:YES];&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This will show the &#39;composeView&#39; which has to be dismissed before the user can continue whatever they were previously doing. Dismissing the view is best done by delegating back to the view or controller that presented it.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;@implementation ComposeViewController

-(IBAction) cancelButtonPressed:(id)sender {
  if([self.delegate respondsToSelector:@selector(composeViewDidFinish)]) {
    [self.delegate composeViewDidFinish];
  }
}

@end&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

When the composeView was created I set the creator as the delegate, then when the cancel button is pressed I can tell the delegate that the composeView is finished and it can decide to dismiss the view or do something else. One simple method call in the delegate dismisses the modal view.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;[self dismissModalViewControllerAnimated:YES];&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

h3. Text Input

Handling text input is incredibly easy since the iPhone handles most of the annoying work for you. You don&#39;t have to worry about calling up the keyboard or anything like that, when a keyboard is needed the framework knows and displays it for you. There&#39;s a lot of customization that you can do through Interface Builder or code, all of which is pretty straight forward.

If you do need to interact with what&#39;s happening with the keyboard there are some optional delegate methods that you can implement. Just set a class as the inputs&#39; delegate and implement the methods you want.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (BOOL)textField:(UITextField *)textField
    shouldChangeCharactersInRange:(NSRange)range 
    replacementString:(NSString *)string {
    
  NSString *testString = [textField.text 
                          stringByReplacingCharactersInRange:range withString:string];
  charactersRemaining.text = [NSString stringWithFormat:@&quot;%d&quot;, (140-[testString length])];

  if( [testString length]&amp;gt;0 &amp;amp;&amp;amp; ([testString length]) &amp;lt;= 140 ) {
    sendButton.enabled = YES;
  } else {
    sendButton.enabled = NO;
  }

  return YES;  
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This first method gives you a bunch of information about the current keyboard interaction, like what string is going to be added and where in the range of the string it&#39;s going to be placed. This lets you filter out characters or modify what is happening with the input. A boolean is returned to say when the input should take place or not. In my case I wanted to enable or disable another button depending on how much text was going to be in the input. By using the &#39;stringByReplacingCharactersInRange&#39; method on the current input text and the string that was being passed in the resulting text length can be found. Thanks to Ben Lachman who &quot;helped me out with this&quot;:http://stackoverflow.com/questions/1561208/iphone-objective-c-only-enable-a-button-if-nstextfield-is-not-blank.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objectivec&quot; data-lang=&quot;objectivec&quot;&gt;- (BOOL)textFieldShouldReturn:(UITextField *)textField{
  if ([textField.text length]&amp;lt;=140) {
  	[textField resignFirstResponder];
	
  	if([self.delegate respondsToSelector:@selector(composeViewDidFinish:withText:)]) {
  		[self.delegate composeViewDidFinish:self withText:textField.text];
  	}
  	return YES;		
  } else {
  	return NO;
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

This next method lets you decide what should happen when return (or send, or go) is pressed. You can call other methods here and return a boolean saying whether the keyboard should return or not. Notice that I am letting the delegate decide what to do with the result.

h3. Conclusion

Well, there was a lot going on in this version of Presence but hopefully I didn&#39;t cut things down too much in this blog post. The most interesting bit is the threading, it&#39;s also the most useful. If you want some more details just let me know or take a look at my version of &quot;Presence 3&quot;:http://github.com/jduff/Presence/tree/V3 yourself.</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>My Ideal Job</title>
        
        <link href="http://jduff.github.com/2009/10/08/my-ideal-job/"/>
        <updated>2009-10-08T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/10/08/my-ideal-job</id>
        <content type="html">Well, I have recently found myself without a job so am in the processes of looking for something. I thought this might be a good opportunity to think about what I really want from a job / employer so that I can try and find something that I&#39;ll really enjoy. You end up spending most of your waking life at work so you might as well enjoy it, right? I&#39;ve decided to put this up on my blog just in case the perfect employer happens to stumble by :). Here it goes.

h4. Working with Technologies I Love

This is number one on my list. I want to work with technology that I love, something that I find really interesting and cutting edge. I love programming Ruby. It is by far the most enjoyable programming language I have ever worked with. That being said, I&#39;ve started learning some Objective-C and iPhone programming and though the language isn&#39;t as nice as Ruby, there&#39;s something about programming a device that has a GPS, camera, phone and so many other goodies that is so very cool.

h4. Working with Smart, Fun People

This isn&#39;t really second, more like equal to the first point. I want to work somewhere that I will continually be learning from the people around me.	Smart might not be the only word to describe these people; innovative, motivated, creative coworkers who will help me improve and grow my skill set is a must. At the same time I want to be able to joke around, have them over for BBQs and have fun with my coworkers.

h4. Develop an Amazing Product

I want to work on something that I think is amazing, something that I&#39;ll go home and talk to my wife about, think about and work on whenever I can. Difficult, engaging problems that will require me to think and come up with interesting solutions are what I&#39;m looking for. I want to make a real contribution to the product, add new and interesting features and continually improve the user experience.

h4. Flexible

Living here in the Great White North it would be nice to work somewhere that has a somewhat flexible schedule. Sometimes it&#39;s a lot easier to open up the laptop at home than braving the partially plowed streets and icy roads.

h4. Open Source Aware

Actually, not just aware of and using Open Source technologies, I want to work somewhere that they actively contribute back to the Open Source community. Somewhere that they encourage their developers to spend a little bit of time working on and creating new Open Source projects. I&#39;ve made a few Open Source contributions that you can see on my &quot;GitHub Profile&quot;:http://github.com/jduff but I would really like to do a lot more.

h4. Local (or Telecommute)

Though it does get cold here, my wife and I love where we live and having our family close by. We have no real interest in packing everything up and moving. I&#39;m looking for something in the Ottawa area, or someone who is willing to have an employee work remotely.

Well, that&#39;s basically it, hopefully this perfect position exists. If this sounds a lot like your business please check out my &quot;Resume&quot;:http://jduff.github.com/resume/ and get in touch.</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Lunch and Learn, iPhoneU</title>
        
        <link href="http://jduff.github.com/2009/09/28/iphoneu/"/>
        <updated>2009-09-28T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/09/28/iphoneu</id>
        <content type="html">For the past couple weeks a few of us at work have gotten into watching screen casts while having our lunch. There have been a variety of topics so far include one on &quot;MacRuby&quot;:http://s3.amazonaws.com/rubyonosx/rubyonosx2009-02-hotcocoa_introduction-rich_kilmer.m4v and another on &quot;HTML5&quot;:http://www.vimeo.com/6691519. Most of the time though it&#39;s been some sort of &quot;iPhone&quot;:http://icodeblog.com/2009/09/15/introduction-to-mapkit-in-iphone-os-3-0/ &quot;programming&quot;:http://videos.71squared.com/6381001 screen cast, the staple being the Stanford &quot;iPhone Application Programming&quot;:http://www.stanford.edu/class/cs193p/cgi-bin/index.php lectures.

Not only is this a lot of fun (yes, I am a big nerd and think a video on HTML5 is fun) but I find that learning a new programming language/framework/etc really helps with your day to day work. Every programming language does things a little differently. When you embrace the methodologies of a new language it can open your eyes to different ways of looking at the programming problems you might face, no matter what technologies you&#39;re using.

On top of just watching the Stanford lectures they have all the &quot;notes and assignments online&quot;:http://www.stanford.edu/class/cs193p/cgi-bin/index.php so we&#39;ve been working away at those in the evenings. I&#39;ve started posting my solutions to GitHub and will continue to update them as we progress. &quot;HelloPoly&quot;:http://github.com/jduff/HelloPoly and &quot;Presence 2&quot;:http://github.com/jduff/Presence/tree/V2 are completed so far, check them out if you&#39;re interested.

If you are interesting in programming for the iPhone or just want to try something new I&#39;d defiantly recommend the &quot;Stanford iPhone lectures&quot;:http://www.stanford.edu/class/cs193p/cgi-bin/index.php. The final version of the Presence assignment ends up being a full blown Twitter client with threading, contacts integration, search and much more.

Take the initiative and have your own Lunch and Learns.</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Create a Remote Branch with Git</title>
        
        <link href="http://jduff.github.com/2009/09/21/create-remote-branch/"/>
        <updated>2009-09-21T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/09/21/create-remote-branch</id>
        <content type="html">Create a branch of your current code on the remote with git:

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  git push origin master:refs/heads/BRANCH_NAME&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>SCP</title>
        
        <link href="http://jduff.github.com/2009/08/09/scp/"/>
        <updated>2009-08-09T00:00:00+00:00</updated>
        <id>jduff.github.com:/2009/08/09/scp</id>
        <content type="html">I don&#39;t have to do this often but every time I need to scp something up to an EC2 server I forget the options and have to waste 10 minutes finding it. Here it is so I don&#39;t need to look for it anymore.

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  scp &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; PRIVATE_KEY LOCAL_FILE USER@IP:REMOTE_LOCATION&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

These &quot;two&quot;:http://www.mkssoftware.com/docs/man1/scp.1.asp &quot;links&quot;:http://www.hypexr.org/linux_scp_help.php have a number of other examples and list some of the other options.</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>It&#39;s Okay to Say &quot;I Don&#39;t Know&quot;</title>
        
        <link href="http://jduff.github.com/2008/12/11/its-okay-to-say-i-dont-know/"/>
        <updated>2008-12-11T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/12/11/its-okay-to-say-i-dont-know</id>
        <content type="html">&lt;p&gt;I&amp;#39;ve only been working in the tech industry for a couple years now and I&amp;#39;m starting to notice that people (and companies) have a very difficult time saying &amp;quot;I don&amp;#39;t know&amp;quot; (or &amp;quot;no&amp;quot;, &amp;quot;we can&amp;#39;t&amp;quot;, etc).&amp;#0160; Why is this?&amp;#0160; There&amp;#39;s nothing wrong with not knowing something, as long as you have the skills and abilities to figure it out. &lt;/p&gt;&lt;p&gt;I was at a local BarCamp meetup a little while back and one the people there was talking about finding jobs.&amp;#0160; At one point he said to never say you can&amp;#39;t do something in a job interview or else you wont get the job.&amp;#0160; I was baffled.&amp;#0160; If you can&amp;#39;t do something, why would you say you can?&amp;#0160; At some point the truth is going to come out anyways.&amp;#0160; Is this really what it&amp;#39;s come down to?&amp;#0160; A better question, do managers expect this when doing interviews?&amp;#0160; Do they expect people to say they can do anything even though they can&amp;#39;t?&amp;#0160; I really don&amp;#39;t know, but this kind of scares me.&lt;/p&gt;&lt;p&gt;I have a couple friends from Europe and they&amp;#39;re just as confused by this behavior as I am.&amp;#0160; Apparently they don&amp;#39;t have a problem with this, if you have something on your resume you bloody well know how to do it, if you can&amp;#39;t do something they expect you to say so.&lt;/p&gt;&lt;p&gt;And really, what is the problem with hiring someone that might not know every detail of everything the position requires?&amp;#0160; If I were hiring someone I&amp;#39;d mainly be interested in their general problem solving and critical thinking skills.&amp;#0160; Sure, you would need to have the basic skills for the job, but as long as it&amp;#39;s obvious that you&amp;#39;re smart and interesting in learning what you don&amp;#39;t know what&amp;#39;s the difference?&amp;#0160; I&amp;#39;ll take that over someone who doesn&amp;#39;t care about the job and is just there for a paycheck any day.&lt;/p&gt;&lt;p&gt;What have your experiences been, have you noticed the same things?&amp;#0160; Do you say &amp;quot;I don&amp;#39;t know&amp;quot; enough?&amp;#0160; Leave it in the comments.&lt;br /&gt;&lt;em&gt;&lt;br /&gt;&amp;quot;We need to accept our ignorance and say &amp;#39;I don&amp;#39;t know&amp;#39; more often&amp;quot; &lt;/em&gt;- Malcolm Gladwell, Blink&lt;/p&gt;



</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Thinking about Testing</title>
        
        <link href="http://jduff.github.com/2008/12/04/thinking-about-testing/"/>
        <updated>2008-12-04T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/12/04/thinking-about-testing</id>
        <content type="html">&lt;p&gt;I&amp;#39;ve always been a big fan of including tests for any of the code I write.&amp;#0160; It was beaten into us in university, made sense when using &lt;a href=&quot;http://www.junit.org/&quot;&gt;JUnit&lt;/a&gt; and made easy in ruby with &lt;a href=&quot;http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html&quot;&gt;Test::Unit&lt;/a&gt;.&amp;#0160; Sometimes I still get annoyed when writing tests though.&amp;#0160; I&amp;#39;ve been thinking about testing a little more than usual the last couple of weeks, mostly about what bothers me when writings tests.&amp;#0160; I hate writing brittle tests.&amp;#0160; I do my best to avoid this, but sometimes in a large project when you&amp;#39;re trying to test everything it becomes difficult.&amp;#0160; The other thing I really hate is trying to test everything.&amp;#0160; I know, I know, &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_coverage&quot;&gt;code coverage&lt;/a&gt; is a good thing, but what good does 100% code coverage do your customers or users?&amp;#0160; Does it make the app suck less?&amp;#0160; Well, I suppose it could, but isn&amp;#39;t it possible that 95% or even 80% coverage would be just as good (for the users), depending on what was tested?&amp;#0160; I&amp;#39;d say it&amp;#39;s very possible.&lt;/p&gt;&lt;p&gt;To get around my first annoyance, the brittle tests, I&amp;#39;ve started creating the objects that I need in the test itself instead of using fixtures (this is &lt;a href=&quot;http://rubyonrails.com/&quot;&gt;rails&lt;/a&gt;).&amp;#0160; This lets me build up the objects for my test without worrying that adding another fixture will break existing tests.&amp;#0160; This works alright for unit tests and smaller scenarios, but creates a bunch of duplicate code when a number of tests use objects that are setup in a similar manner (refactoring the setup into methods helps with this, but the tests get confusing as you need to jump around methods).&lt;/p&gt;&lt;p&gt;Next problem, I want to write tests for things that need to be tested, not some far off situation that I think could happen.&amp;#0160; In Jamis Bucks talk at RubyConf, &lt;a href=&quot;http://rubyconf2008.confreaks.com/recovering-from-enterprise.html&quot;&gt;Recovering from Enterprise&lt;/a&gt;, he said that you should &amp;quot;&lt;em&gt;code just in time, not just in case...there&amp;#39;s no excuse to sit and play what if games&lt;/em&gt;&amp;quot;.&amp;#0160; I feel exactly the same way.&amp;#0160; Now, I&amp;#39;ve been thinking over this for a couple days, doing some reading and whatnot and have decided (hope!) that RSpec will be my savior.&amp;#0160; From the &lt;a href=&quot;http://rspec.info/&quot;&gt;rspec.info&lt;/a&gt; site, &amp;quot;&lt;em&gt;Rspec is a Behavior Driven Development (&lt;a href=&quot;http://en.wikipedia.org/wiki/Behavior_driven_development&quot;&gt;BDD&lt;/a&gt;) framework for Ruby&lt;/em&gt;&amp;quot;.&amp;#0160; The way it works is you write &amp;#39;specifications&amp;#39; (specs) that define how the system should behave.&amp;#0160; By writing he specs first and then writing the implementation methods afterward you are building, and testing, the system as it should behave; you&amp;#39;re not testing arbitrary situations that probably wont occur.&amp;#0160; Writing tests first and implementation code afterwords also has a neat catch phrase, Test Driven Development (&lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;TDD&lt;/a&gt;).&amp;#0160; RSpec allows you to nest scenarios as well which helps me with the first problem I was having as I could build up the context of the test suite as I went, reusing the earlier setup if I wanted.&lt;/p&gt;&lt;p&gt;So far I&amp;#39;ve done a lot of reading and have written a few specs, but really haven&amp;#39;t scratched the surface of what RSpec has to offer.&amp;#0160; I&amp;#39;m not sure if this will solve all my testing woes, but it&amp;#39;s defiantly making me think and test a bit differently, which I like.&lt;/p&gt;</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Leaving for RubyConf 2008 Tomorrow</title>
        
        <link href="http://jduff.github.com/2008/11/04/leaving-for-rubyconf-2008-tomorrow/"/>
        <updated>2008-11-04T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/11/04/leaving-for-rubyconf-2008-tomorrow</id>
        <content type="html">&lt;p&gt;I&amp;#39;m really looking forward to leaving tomorrow afternoon for Orlando Florida to attend &lt;a href=&quot;http://rubyconf.org&quot;&gt;RubyConf 2008&lt;/a&gt;, it should be a blast.&amp;#0160; The hotel looks amazing, the weather is going to be great, what more can you ask for?&amp;#0160; Oh ya, there is more, some great talks and presentations from Rubyists around the world!&lt;/p&gt;&lt;p&gt;There are a number of interesting presentations, but a a couple of them really stand out.&amp;#0160; One presentation that I&amp;#39;m really looking forward to is &amp;#39;&lt;a href=&quot;http://rubyconf.org/talks/18&quot;&gt;Recovering from Enterprise: how to embrace Ruby&amp;#39;s idioms and say goodbye to bad habits&lt;/a&gt;&amp;#39; by Jamis Buck of &lt;a href=&quot;http://37signals.com/&quot;&gt;37signals&lt;/a&gt;.&amp;#0160; I really respect the guys at 37, they have a no bullshit way of saying things that &lt;a href=&quot;http://gettingreal.37signals.com/toc.php&quot;&gt;just make sense&lt;/a&gt;, I like that.&amp;#0160; Jamis is also a long time Rubyist and has given so much to the community with the projects he&amp;#39;s worked on (capistrano, sqllite ruby bindings), and has been teasing us with &lt;a href=&quot;http://www.37signals.com/svn/posts/1340-embrace-real-constraints-not-artificial-ones&quot;&gt;interesting blog posts&lt;/a&gt; related to his presentation.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;I&amp;#39;m also interested in the talk Scott Chacon is giving, &amp;#39;&lt;a href=&quot;http://rubyconf.org/talks/8&quot;&gt;Using Git in Ruby Applications&lt;/a&gt;&amp;#39; mainly because I find &lt;a href=&quot;http://en.wikipedia.org/wiki/Git_%28software%29&quot;&gt;Git&lt;/a&gt; to be such an in interesting source control system (and maybe I can pull some of my co-workers along so Scott can infect them with the Git as well).&amp;#0160; It sounds like Scott is going to be getting into some very interesting things with his presentation as well, such as using git as the backend for a ruby based wiki or file backup system.&amp;#0160; Cool stuff.&lt;/p&gt;&lt;p&gt;On Friday I&amp;#39;m probably going to try and catch Yehuda Katz presentation, &amp;#39;&lt;a href=&quot;http://rubyconf.org/talks/51&quot;&gt;Writing Code That Doesn&amp;#39;t Suck: Interface P=Oriented Design&lt;/a&gt;&amp;#39; since, if you&amp;#39;ve read any of my &lt;a href=&quot;/2008/09/24/make-it-suck-less/&quot;&gt;other&lt;/a&gt; &lt;a href=&quot;/2008/10/29/ec2-makes-getting-a-startup-going-suck-less/&quot;&gt;blog&lt;/a&gt; &lt;a href=&quot;/2008/10/21/making-input-fields-suck-less/&quot;&gt;posts&lt;/a&gt;, I really like to do as much as possible to make things suck less.&amp;#0160; I&amp;#39;m not all that interested in Merb though so I may wander over to &amp;#39;&lt;a href=&quot;http://rubyconf.org/talks/50&quot;&gt;Ruby Heavy-Lifting: Lazy load it, Event it, Defer it, and then Optimize it.&lt;/a&gt;&amp;#39; by Ilya Griorik and see what he has to say beacause, really, can you every know enough about making you code and application run faster?&amp;#0160; Didn&amp;#39;t think so.&lt;/p&gt;&lt;p&gt;Anyways, that&amp;#39;s just a short run down on some of the great presentations that are going to be happening this weekend.&amp;#0160; There will also be appearances by Matz (the creator of Ruby) and Dave Thomas (Pragmatic Programmers), both are likely to have something interesting to say.&lt;/p&gt;&lt;p&gt;See you in Orlando!&lt;/p&gt;</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Facebook Applications are so 2007</title>
        
        <link href="http://jduff.github.com/2008/11/03/facebook-applications-are-so-2007/"/>
        <updated>2008-11-03T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/11/03/facebook-applications-are-so-2007</id>
        <content type="html">&lt;p&gt;&lt;img alt=&quot;Facebooklogo&quot; border=&quot;0&quot; class=&quot;at-xid-6a00e554746ace8834010535d0852b970b &quot; src=&quot;/images/old/facebook.jpg&quot; title=&quot;Facebooklogo&quot; /&gt;&amp;#0160; When &lt;a href=&quot;http://facebook.com&quot;&gt;Facebook&lt;/a&gt; released their application platform &lt;a href=&quot;http://www.techcrunch.com/2007/05/24/facebook-launches-facebook-platform-they-are-the-anti-myspace/&quot;&gt;last year&lt;/a&gt; it was revolutionary and a slew of businesses popped up out of nowhere.&amp;#0160; A number of these business got huge valuations and &lt;a href=&quot;http://www.insidefacebook.com/2007/07/11/facebook-vc-were-investing-in-facebook-apps-too/&quot;&gt;outside funding&lt;/a&gt;, some even made some money.&amp;#0160; But now that the dust has settled from the landgrab and the competitors have caught up with their own offerings (with a &lt;a href=&quot;http://blueprintcode.typepad.com/blueprint_code/2008/11/follow-the-leader---linkedin-does-an-app-platform-why.html&quot;&gt;varying degree of success&lt;/a&gt;) what&amp;#39;s next for the app platform?&amp;#0160; Well, from where I sit, it looks like it&amp;#39;s being retired.&lt;/p&gt;&lt;p&gt;The &amp;#39;beta&amp;#39; features such as the &lt;a href=&quot;http://wiki.developers.facebook.com/index.php/Data_Store_API_documentation&quot;&gt;Data Storage apis&lt;/a&gt; have had almost no movement in over a year, the api itself hasn&amp;#39;t had any drastic changes (except for the ones do to the new layout) in months, what&amp;#39;s been going on?&amp;#0160; It used to be that notices would be posted on a weekly basis about updates and new features, now there&amp;#39;s nothing.&amp;#0160; The chatter around the Facebook platform is dying down to a dull hum.&lt;/p&gt;&lt;p&gt;Applications are pushed out of the main page, multiple clicks away, the directory is bloated with thousands and thousands of pointless applications, how are you supposed to make a mark?&amp;#0160; Facebook started out with an &amp;#39;anything goes&amp;#39; policy for applications, when things started turning into a blue and white version of Myspace they realized their mistakes and clamped down on the restrictions making it impossible for new applications to break in.&lt;/p&gt;&lt;p&gt;Facebooks Solution:&amp;#0160; Facebook Connect&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://developers.facebook.com/news.php?blog=1&amp;amp;story=108&quot;&gt;Connect&lt;/a&gt; seems to be the solution to the broken application platform.&amp;#0160; Instead of embedding your application into Facebook you can now have users login through your website to Facebook and allow your application to access their data.&amp;#0160; So basically all their doing is Single Sign On and a standard api to access the users data.&amp;#0160; What&amp;#39;s revolutionary about this?&amp;#0160; Nothing.&amp;#0160; That &lt;a href=&quot;http://www.wired.com/techbiz/startups/news/2007/10/facebook_future&quot;&gt;$15 billion dollar valuation&lt;/a&gt; is seeming more ridiculous every day.&lt;/p&gt;&lt;p&gt;This doesn&amp;#39;t mean Facebook applications are totally useless now, it just means there aren&amp;#39;t going to be any business built solely on a Facebook app anymore.&amp;#0160; Since the spotlights moved on, Facebook needs to work at becoming cash flow positive to make keep things rolling, unless they they can build another &lt;a href=&quot;http://www.mondaynightcrew.com/issues/comic_0065.html&quot;&gt;Hype Machine&lt;/a&gt; to bring back the interest.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Follow The Leader - Linkedin Does an App Platform, Why?</title>
        
        <link href="http://jduff.github.com/2008/11/01/follow-the-leader-linkedin-does-an-app-platform-why/"/>
        <updated>2008-11-01T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/11/01/follow-the-leader-linkedin-does-an-app-platform-why</id>
        <content type="html">&lt;p&gt;This past week saw something we&amp;#39;ve seem &lt;a href=&quot;http://www.techcrunch.com/2007/05/24/facebook-launches-facebook-platform-they-are-the-anti-myspace/&quot;&gt;before&lt;/a&gt;, &lt;a href=&quot;http://mashable.com/2007/12/11/bebo-platform/&quot;&gt;again&lt;/a&gt; and &lt;a href=&quot;http://mashable.com/2008/02/04/myspace-developer-platform-launches/&quot;&gt;again&lt;/a&gt;, with &lt;a href=&quot;http://www.linkedin.com/&quot;&gt;Linkedin&lt;/a&gt; launching it&amp;#39;s &lt;a href=&quot;http://blog.linkedin.com/2008/10/28/announcing-applications-on-linkedin/&quot;&gt;application platform&lt;/a&gt;.&amp;#0160; The big question is why, what&amp;#39;s the point?&amp;#0160; Their team is pushing it as professional applications for things like sharing book reviews, documents, and extended communication options.&lt;/p&gt;&lt;p&gt;Okay, that&amp;#39;s cool, but most of the people you generally connect with on Linkedin are professional peers, if you had a need for this you&amp;#39;re probably already doing it with something like IM or google docs.&amp;#0160; Since Linkedin is a professional network it doesn&amp;#39;t really lend itself to the type of viral &lt;a href=&quot;http://news.cnet.com/8301-17939_109-9727759-2.html&quot;&gt;sheep throwing applications&lt;/a&gt; that made the Facebook platform so popular.&lt;/p&gt;&lt;p&gt;Now, the thing I&amp;#39;m really wondering is why it took them almost a year from &lt;a href=&quot;http://blog.linkedin.com/2007/12/10/the-intelligent-2/&quot;&gt;announcing the platform&lt;/a&gt; (about 5 months after the Facebook platform took off) and actually &lt;a href=&quot;http://blog.linkedin.com/2008/10/28/announcing-applications-on-linkedin/&quot;&gt;releasing it&lt;/a&gt;.&amp;#0160; To me it seems like the first post on their platform was a load of crap and they were just trying to grab onto a bit of the hype that Facebook had generated.&amp;#0160; On top of this almost every application I tried to use gave me some sort of error or had information flowing outside of the visible area for the application.&amp;#0160; I expect more from such a &lt;a href=&quot;http://www.crunchbase.com/company/linkedin&quot;&gt;high profile company&lt;/a&gt; with over a year of development time.&lt;/p&gt;&lt;p&gt;This doesn&amp;#39;t make Linkedin suck less, if anything it makes them suck more because it seems like all their doing is running after the successful ideas from other companies.&amp;#0160; If it doesn&amp;#39;t make it suck less, don&amp;#39;t do it.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>EC2 Makes Getting a Startup Going Suck Less</title>
        
        <link href="http://jduff.github.com/2008/10/29/ec2-makes-getting-a-startup-going-suck-less/"/>
        <updated>2008-10-29T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/10/29/ec2-makes-getting-a-startup-going-suck-less</id>
        <content type="html">&lt;p&gt;Obviously getting your startup going doesn&amp;#39;t suck (well, hopefully not all the time), but it is a shit load of work.&amp;#0160; You need a kick ass idea, people to build it, a way to distribute, somehow get people to pay for what you&amp;#39;re doing and countless other tasks.&amp;#0160; This is a lot to deal with, and since you&amp;#39;re a startup it&amp;#39;s probably you or a small team doing all the work.&amp;#0160; Well, if you happen to be building a web based product &lt;a href=&quot;http://aws.amazon.com/ec2/&quot;&gt;Amazons EC2&lt;/a&gt; platform is defiantly something to check out.&lt;/p&gt;&lt;p&gt;EC2 is Amazons &amp;#39;Elastic &lt;a href=&quot;http://en.wikipedia.org/wiki/Cloud_computing&quot;&gt;Cloud Computing&lt;/a&gt;&amp;#39; platform and it lets you take advantage of Amazons huge server and computing infrastructure to run your own server instances.&amp;#0160; There are countless advantages to running your application in the cloud like this, the big ones in my opinion are cost savings as you &lt;a href=&quot;http://aws.amazon.com/ec2/#pricing&quot;&gt;pay for what you use&lt;/a&gt;, flexibility in expanding your server farm and the reliability of a distributed and proven network.&lt;/p&gt;&lt;p&gt;This is really cool.&amp;#0160; If you think back to a couple of years ago how you would setup your own infrastructure you&amp;#39;d need to go out and buy some expensive servers and load balances, get it all setup somewhere&amp;#0160; and then hope the traffic doesn&amp;#39;t blow up the machines before you can get get more in to handle the load.&amp;#0160; Now with EC2 you don&amp;#39;t need to worry about the hardware and over purchasing to handle the load or running out and buying a new machine when one gets fried.&lt;/p&gt;&lt;p&gt;Things with EC2 aren&amp;#39;t quite perfect yet, but they&amp;#39;re not far off and a lot of the pain points are going to be addressed in the near future (2009) Amazon says.&amp;#0160; From the &lt;a href=&quot;http://aws.typepad.com/aws/2008/10/big-day-for-ec2.html&quot;&gt;Amazon Web Services blog&lt;/a&gt;, here&amp;#39;s a couple of the things to look forward to:&lt;/p&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&lt;em&gt;&lt;strong&gt;Management Console&lt;/strong&gt; - The management console will simplify the process of configuring and operating your applications in the AWS cloud. You&amp;#39;ll be able to get a global picture of your cloud computing environment using a point-and-click web interface.&lt;br /&gt;&lt;strong&gt;Load Balancing&lt;/strong&gt; - The load balancing service will allow you to balance incoming requests and traffic across multiple EC2 instances.&lt;br /&gt;&lt;strong&gt;Automatic Scaling&lt;/strong&gt; - The auto-scaling service will allow you to grow and shrink your usage of EC2 capacity on demand based on application requirements.&lt;br /&gt;&lt;strong&gt;Cloud Monitoring&lt;/strong&gt; - The cloud monitoring service will provide real time, multi-dimensional monitoring of host resources across any number of EC2 instances, with the ability to aggregate operational metrics across instances, Availability Zones, and time slots.&lt;br /&gt;&lt;/em&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;Awesomesauce.&amp;#0160; Those are the exact things that have been creating extra work when using their current offering, Amazon is spot on with the features that their users are really looking for.&lt;/p&gt;&lt;p&gt;I really like what Amazon is doing in this space, but if you don&amp;#39;t or if it doesn&amp;#39;t do what you need it to there are alternatives.&amp;#0160; &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;Google App Engine (GAE)&lt;/a&gt; is one such alternative that looks pretty neat.&amp;#0160; It&amp;#39;s neat because it&amp;#39;s built by google, on top of their infrastructure and allows easy integration with existing google services (docs, accounts, etc).&amp;#0160; In it&amp;#39;s current state it&amp;#39;s nothing compared to EC2.&amp;#0160; &lt;/p&gt;&lt;p&gt;The biggest difference is that with GAE you&amp;#39;re tied to using python for your application development and you can&amp;#39;t really customize the platform at all.&amp;#0160; With EC2 you start with a basic linux (and now windows) that you can then customize with whatever you want.&amp;#0160; But if you don&amp;#39;t want to do all that work, and you&amp;#39;re a python kind of person, GAE might be perfect for you.&amp;#0160; I, on the other hand, prefer the flexibility you get with EC2 and can&amp;#39;t wait to see where they go from here.&lt;/p&gt;&lt;p&gt;Go out, &lt;a href=&quot;http://docs.amazonwebservices.com/AmazonEC2/gsg/2006-06-26/&quot;&gt;get started&lt;/a&gt;.&lt;/p&gt;

</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>ActiveApi - Wrapping a RESTful API in AS3</title>
        
        <link href="http://jduff.github.com/2008/10/22/activeapi-wrapping-a-restful-api-in-as3/"/>
        <updated>2008-10-22T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/10/22/activeapi-wrapping-a-restful-api-in-as3</id>
        <content type="html">&lt;p&gt;ActiveApi is my AS3 wrapper for a RESTful api, I just came up with ActiveApi right now so if I&amp;#39;m stepping on someones toes just let me know.&amp;#0160; In &lt;a href=&quot;/2008/10/19/wrapping-a-restful-rails-api-in-flex/&quot;&gt;my last post&lt;/a&gt; I kind of went over how I came up with these classes so I&amp;#39;m just going to dive into some code.&amp;#0160; &lt;/p&gt;&lt;p&gt;To get started you need to define a controller class that extends from activeapi.base.Controller.&amp;#0160; This class should be a singleton, you can do that however you like.&amp;#0160; Controller defines a getter base_url that just throws an error so you&amp;#39;ll want to override that so it returns your base url.&amp;#0160; This is what you&amp;#39;ll get:&lt;/p&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&lt;em&gt;package activeapi.example&lt;br /&gt;{&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; import activeapi.base.Controller;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; public class ExampleController extends Controller&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public const BASE_URL:String = &amp;quot;http://localhost:3001/&amp;quot;;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; private static var ExampleController = new ExampleController(true);&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public function TrackerController(only_one_allowed:Boolean) {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public static function get inst(): ExampleController {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; return _instance;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public override function get base_url():String {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; return BASE_URL;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;}&lt;/em&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;Controller extends from EventDispatcher so you get all the event listening and dispatching methods from that.&amp;#0160; This is the class that you will add listeners to for CREATE and DELETE of your objects, like this:&lt;/p&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&lt;em&gt;ExampleController.inst.addEventListener(&amp;quot;session&amp;quot;+ActiveEvent.CREATE, auth);&lt;br /&gt;&lt;/em&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;Point to note, I&amp;#39;m prefixing the type of object I am creating to the event string, this isn&amp;#39;t the ideal design but it was the best I could come up with.&lt;/p&gt;&lt;p&gt;Next is defining the class that is going to be doing the RESTful operations, the Session class in this example.&amp;#0160; For now I haven&amp;#39;t found a reason to create a base class to extend from, instead you instantiate an object that will be used to delegate the work to.&amp;#0160; This is what the basic Session class would look like:&lt;/p&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&lt;em&gt;package activeapi.example&lt;br /&gt;{&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; import mx.rpc.events.ResultEvent;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; import activeapi.example.base.ActiveEvent;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; import activeapi.example.base.ResourceHandler;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; public class Session&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; //Static resource handler, passing in the name of the model and the controller instance.&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; private static var resource:ResourceHandler = new ResourceHandler(&amp;quot;session&amp;quot;, ExampleController.inst);&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public var id:String;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public function Session(identifier:String)&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; id = identifier;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public static function create(args:Object):void {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; //let the resource handler make the call&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; resource.create(args, create_complete_callback);&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; // static create method Session.create&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; private static function create_complete_callback(event:ResultEvent):void {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; //delegate to the resource handler to handle the basic result and fire the events.&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; resource.handle_and_dispatch(ActiveEvent.CREATE, Session.parse(event.result), event);&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public function destroy():void {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; resource.destroy({id:id}, delete_complete_callback);&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; private function delete_complete_callback(event:ResultEvent):void {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; resource.handle_and_dispatch(ActiveEvent.DELETE, null, event);&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; public static function parse(data:Object):Session {&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; //return a new session from the data&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;&amp;#0160;&amp;#0160;&amp;#0160; }&lt;br /&gt;}&lt;br /&gt;&lt;/em&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;This class has a bit more going on.&amp;#0160; First off is the ResourceHandler, it takes the name of the object type you want to create and a Controller as it&amp;#39;s parameters.&amp;#0160; I made mine static so that I could use it in both my static create method and instance method destroy.&amp;#0160; Under the covers the ResourceHandler sets up some HTTPService objects pointing to the urls for creating and destroying the session object and setting op the correct mehod and response type (XML).&amp;#0160; These objects aren&amp;#39;t accessible but are used by calling the create and destroy methods on the ResourceHandler.&amp;#0160; In the callback I use another method on the, handle_and_dispatch, to do some basic parsing of the response and then dispatching the events on the controller.&amp;#0160; The second parameter of handle_and_dispatch is an object and is added to the final event that is dispatched.&amp;#0160; The auth method that was added to listen for session CREATE before might look something like this:&lt;br /&gt;&lt;em&gt;&lt;br /&gt;&lt;/em&gt;&lt;/p&gt;&lt;div style=&quot;margin-left: 40px;&quot;&gt;&lt;em&gt;private function auth(event:ActiveEvent):void {&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;#0160;&amp;#0160;&amp;#0160; if(Session(event.object).id!=null)&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; Application.application.currentState = &amp;quot;logged_in&amp;quot;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;#0160;&amp;#0160;&amp;#0160; else&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;#0160;&amp;#0160;&amp;#0160; &amp;#0160;&amp;#0160;&amp;#0160; Alert.show(event.message.toString());&lt;/em&gt;&lt;br /&gt;&lt;em&gt;}&lt;/em&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;And that&amp;#39;s basically it.&amp;#0160; The ExampleController kind of acts like a central messaging system and the major work is delegated to the ResourceHandler.&amp;#0160; I still need to pull this out from the project I&amp;#39;m using it for, which shouldn&amp;#39;t take long, so if you&amp;#39;re interested in the code let me know in the comments.&amp;#0160; I&amp;#39;d also really appreciate some feedback on the design choices and improvement suggestions.&amp;#0160; Personally I&amp;#39;m still left feeling like there&amp;#39;s a better way but trying to figure something out has been sucking up way too much time.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Making Input Fields Suck Less</title>
        
        <link href="http://jduff.github.com/2008/10/21/making-input-fields-suck-less/"/>
        <updated>2008-10-21T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/10/21/making-input-fields-suck-less</id>
        <content type="html">&lt;p&gt;I subscribed to the blog &lt;a href=&quot;http://www.usabilitypost.com/&quot;&gt;Usability Post&lt;/a&gt; last week and have already come to love it.&amp;#0160; There&amp;#39;s a pile of content on this site, all geared towards making your products more user friendly.&amp;#0160; There&amp;#39;s everything you can think of here, from general ideas on using &lt;a href=&quot;http://www.usabilitypost.com/2008/10/17/categories-vs-tags/&quot;&gt;categories vs tags&lt;/a&gt;, to specific hints or tricks like how to &lt;a href=&quot;http://www.usabilitypost.com/2008/09/22/automatically-select-form-input-field-on-page-load/&quot;&gt;automatically select and input field on page load&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;One particular article was published last week that caught my eye on &lt;a href=&quot;http://www.usabilitypost.com/2008/10/15/css-tip-remove-mac-osx-glowing-blue-outlin-for-custom-styled-input-fields/&quot;&gt;how to remove the OS X glowing blue outline for custom styled input fields&lt;/a&gt;.&amp;#0160; This tip is great.&amp;#0160; It&amp;#39;s simple, it doesn&amp;#39;t change the world, it doesn&amp;#39;t disrupt anything, but it makes your app suck a whole lot less for the end user.&lt;/p&gt;&lt;p&gt;Check out the post, &lt;a href=&quot;http://www.usabilitypost.com/&quot;&gt;subscribe to the blog&lt;/a&gt; and start using these ideas to make your applications suck less, because really, who likes a sucky app?&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Wrapping a RESTful Rails API in FLEX</title>
        
        <link href="http://jduff.github.com/2008/10/19/wrapping-a-restful-rails-api-in-flex/"/>
        <updated>2008-10-19T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/10/19/wrapping-a-restful-rails-api-in-flex</id>
        <content type="html">&lt;p&gt;A little while back I was talking about getting started with &lt;a href=&quot;/2008/10/01/rails-and-air/&quot;&gt;writing an Air app in flex that talks to a Rails backend&lt;/a&gt; and some of the troubles I was having.&amp;#0160; I&amp;#39;ve been working on and off trying to fine tune what I started out with and turn it into a set of base classes for wrapping a restful api (based on the rails conventions).&amp;#0160; I&amp;#39;ve finally got something, it&amp;#39;s not ideal and it&amp;#39;s really not how I would have liked he design to turn out, but it&amp;#39;s better than anything I&amp;#39;ve come up with along the way.&lt;/p&gt;&lt;p&gt;I&amp;#39;ll start out with how I would have like this little framework to have turned out.&amp;#0160; What I was really looking for was a couple of base classes that defined the basic REST actions as well as some unifying way to dispatch and listen for events on the api.&lt;/p&gt;&lt;p&gt;The second problem, &amp;#39;event management&amp;#39; I guess, wasn&amp;#39;t too hard to solve, I created a Singleton (sort of, AS3 doesn&amp;#39;t really let you do this, but you can kind of fake it) that extended from EventDispatcher and then added and made dispatch calls on the instance.&amp;#0160; My class making the REST calls now needed to know about this &amp;#39;Controller&amp;#39; class to be able to do the event dispatching, it also made sense to define the endpoint url here.&lt;/p&gt;&lt;p&gt;Now, the main problem I was trying to solve, having a base class to define the REST calls, kept giving me trouble.&amp;#0160; At first defining instance methods for create, destroy, etc made sense but then as I started using the class having create as an instance method really didn&amp;#39;t make sense; create is building the object instance and should be a static class method.&amp;#0160; This is where my trouble started, since create (and get) actions should be static, if I wanted to define the logic in the base class then my subclass would still need to provide a wrapping method, or I&amp;#39;d be calling something like Base.create(&amp;quot;object_type&amp;quot;) everywhere, which didn&amp;#39;t really seem right to me.&amp;#0160; This lead me down a long road of messing this reflection classes, and introspection methods (which are awful in AS3 in my opinion) causing a lot of ugly code and me to become frustrated with my solution.&lt;/p&gt;&lt;p&gt;After messing about like this for three separate coding sessions I had enough and decided to get back to what it needs to do; blew away the base classes and brought everything into the main class (for now this was the Session) and structured things the way I wanted it to look for a client of the api.&amp;#0160; Once I got things working again it was again obvious that some things could be abstracted away, but I still have the problem that some api calls should be static and some not; which would pull me into the same mess as before with a base class.&lt;/p&gt;&lt;p&gt;So, Instead of doing that I created an object that wrapped up all the rest services into a single package then I created a static instance variable of this &amp;#39;ResourceHandler&amp;#39; inside my Session class and delegated the work to it.&amp;#0160; Now, this isn&amp;#39;t as easy as extending from a class and overriding a couple of methods, but it does hide away all the HTTPService definitions, adding and removing event listeners, and other redundancies from the classes.&lt;/p&gt;&lt;p&gt;I still think there should be a cleaner way to do some of this in AS3, maybe I just don&amp;#39;t know the language well enough though.&amp;#0160; Part way through I did find another framework that was trying to implement &lt;a href=&quot;http://code.google.com/p/as3-active-resource/&quot;&gt;ActiveResource in AS3&lt;/a&gt;, but the project doesn&amp;#39;t look very active anymore.&amp;#0160; I&amp;#39;ll post a little walkthrough of how the classes work in a bit, it&amp;#39;s still not complete yet but if you want to take a look at the code in the meantime leave a comment.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Rails and Air</title>
        
        <link href="http://jduff.github.com/2008/10/01/rails-and-air/"/>
        <updated>2008-10-01T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/10/01/rails-and-air</id>
        <content type="html">&lt;p&gt;As I said last time I&amp;#39;ve started playing around with Adobe Air, what I&amp;#39;m doing is a little Rails app with a Air desktop app written in Flex 3.&amp;#160; For the Rails portion I&amp;#39;m going with the standard REST actions with responses for html and xml.&amp;#160; The Air application then uses the REST api to communicate with the back end.&amp;#160; Everything is pretty straight forward, but getting flex to play nice was kind of frustrating.&lt;/p&gt;&lt;p&gt;The main problem was getting rails to accept the requests.&amp;#160; I started out with something like this:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-as3&quot; data-lang=&quot;as3&quot;&gt;  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HTTPService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTTPService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://localhost:3000/sessions&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ResultEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
  &lt;p&gt;The first problem I ran into with this is that Rails was ignoring the requests and kept giving me a ActionController::InvalidAuthenticityToken error.&amp;#160; It took a little googling but I finally tracked it down to the CRSF protection in Rails 2; basically all forms submitted required a auth token to be sent with the data to validate&amp;#160; the form was generated by the server it is being submitted to.&amp;#160; This is only required for HTML forms being submitted, if the content-type is something else (like xml for my api services) the Authenticity Token is not required.&lt;/p&gt;&lt;p&gt;Once I got that figured out the requests were making it a little bit further but still getting hung up.&amp;#160; This time it was the xml parsing saying I was trying to add a second root node to the xml.&amp;#160; This was pretty obvious, I was passing login and password without being wrapped in anything, a couple little changes and this is where I&amp;#39;m at:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-as3&quot; data-lang=&quot;as3&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HTTPService&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTTPService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;POST&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://localhost:3000/sessions&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;contentType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTTPService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CONTENT_TYPE_XML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ResultEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;user&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;A little change on the server so it looks for the login and password within the session object and off to the races.&amp;#160; Well, sort of.&amp;#160; You might notice that I slipped in that service.method = &amp;quot;POST&amp;quot;; HTTPService supports POST, GET, PUT, DELETE etc for the method.&amp;#160; This was great so I banged out another method for logging out, basically the same as the previous one but with service.method = &amp;quot;DELETE&amp;quot;.&amp;#160; This lead to a couple hours of debugging, googling and cURLing to try and figure out why logging out wasn&amp;#39;t working.&amp;#160; Long story short, the only type of requests HTTPService actually does is POST and GET, no matter what you set the service method to.&amp;#160; So, reach back and pull out the hacks to come up with this for the logout action url:&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-as3&quot; data-lang=&quot;as3&quot;&gt;    &lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://localhost:3000/sessions?_method=DELETE&#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now Rails can pick that out and knows that I&amp;#39;m trying to do a delete and routes the request correctly.&amp;#160; Now that I&amp;#39;m rolling it&amp;#39;s easy to keep defining service objects and making calls to my Rails server but it&amp;#39;s becoming clear that a lot of this can be abstracted away.&amp;#160; In my next post I&amp;#39;ll talk about how I&amp;#39;ve started designing that abstraction and how it&amp;#39;s going.&lt;/p&gt;</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Playing with Flex 3</title>
        
        <link href="http://jduff.github.com/2008/09/30/playing-with-flex-3/"/>
        <updated>2008-09-30T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/09/30/playing-with-flex-3</id>
        <content type="html">&lt;p&gt;I&amp;#39;ve started playing around with Adobe Air and Flex 3 again, man is it annoying sometimes.&amp;#160; I&amp;#39;ve been programming Ruby for awhile now and really like it so maybe it&amp;#39;s affecting how I look at other languages, but I&amp;#39;m starting to notice how convoluted and confusing things seem to be in other languages.&amp;#160; The thing that annoys me around every corner with Flex (and ActionScript 3) is how heavily the rely on events.&amp;#160; I understand the event pattern and how useful events can be, but most Flex code I look at gets very confusing trying to follow all the events jumping around.&amp;#160; Everything happens with events and listeners; click, mouse move, service calls, image loaders, url loaders... &lt;/p&gt;&lt;p&gt;Why does everything need to happen based on events?&amp;#160; Why can&amp;#39;t some things, like service calls, block until they get a response instead of fire and forget?&amp;#160; It would make a little more sense if flash was multi-threaded but it isn&amp;#39;t, so if something else starts happening and holding the runtime up it doesn&amp;#39;t matter if you&amp;#39;re event gets fired.&amp;#160; Maybe this is just me, but following from method call, to handler, to another handler because the last one threw another event is really annoying.&lt;/p&gt;&lt;p&gt;Well, now that I got that rant out of the way I&amp;#39;ll start digging in and trying to fit in with the Flex event based ways.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Make It Suck Less</title>
        
        <link href="http://jduff.github.com/2008/09/24/make-it-suck-less/"/>
        <updated>2008-09-24T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/09/24/make-it-suck-less</id>
        <content type="html">&lt;p&gt;That&amp;#39;s what I&amp;#39;m asking myself before I do anything these days.&amp;#160; Is what I am doing making it suck less?&amp;#160; Am I making it suck more?&amp;#160; Why am I doing it then?&amp;#160; I&amp;#39;m doing this before I write code or before changing something around the house; before doing anything.&lt;/p&gt;&lt;p&gt;I&amp;#39;m starting to find that most people, myself included, get caught up in what they&amp;#39;re doing, what they&amp;#39;re trying to achieve, and it distracts them.&amp;#160; Most people think what they&amp;#39;re doing is great, the best, and that they must be doing it right.&amp;#160; If you always think what you&amp;#39;re doing is already the perfect solution, can you really make something great?&amp;#160; If you&amp;#39;re only focused on where you want to be instead of watching the road ahead of you are you going to miss the potholes along the way?&lt;/p&gt;&lt;p&gt;This is why I assume it sucks.&amp;#160; It must suck, or else why would I be writing this code?&amp;#160; Or why would I be taking that woodchip path out of my backyard?&amp;#160; Because it sucks.&amp;#160; The process we&amp;#39;re using sucks, so I&amp;#39;m writing some code to fix it.&amp;#160; It sucks raking leaves and pulling up half the path at the same time so I&amp;#39;m putting in stepping stones.&lt;/p&gt;&lt;p&gt;Make it Suck Less.&lt;/p&gt;&lt;p&gt;Don&amp;#39;t try and take the gold right away, you need to work up to it.&amp;#160; You&amp;#39;ll just hurt yourself reaching for something that you can&amp;#39;t get to yet.&amp;#160; So work up to it, little bits at a time.&amp;#160; Make sure what you&amp;#39;re doing is getting there.&amp;#160; Make sure you&amp;#39;re solving the problem at hand.&amp;#160; Make it suck less to do something.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Strands - The Other, Other Life Streaming Service</title>
        
        <link href="http://jduff.github.com/2008/09/12/strands-the-other-other-lifes-streaming-service/"/>
        <updated>2008-09-12T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/09/12/strands-the-other-other-lifes-streaming-service</id>
        <content type="html">&lt;p&gt;&lt;img alt=&quot;Strands_logo&quot; border=&quot;0&quot; class=&quot;at-xid-6a00e554746ace8834010534a601d1970c &quot; src=&quot;/images/old/strands.jpg&quot; title=&quot;Strands_logo&quot; /&gt; A little while back I heard some chatter on &lt;a href=&quot;http://friendfeed.com&quot;&gt;FriendFeed&lt;/a&gt; about &lt;a href=&quot;http://www.jaiku.com/&quot;&gt;another&lt;/a&gt; &lt;a href=&quot;http://socialthing.com/&quot;&gt;life&lt;/a&gt; &lt;a href=&quot;http://www.socialmedian.com/&quot;&gt;streaming&lt;/a&gt; &lt;a href=&quot;http://secondbrain.com/&quot;&gt;service&lt;/a&gt; that had just come out and was &amp;#39;FriendFeed but better&amp;#39;.&amp;#160; Naturally I had to check it out and take a look for myself to see what all the hype was about over &lt;a href=&quot;http://strands.com&quot;&gt;Strands&lt;/a&gt;.&amp;#160; I created my account, added some services and friended some people.&amp;#160; That night I spent a couple hours checking out peoples feeds and clicking around.&amp;#160; I hadn&amp;#39;t looked in again until tonight, almost a month later.&lt;/p&gt;&lt;p&gt;There&amp;#39;s a lot of competition in the feed aggregation or life streaming area these days so you really have to be innovative to catch peoples interests.&amp;#160; &lt;a href=&quot;http://friendfeed.com&quot;&gt;FriendFeed&lt;/a&gt; came a long at just the right time to catch people with a very solid offering before they were committed to something else.&amp;#160; Anyone else coming into this space really need to take the hints from the current leaders and really &lt;a href=&quot;http://www.phrases.org.uk/meanings/push-the-envelope.html&quot;&gt;push the envelope&lt;/a&gt; to be able to pull users from services they&amp;#39;ve now become attached to.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://strands.com&quot;&gt;Strands&lt;/a&gt; did a very good job of picking up where some of these other services had left off.&amp;#160; Trendwatch, recommendations and a &amp;#39;hot posts&amp;#39; list are all things that most other services are missing.&amp;#160; They also had friend groups before FriendFeed added their &lt;a href=&quot;http://www.readwriteweb.com/archives/friendfeed_beta_interface.php&quot;&gt;lists feature&lt;/a&gt;.&amp;#160; All these features sounded great to me I jumped ship to check it out.&lt;/p&gt;&lt;p&gt;I said earlier that will the competition out there newer life streaming companies need to push he envelope, which Strands has done, but they also need to take the lead from the services that already exist.&amp;#160; This is where Strands dropped the ball.&amp;#160; One of the things everyone raves about with FriendFeed is how simple and streamlined the interface is.&amp;#160; There&amp;#39;s no &lt;a href=&quot;http://en.wikipedia.org/wiki/Clutter&quot;&gt;clutter&lt;/a&gt;, just your content.&amp;#160; This is where I feel Strands misses the target.&lt;/p&gt;&lt;p&gt;Everything in Strands is so bulky.&amp;#160; The graphics are bulky, there&amp;#39;s lots of empty space, about the only thing that isn&amp;#39;t bulky is the content stream, the one thing that should be.&amp;#160; On my homepage I can see two post, that&amp;#39;s it.&amp;#160; What am I looking at other than my content?&amp;#160; Pictures of the people I follow, menus and a whole lot of white space.&amp;#160; A service that is used to view the aggregated data of your friends should really put that content front and center, as much as it can, because at the end of the day that&amp;#39;s why I&amp;#39;m there.&lt;/p&gt;&lt;p&gt;All in all &lt;a href=&quot;http://strands.com&quot;&gt;Strands&lt;/a&gt; did a pretty great job of coming up with some new and interesting features but they need to work on the presentation before it will become useful.&amp;#160; With it&amp;#39;s current design it seems like they&amp;#39;re trying to give all the features and areas of the site the same amount of play, but all features are not made equal.&amp;#160; They need to think about what people are really coming to the site for and put that in the forefront.&amp;#160; &lt;/p&gt;</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>Getting to started</title>
        
        <link href="http://jduff.github.com/2008/09/02/getting-to-started/"/>
        <updated>2008-09-02T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/09/02/getting-to-started</id>
        <content type="html">&lt;p&gt;This is the story of how I finally got around to signing up to a blogging service and getting that first post up there.&amp;nbsp; It isn&#39;t all that exciting; there wasn&#39;t any lighting, an explosion or even a bear attack, but this is my blog and my story so I&#39;m going to tell it.&lt;/p&gt;

&lt;p&gt;About a year ago things finally clicked together that as a software developer I should probably be showcasing my work and what I know, building a brand as it were.&amp;nbsp; It had nothing to do with the &lt;a href=&quot;http://inspired.entrepreneur.com/2007/11/05/how-can-you-build-your-brand-with-a-blog/&quot;&gt;countless&lt;/a&gt; &lt;a href=&quot;http://kalsey.com/2003/06/build_your_brand/&quot;&gt;posts&lt;/a&gt; on &lt;a href=&quot;http://freelanceswitch.com/product-reviews/brand-yourself-a-sponsored-review-of-quicksprout/&quot;&gt;building&lt;/a&gt; your online &lt;a href=&quot;http://www.problogger.net/archives/2007/06/09/how-to-build-your-personal-brand-through-your-blog/&quot;&gt;brand,&lt;/a&gt; it just came to me.&amp;nbsp; I swear.&amp;nbsp; Around this same time I came across a couple of developers talking about how building your blogging engine is a good way to showcase your work and try out new ideas with your development (can&#39;t find any links anymore).&amp;nbsp; This really appealed to me; there&#39;s always something new coming along and work isn&#39;t always the best place to try every shiny thing.&amp;nbsp; So I got started.&amp;nbsp; About a year ago.&lt;/p&gt;

&lt;p&gt;I got going at a fair clip on things, was working with the latest version of Rails (2.0 at that time) which was neat because they&#39;ve added a lot of &lt;a href=&quot;http://railscasts.com/episodes/81&quot;&gt;interesting&lt;/a&gt; &lt;a href=&quot;http://www.slideshare.net/brynary/whats-new-in-rails-2/&quot;&gt;things&lt;/a&gt;, but then life pulled me away.&amp;nbsp; I &lt;a href=&quot;http://www.flickr.com/photos/27269999@N05/2820011262/&quot;&gt;got married&lt;/a&gt;, so a lot of time was spent planning that, we &lt;a href=&quot;http://www.flickr.com/photos/27269999@N05/2737074670/in/photostream/&quot;&gt;bought a house&lt;/a&gt; and we even moved in.&amp;nbsp; It&#39;s been a crazy year.&amp;nbsp; Even with everything going on I&#39;d still try and pull a minute or two away to work on things.&amp;nbsp; I even managed a pretty decent design and logo.&lt;/p&gt;

&lt;center&gt;&lt;img width=&quot;500&quot; height=&quot;298&quot; border=&quot;0&quot; src=&quot;/images/old/design.png&quot; title=&quot;Picture_2&quot; alt=&quot;Picture_2&quot; /&gt;&lt;/center&gt;




&lt;p&gt;Then I read &lt;a href=&quot;http://blog.jayfields.com/2008/08/be-your-start-up.html&quot;&gt;this article&lt;/a&gt; by Jay Fields, someone I really respect within the rails community, on blogging.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Don&#39;t roll your own, you don&#39;t need the maintenance headache.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Hm.&amp;nbsp; Ya, shit, he&#39;s right.&amp;nbsp; It&#39;s been fun playing around with building the blog, but I wasn&#39;t getting anywhere (though I did end up with a 17 message thread in gmail of post ideas).&lt;/p&gt;

&lt;p&gt;With my new direction I did some research and decided on using &lt;a href=&quot;http://www.typepad.com&quot;&gt;Typepad&lt;/a&gt; to host my blog.&amp;nbsp; Now things aren&#39;t quite how I&#39;d like them (I don&#39;t have full control over the html with the plan I got) but hey, at least I&#39;m here.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
    <entry>
        <title>First Post</title>
        
        <link href="http://jduff.github.com/2008/08/29/First-Post/"/>
        <updated>2008-08-29T00:00:00+00:00</updated>
        <id>jduff.github.com:/2008/08/29/First-Post</id>
        <content type="html">&lt;p&gt;So, I&#39;ve finally started blogging, this is something I&#39;ve been wanting to do for almost a year now but work and life have managed to keep me too busy up to now.&amp;nbsp; This is my first post here so It makes sense to tell you a little about who I am and what I&#39;m interested in so you know what you&#39;re getting into by reading this blog.&amp;nbsp; It feels a little strange though, logically I should introduce myself right at the start but right now there&#39;s no one listening so does it really matter?&amp;nbsp; Anyways, hopefully someone will someday go back into the archives and find this introductory post helpful.&lt;/p&gt;

&lt;p&gt;My name is John Duff, I live in Canada&#39;s capital city, Ottawa and work full time as a Software Developer.&amp;nbsp; I graduated Carleton University in 2006 from Software Engineering.&amp;nbsp; I&#39;m currently working with Ruby and Rails for the most part but have done a fair bit of Java, .Net, Javascript and Flex programming as well.&amp;nbsp; At the moment I have a bit of a fixation with FriendFeed and various other Social
Media outlets and am very interested in what is happening with cloud computing. I&#39;m also dabbling in design (photoshop, illustrator,
css) a bit more as well as keeping up with what is happening in the
Ruby community.&lt;/p&gt;
</content>
        <author>
            <name>John</name>
            <uri>http://twitter.com/johnduff</uri>
        </author>
    </entry>
    
</feed>