<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Fightinjoe: Blogs</title><link>http://www.fightinjoe.com/blogs.rss</link><description>Fightinjoe.com: Blogs</description><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/fightinjoe" type="application/rss+xml" /><feedburner:browserFriendly></feedburner:browserFriendly><item><title>Traveling Japan</title><link>http://fightinjoe.com/2007/11/traveling-japan</link><guid>http://fightinjoe.com/2007/11/traveling-japan</guid><description>&lt;p&gt;Want to travel Japan?  Here&amp;#8217;s a broad starting point.&lt;/p&gt;


	&lt;h2&gt;Arriving in Japan + Getting around the regions&lt;/h2&gt;


	&lt;p&gt;There are two major international airports in Japan.  The largest is Narita (NRT), which is outside Tokyo.  The newest is Kansai (KIX) which is on a manmade island in Osaka Bay.&lt;/p&gt;


	&lt;p&gt;The Shinkansen, Japan&amp;#8217;s bullet train, links the major points of interest in Japan, running from north of Tokyo through the capital past Mt. Fuji to Kyoto, Osaka, and further southwest to Hiroshima and points beyond.  Trains run frequently (every 20 minutes or so) but tickets can be as expensive as flying.  &lt;span class="caps"&gt;A JR&lt;/span&gt; Rail Pass is a good value, especially when getting around Tokyo and traveling by Shinkansen.&lt;/p&gt;


	&lt;h3&gt;Kantou / Tokyo / Narita (NRT)&lt;/h3&gt;


	&lt;p&gt;Narita handles almost purely international flights.  Domestic flights for Tokyo are through Haneda.&lt;/p&gt;


	&lt;p&gt;Narita is not in Tokyo; it is in the neighboring prefecture Chiba.  Thus, it takes a bus or train ride to get into Tokyo, which usually lasts an hour or so.  If you&amp;#8217;ve got a transfer to a domestic flight out of Haneda, make sure to budget at least two hours between landing and departing.&lt;/p&gt;


	&lt;h3&gt;Kansai / Osaka / &lt;span class="caps"&gt;KIX&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;Kansai International Airport (KIX) handles international and domestic flights.  The older Osaka airport, Itami, continues to handle some domestic flights as well as short-distance international flights.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;KIX&lt;/span&gt; theoretically serves the whole Kansai region, but is about an hour south of central Osaka, which makes it 2 hours away from Kobe and Kyoto.&lt;/p&gt;


	&lt;p&gt;Kansai is a hodge-podge of different train companies that seem to differ by prefecture (and are useless in Kyoto, which you can get to but can&amp;#8217;t get around by train).  A good map and pocket change is a better way to travel than with a rail pass in Kansai.&lt;/p&gt;


	&lt;h3&gt;Hiroshima and Kyushu&lt;/h3&gt;


	&lt;p&gt;I&amp;#8217;ve never been, but these places aren&amp;#8217;t close to Kyoto or Tokyo.  A few extra days in the capital or cultural center of Japan are worth more than a long round trip and single night in Hiroshima.&lt;/p&gt;


	&lt;h3&gt;Hokkaido and Okinawa&lt;/h3&gt;


	&lt;p&gt;The extreme north and south of Japan are definitely worth the visit, but are journeys in and of themselves.  There are many package deals that tour companies such as &lt;span class="caps"&gt;JTB&lt;/span&gt; sell to both places, which make it easy to get a round trip flight, hotel, and rental car, which you&amp;#8217;ll definitely need to get around both places.&lt;/p&gt;


	&lt;h2&gt;Tokyo&lt;/h2&gt;


	&lt;p&gt;Tokyo is the capital of Japan.  The emperor has a nice spread that&amp;#8217;s semi-off-limits, and the government has a very tall building with a free observation deck.  But what&amp;#8217;s most interesting is at the street level and the distinct microcosms that erupt at each station along the central green loop line (JR Yamanote-sen).  Highlights along the way are:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Ginza&lt;/strong&gt; &amp;#8211; expensive shopping district.  Japan&amp;#8217;s trophy wives congregate here to show off their new Gucci hand bags.  You&amp;#8217;ll notice them because they all have long straight black hair &amp;#8211; a rarity in other parts of Tokyo.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Ueno&lt;/strong&gt; &amp;#8211; there&amp;#8217;s a great park here with cherry blossoms that are gorgeous in the spring time.  There&amp;#8217;s also a zoo and a statue of a samurai walking his dog and museums.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Akihaibara&lt;/strong&gt; &amp;#8211; this is the tech district of Tokyo.  New and old electronics can be found in niche stores.  The Maid Cafes are also interesting sub cultures to visit.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Shinjuku&lt;/strong&gt; &amp;#8211; One of the busiest stations in the world &amp;#8211; it processes over 3 million people a day.  There are two parts to this district, which are literally separated by the train tracks. The west side is home to the tallest buildings in Tokyo, including the aforementioned government twin towers with the free observation deck (you can see Mt. Fuji on a clear day).  The east side is the red light district of Tokyo which is full of cabaret and host clubs, capsule hotels, panty vending machines, and all of the fetish frivolities Japan is stereotyped for.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Harajuku&lt;/strong&gt; &amp;#8211; there is a bridge close to the entrance to the neighboring park where all of the cos-play freakers hang out, especially on Saturday.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Shibuya&lt;/strong&gt; &amp;#8211; the famous crosswalk from Lost In Translation is here, along with some large department stores.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Ropongi&lt;/strong&gt; &amp;#8211; clubbing, clubbing, clubbing, and a giant spider statue outside of the newly completed Ropongi Hills.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Other places that come highly recommended are Asakusa for a traditional feel, the fish market in the morning, the &lt;span class="caps"&gt;NHK&lt;/span&gt; studios, and Studio Ghibli&amp;#8217;s theme park (home of Totoro).&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s easy to spend 3 &amp;#8211; 5 days in Tokyo and not run out of things to do or places to see.  A lot of the charm of Tokyo is getting lost in the city and being surprised by what you find.&lt;/p&gt;


	&lt;h2&gt;Osaka / Kyoto / Kobe / Nara&lt;/h2&gt;


	&lt;p&gt;The only thing that Tokyo doesn&amp;#8217;t have to offer (at least in large quantity) is traditional Japanese culture.  For that, Kansai is the place to be.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Kyoto&lt;/strong&gt; is like Prague &amp;#8211; a very well preserved slice of culture from several hundred years ago.  There are enough temples and shrines and museums and world heritage sites to keep you busy for at least a full week, though two or three nights is probably sufficient.&lt;/p&gt;


	&lt;p&gt;Getting around Kyoto is most easily done on foot or by bicycle.  Just north of Kyoto station is a Muji department store that rents bicycles for a reasonable price.  With a bicycle and a map of the city, you can easily schedule your day by randomly choosing three sights to see and leisurely making your way around to each.  If your random number generator is broken, check out Ginkakuji (the golden temple) and Kiyomizu (the temple up on the hill).  The river that runs through Kyoto has wide banks on either side that are also good for cycling.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Nara&lt;/strong&gt; doesn&amp;#8217;t get much publicity, but Nara Koen (Nara park) is a nice afternoon with it&amp;#8217;s domesticated deer that roam about freely as well as a huge bronze Buddha.  Horyuji temple which is close by is the oldest wooden structure in the world and worth a visit as well.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Osaka&lt;/strong&gt; is good for shopping, but in the end is just another big city.  Spend your time in Tokyo and Kyoto.  If you make it to &lt;strong&gt;Kobe&lt;/strong&gt;, the large population of foreigners makes for good eating, and supposedly the city is good for shoe shopping as well.&lt;/p&gt;


	&lt;h2&gt;Okinawa and Hokkaido&lt;/h2&gt;


	&lt;p&gt;&lt;strong&gt;Okinawa&lt;/strong&gt; is Japan&amp;#8217;s Hawaii, except that the islands were formed from coral, not volcanic activity.  This makes for gorgeous diving and snorkeling, strangely shaped islands, white sand beaches, and poor surfing.  The main island, also called Okinawa, is most beautiful about and hour north of Naha, the capital, in Onnason.  Another 30 minutes further north is Nago, which has a world class aquarium.&lt;/p&gt;


	&lt;p&gt;If time permits, the outlying island are even more rewarding.  Miyako is a flight away, but there are ferries that run between Okinawa and Tonaki and Tokashiki, two smaller outlying islands that offer a unique slice of Okinawa culture, which is an interesting slice of asian influences, the longest life expectancy in the world, an abundance of pork, their own brand of alcohol (awamori), and a quiet seaside lifestyle.&lt;/p&gt;


	&lt;p&gt;Make sure to enjoy a cold mug of Orion beer while in town, Okinawa&amp;#8217;s native beer.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Hokkaido&lt;/strong&gt; is much more of a melting pot, having been colonized by people from all over Japan over 100 years ago.  If you go to Hokkaido, you have to indulge in the onsens there, or natural hot spas.  They come in all sizes: big and small, developed and naturally occurring, one-man baths beside a river, holes you dig yourself in the beach of a lake with volcanic activity below it, seasize baths only accessible at low tide; the list goes on.&lt;/p&gt;


	&lt;p&gt;The seafood in Hokkaido is also the best in all of Japan, with specialties like giant crab and sea urchin (uni).  Enjoy with Sapporo, the local beer that&amp;#8217;s famously exported around the world.&lt;/p&gt;


	&lt;h2&gt;Summary&lt;/h2&gt;


	&lt;p&gt;Here&amp;#8217;s a few recommended schedules for getting around Japan:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;4 days or less &amp;#8211; Just Tokyo should be sufficient.  You&amp;#8217;ll spend at least a day traveling to Kyoto and getting situated, so traveling might not be worth it.&lt;/li&gt;
		&lt;li&gt;7 days or less &amp;#8211; Tokyo and Kyoto should be sufficient; you definitely won&amp;#8217;t be bored, and there will be plenty left over for your next trip to Japan!&lt;/li&gt;
		&lt;li&gt;7 days &amp;#8211; alternately, you could spend this time nicely in Okinawa or Hokkaido for 3 &amp;#8211; 4 nights and the rest of your time in Tokyo.&lt;/li&gt;
		&lt;li&gt;10 days &amp;#8211; Tokyo and Kyoto will be easy.  From Kyoto, you can also take day trips to Nara (highly recommended), Osaka, and Kobe (equally recommended).&lt;/li&gt;
		&lt;li&gt;14 days &amp;#8211; Use your JR rail pass to go everywhere the Shinkansen goes and let the train system show you around Japan.  Ideally, Tokyo through Kyoto on to Hiroshima.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Happy travels!&lt;/p&gt;</description><pubDate>2008-05-25T08:46:47+01:00</pubDate></item><item><title>Scaffolds for free</title><link>http://fightinjoe.com/2008/4/scaffolds-for-free</link><guid>http://fightinjoe.com/2008/4/scaffolds-for-free</guid><description>&lt;p&gt;One of the novel concepts introduced to the mainstream by Ruby on Rails was that of scaffolding.&lt;/p&gt;


	&lt;p&gt;Using as many acronyms as possible, the idea was that to &lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself"&gt;&lt;span class="caps"&gt;DRY&lt;/span&gt;&lt;/a&gt; with &lt;a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete"&gt;&lt;span class="caps"&gt;CRUD&lt;/span&gt;&lt;/a&gt; functionality.  Rails achieved this with the helper method &lt;a href="http://wiki.rubyonrails.org/rails/pages/Scaffold"&gt;#scaffold&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt;, among other web frameworks, realized that specifying &lt;ins&gt;#scaffold&lt;/ins&gt; at the beginning of cookie-cutter controllers isn&amp;#8217;t exactly &lt;span class="caps"&gt;DRY&lt;/span&gt;.  Nor is implementing an authentication and user management system.  Django, for one, offers a nice, modular &lt;a href="http://www.djangobook.com/en/beta/chapter06/"&gt;Admin interface&lt;/a&gt; that can be turned on with a few lines of code.&lt;/p&gt;


	&lt;p&gt;Doing this in Rails isn&amp;#8217;t easy.  &lt;a href="http://rails-engines.org/"&gt;Rails Engines&lt;/a&gt; make it possible, but it&amp;#8217;s still an extra step.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://merbivore.com"&gt;Merb&lt;/a&gt;, on the other hand, does play nice, though not obviously.&lt;/p&gt;


	&lt;p&gt;Building on the &lt;a href="http://fightinjoe.com/2008/4/distributed-mvc"&gt;work I did with distributed &lt;span class="caps"&gt;MVC&lt;/span&gt;&lt;/a&gt;, as well as the &lt;a href="http://github.com/fightinjoe/mex"&gt;proof-of-concept exception logger MeX&lt;/a&gt;, I took a look into creating a Merb Plugin / Gem that will automatically provide scaffolding for free for all models in a Merb app.&lt;/p&gt;


	&lt;h3&gt;Merb AutoScaffold&lt;/h3&gt;


	&lt;p&gt;The result is &lt;a href="http://github.com/fightinjoe/merb-autoscaffold"&gt;Merb AutoScaffold&lt;/a&gt;.  Install the gem, require it in your app, and you&amp;#8217;ll have scaffolding by default.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s the way it works:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Find all of the models&lt;/li&gt;
		&lt;li&gt;For each model, create or extend it&amp;#8217;s controller&lt;/li&gt;
		&lt;li&gt;For each controller, add &lt;span class="caps"&gt;CRUD&lt;/span&gt; actions that don&amp;#8217;t already exist&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;This is pretty straight forward, and made even more simple with some helpful Merb methods.&lt;/p&gt;


	&lt;p&gt;For one, Merb keeps track of load paths with &lt;ins&gt;Merb.dir_for&lt;/ins&gt;.  Also, the Merb::Controller#_template_location makes it easy to hijack where templates are loaded from.&lt;/p&gt;


	&lt;p&gt;The trickiest part with the gem is making sure to give precedence to parts of the application that already exist &amp;#8211; you don&amp;#8217;t want scaffolding to override locally defined methods.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; &amp;#8211; April 27 &amp;#8211; It ends up that it&amp;#8217;s nice to keep the admin interface separate from the regular interface.  Thus, AutoScaffolds have been updated to be namespaced.  So, for example, when AutoScaffolds creates a controller for the Blog model, it will create Scaffold::Blogs &amp;lt; Application so as not to conflict with already existing controllers.  Likewise, this will map to the /scaffolds/blogs path by default, though the route namespace can be configured in init.rb.&lt;/p&gt;


	&lt;p&gt;Right now the gem is at a 0.1.0 release.  It could look a lot prettier, have better support for ID and Date fields, and ideally will have support for associations in the future.  But for the time being, it&amp;#8217;s as pretty at &lt;ins&gt;merb-gen resource&lt;/ins&gt;&amp;#8217;s scaffolds, and gets the job done.  Who could ask for more?&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;&lt;/strong&gt; &amp;#8211; April 27th &amp;#8211; 0.1.2 has just been released, bringing with it support for associations, merbivore.com-type styling, namespacing, and pagination (in edge). Once tests are complete, version 0.2 should be ready for release as a full-fledged gem!&lt;/p&gt;</description><pubDate>2008-04-25T08:32:08+01:00</pubDate></item><item><title>Distributed MVC</title><link>http://fightinjoe.com/2008/4/distributed-mvc</link><guid>http://fightinjoe.com/2008/4/distributed-mvc</guid><description>&lt;p&gt;&lt;a href="http://www.rubyonrails.com"&gt;Rails&lt;/a&gt; literally interprets the &lt;span class="caps"&gt;MVC&lt;/span&gt; structure in the /app directory with the &lt;tt&gt;models&lt;/tt&gt;, &lt;tt&gt;views&lt;/tt&gt;, and &lt;tt&gt;controllers&lt;/tt&gt; directories.  These directories are essential to how Rails runs, as it eschews configuration for the context that these directories and their files provide.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.merbivore.com"&gt;Merb&lt;/a&gt; follows suit; all default Merb apps respect the &lt;span class="caps"&gt;MVC&lt;/span&gt; structure Rails pioneered.  But Merb allows the defaults to be overwritten, allowing for open interpretation of &lt;span class="caps"&gt;MVC&lt;/span&gt;&amp;#8217;s physical structure.&lt;/p&gt;


	&lt;p&gt;&lt;tt&gt;merb-gen app&lt;/tt&gt; supports the default, flat, and very-flat app generation.  And in the &lt;tt&gt;init.rb&lt;/tt&gt; file, a custom directory structure can be setup; see the &lt;a href="http://github.com/wycats/merb-core/tree/master/lib/merb-core/bootloader.rb"&gt;inline docs on the bootloader&lt;/a&gt;, line 144, for more details.&lt;/p&gt;


	&lt;p&gt;But what if static customization of the &lt;span class="caps"&gt;MVC&lt;/span&gt; structure isn&amp;#8217;t enough?  What if you need dynamic customization?&lt;/p&gt;


	&lt;h2&gt;Customizing custom&lt;/h2&gt;


	&lt;p&gt;Encapsulated functionality is a perfect example of why the &lt;span class="caps"&gt;MVC&lt;/span&gt; file structure needs might need to be customized.  What if you want the same functionality in multiple applications?  Authentication, for example?  There is a &lt;a href="http://hassox.blogspot.com/2008/02/merbful-authentication-initial-merb-09.html"&gt;great generator&lt;/a&gt; that will solve this problem.  But what if you want a self-contained gem you can use in any application with only one &amp;#8216;dependency&amp;#8217; line?&lt;/p&gt;


	&lt;p&gt;The Rails answer to this is to use &lt;a href="http://rails-engines.org/"&gt;Engines&lt;/a&gt; &amp;#8211; a plugin that extends Rails to make it easy for plugins to access and extend Rails&amp;#8217; &lt;span class="caps"&gt;MVC&lt;/span&gt; setup.&lt;/p&gt;


	&lt;p&gt;So where are Engines for Merb?  They&amp;#8217;re included in &lt;tt&gt;merb-core&lt;/tt&gt; for free!&lt;/p&gt;


	&lt;p&gt;Engines basically gives the ability to register new models, controllers, views, and routes.  How is this done in Merb?&lt;/p&gt;


	&lt;h2&gt;Merb Controllers&lt;/h2&gt;


	&lt;p&gt;When Merb needs a controller, it doesn&amp;#8217;t look in a direction &amp;#8211; it looks at Merb::Controller, the class from which all controllers must be descendants. And the reason why they must be descendants?  Because inheritance is how Merb tracks the controllers.&lt;/p&gt;


	&lt;p&gt;On line 25 of &lt;a href="http://github.com/wycats/merb-core/tree/master/lib/merb-core/controller/merb_controller.rb"&gt;merb_controller.rb&lt;/a&gt;
there is this neat little trick:&lt;/p&gt;


	&lt;p&gt;&lt;pre style="overflow: hidden;"&gt;&lt;code class="line_number" style="float: left; margin-right: 1em"&gt;1
2
3
4
5&lt;/code&gt;&lt;code&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;inherited&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;klass&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="ident"&gt;_subclasses&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="ident"&gt;klass&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;_template_root&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dir_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:view&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;_template_root&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;super&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;


	&lt;p&gt;When Merb is started, all of the controllers are loaded, and as each one is loaded, it&amp;#8217;s class name is saved in the class accessor &lt;tt&gt;_subclasses&lt;/tt&gt;.  Then, when a request is &lt;a href="http://github.com/wycats/merb-core/tree/master/lib/merb-core/dispatch/dispatcher.rb"&gt;dispatched&lt;/a&gt; (line 51), the requested controller is looked up in the same array.&lt;/p&gt;


	&lt;p&gt;So how does one add a dynamic controller to Merb?  By loading a class that inherits from Merb::Controller.  This is as simple as &lt;tt&gt;require &amp;#8216;myController&amp;#8217;&lt;/tt&gt;.&lt;/p&gt;


	&lt;h2&gt;Merb Views&lt;/h2&gt;


	&lt;p&gt;Merb views are handled in a unique way &amp;#8211; when Merb is started, all views are compiled into methods on their respective controller.  So adding new views takes more than just specifying a new file to look for.&lt;/p&gt;


	&lt;p&gt;Merb::Controller uses the instance method &lt;tt&gt;_template_location&lt;/tt&gt; to resolve which views to load.  Override this method in a controller and view path can be specified.  For example, this is how a flat Merb app specifies a custom view folder:&lt;/p&gt;


	&lt;p&gt;&lt;pre style="overflow: hidden;"&gt;&lt;code class="line_number" style="float: left; margin-right: 1em"&gt;1
2
3&lt;/code&gt;&lt;code&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;_template_location&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;controller&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;controller_name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="ident"&gt;controller&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;layout&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;layout.&lt;span class="expr"&gt;#{action}&lt;/span&gt;.&lt;span class="expr"&gt;#{type}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{action}&lt;/span&gt;.&lt;span class="expr"&gt;#{type}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;


	&lt;p&gt;The only &amp;#8216;gotcha&amp;#8217; here is that &lt;ins&gt;_template_location&lt;/ins&gt; is scoped to the view directory.  To get around this, one only needs to engineer a way to back out of the directory:&lt;/p&gt;


	&lt;p&gt;&lt;pre style="overflow: hidden;"&gt;&lt;code class="line_number" style="float: left; margin-right: 1em"&gt;1
2
3
4
5
6&lt;/code&gt;&lt;code&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;_template_location&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;controller&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;controller_name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="ident"&gt;undo&lt;/span&gt;   &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load_paths&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:view&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;first&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(%r{&lt;/span&gt;&lt;span class="regex"&gt;[^/]+&lt;/span&gt;&lt;span class="punct"&gt;},&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;..&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="ident"&gt;prefix&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="ident"&gt;file&lt;/span&gt;   &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;controller&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;layout&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;layout.&lt;span class="expr"&gt;#{action}&lt;/span&gt;.&lt;span class="expr"&gt;#{type}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{action}&lt;/span&gt;.&lt;span class="expr"&gt;#{type}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;.&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;undo&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;prefix&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;views&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;file&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;


	&lt;p&gt;The above code changes the view directory to be relative to the current file, not the pre-specified &lt;ins&gt;view&lt;/ins&gt; root.&lt;/p&gt;


	&lt;h2&gt;Merb models&lt;/h2&gt;


	&lt;p&gt;Models in Merb are treated like any regular library.  Just as with controllers, if a model has been loaded, Merb will have access to it.&lt;/p&gt;


	&lt;h2&gt;Merb routes&lt;/h2&gt;


	&lt;p&gt;Merb routes can be extended at any time with Merb::Router.append and Merb::Router.prepend:&lt;/p&gt;


	&lt;p&gt;&lt;pre style="overflow: hidden;"&gt;&lt;code class="line_number" style="float: left; margin-right: 1em"&gt;1
2
3
4
5&lt;/code&gt;&lt;code&gt;&lt;span class="constant"&gt;Merb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Router&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;prepend&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/&lt;/span&gt;&lt;span class="punct"&gt;').&lt;/span&gt;&lt;span class="ident"&gt;to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;blogs&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;'&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;resources&lt;/span&gt; &lt;span class="symbol"&gt;:axes&lt;/span&gt;
&lt;span class="comment"&gt;#  r.default_routes&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;


	&lt;p&gt;Make sure not to call Merb::Router.prepare as it will destroy all previously created routes.&lt;/p&gt;


	&lt;h2&gt;Putting it all together&lt;/h2&gt;


	&lt;p&gt;Knowing how to load all of the pieces, it&amp;#8217;s an easy step to encapsulate everything together into a Merb gem.  Using &lt;ins&gt;merb-gen plugin myGem&lt;/ins&gt; to create the framework for packing together your funcationality, toss your files into the lib directory and set the gem to properly include your files and set your roots when included.&lt;/p&gt;


	&lt;p&gt;For an example of how it all fits together, &lt;a href="http://github.com/fightinjoe/mex"&gt;take a look at MeX&lt;/a&gt;, a Gem that provides plug-and-play exception logging to any Merb app.&lt;/p&gt;</description><pubDate>2008-04-18T15:51:24+01:00</pubDate></item><item><title>Apples and Oranges</title><link>http://fightinjoe.com/2008/4/apples-and-oranges</link><guid>http://fightinjoe.com/2008/4/apples-and-oranges</guid><description>&lt;p&gt;Never stop learning, or so they say.  With the cost of a post-graduate degree or returning for a higher education, they might as well say &amp;#8220;never stop paying for student loans.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;When schooling was public, learning was easy.  Once graduated, it doesn&amp;#8217;t come so easy.  First, it requires a proactive attitude.  Next, it requires some discrimination to find good teachers; i.e. &lt;span class="caps"&gt;CNN&lt;/span&gt; and Fox News aren&amp;#8217;t exactly ideal teachers.  Finally, it requires a lot of patience.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve been trying to pick up a few new skills recently, most of which run parallel to my line of work &amp;#8211; web app development.  The problem is that while I have a generic knowledge base regarding programming, on top of that I have very specific knowledge of my preferred &lt;a href="http://www.ruby-lang.org/"&gt;programming language&lt;/a&gt; and &lt;a href="http://www.rubyonrails.com"&gt;web framework&lt;/a&gt;.  When shifting to a different language or framework, I don&amp;#8217;t need to rebuild my base &amp;#8211; I just need to translate my specific knowledge.&lt;/p&gt;


	&lt;p&gt;Learning many things is like this.  If experience is the best teacher, being able to relate new knowledge to previous experience has to be a second-best option.  In this vein, I&amp;#8217;m trying something new &amp;#8211; I&amp;#8217;m trying to collect knowledge I have, and then as I learn new things, I want to what I know into what I learned.&lt;/p&gt;


	&lt;p&gt;Thus, I&amp;#8217;ve spawned &lt;a href="http://vs.fightinjoe.com"&gt;Vs.&lt;/a&gt;, a web app that is supposed to make comparisons easy.  It&amp;#8217;s still a work in progress, but it&amp;#8217;s given me quite a few opportunities to play with different design ideas, new programming tools and techniques, and unique attitudes towards learning.&lt;/p&gt;


	&lt;p&gt;Right now the site is clearly only serving one person &amp;#8211; myself.  It&amp;#8217;s available for public viewing, but closed for contribution.  My hope is that I can open it up in the near future for anyone to use.&lt;/p&gt;


	&lt;p&gt;It would be cool to use the site for things like comparing languages, or even dialects of the same language; for comparing products, foods, recipes; for comparing theories, philosophies, etc.&lt;/p&gt;


	&lt;p&gt;So with that goal in mind, what do you want to compare?  Is the project worthwhile?  Can this be a better way to learn, or just another silly web app?&lt;/p&gt;</description><pubDate>2008-04-13T14:18:39+01:00</pubDate></item><item><title>Projects</title><link>http://fightinjoe.com/2008/4/projects</link><guid>http://fightinjoe.com/2008/4/projects</guid><description>&lt;p&gt;The following are a few projects that I&amp;#8217;ve developed:&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://fightinjoe.com"&gt;Fightinjoe.com&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;If you&amp;#8217;re reading this, you&amp;#8217;ve already seen this project.  A &lt;a href="http://nubyonrails.com/articles/about-this-blog-memcached"&gt;wise man&lt;/a&gt; once said, &amp;#8220;every beginning Rails developer should
write their own blog software.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;This is my attempt at doing things differently; it is not only my first &lt;a href="http://merbivore.com"&gt;Merb&lt;/a&gt; project, but it is also my first &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; + &lt;a href="http://datamapper.org"&gt;DataMapper&lt;/a&gt; + &lt;a href="http://postgresql.org"&gt;PostgreSQL&lt;/a&gt; + &lt;a href="http://rubyhitsquad.com/Vlad_the_Deployer.html"&gt;Vlad&lt;/a&gt; project.&lt;/p&gt;


	&lt;p&gt;This project is &lt;a href="http://github.com/fightinjoe/fightinjoe-merb-blog/tree"&gt;open-sourced at GitHub&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://vs.fightinjoe.com"&gt;Vs.&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;My first Merb project quickly spun off two additional projects.  With a large knowledge of &amp;#8220;Ruby on Rails&amp;#8221;http://rubyonrails.com and the mainstream stack it utilizes, I knew what I needed to do to build my first Merb blog.  What I didn&amp;#8217;t know was how.&lt;/p&gt;


	&lt;p&gt;I didn&amp;#8217;t need a Merb tutorial, I needed a Rails-to-Merb translator.  I couldn&amp;#8217;tfind one, so I built one.&lt;/p&gt;


	&lt;p&gt;The goal: expedite the translation of knowledge between two subjects in the same discipline. In other words, make it easier than ever to reinvent the wheel.&lt;/p&gt;


	&lt;p&gt;Right now in version 0.1 it is closed source and closed to outside contributors.  My goal is to change this in upcoming releases.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://fightinjoe.com/2008/4/scaffolds-for-free"&gt;Merb AutoScaffold&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;I woke up this morning with a bright idea &amp;#8211; make scaffolding easy and automatic for any Merb app via a simple Gem.  6 hours later merb_autoscaffold was up and running locally providing all the functionality that Rails scaffolds have to offer.&lt;/p&gt;


	&lt;p&gt;The goal is to grow this not just into a robust scaffolding solution, but also to have it work together with MeX as a proof-of-concept of how easy it is to compartmentalize and distribute functionality in Merb.&lt;/p&gt;


	&lt;p&gt;Fork and contribute to &lt;a href="https://github.com/fightinjoe/merb-autoscaffold/tree"&gt;Merb AutoScaffolding on GitHub&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://github.com/fightinjoe/mex"&gt;MeX&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;My first Merb project also necessitated an exception tracker.  But with all of these new projects springing up, I was torn between developing a plugin that could be dropped into any app, or a centralized web service that any app could talk to.&lt;/p&gt;


	&lt;p&gt;I decided on the latter and used it as an excuse to create my first flat Merb app: MeX (Merb eXception).&lt;/p&gt;


	&lt;p&gt;Drawing heavily on the &lt;a href="http://github.com/defunkt/exception_logger/tree/master"&gt;exception_logger&lt;/a&gt; Rails plugin, MeX has been rewritten to work with Merb, DataMapper, and jQuery.&lt;/p&gt;


	&lt;p&gt;Version 0.1.0 is out now, which provides the same functionality that exception logger provides, except in a stand-alone form.  Future versions will add authentication as well as the ability to use the app as a plugin inside of a Merb app or as a Ruby Gem for easy deployment!&lt;/p&gt;


	&lt;p&gt;The project is &lt;a href="http://github.com/fightinjoe/mex"&gt;open-sourced on GitHub&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://www.tribewanted.com"&gt;Tribewanted.com&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;I&amp;#8217;ve also had the pleasure of working for Tribewanted to redesign and re-engineer their web presence.  The experience was one-of-a-kind, with me spending three months with the project on an island in Fiji with no electricity or running water.&lt;/p&gt;


	&lt;p&gt;I never thought my commute to work would be a 30 minute boat ride across the ocean and up a river to a small sugar plantation town.  Working locally with Tribewanted, however, was a huge benefit for being involved with the community, and has made my continued remote work that much more productive.&lt;/p&gt;


	&lt;h3&gt;&lt;a href="http://kinzin.com"&gt;Kinzin.com&lt;/a&gt;&lt;/h3&gt;


	&lt;p&gt;Kinzin is a place online for families &amp;#8211; a safe harbor for sharing stories and pictures and staying in touch.  While I haven&amp;#8217;t been involved in the recent iterations of Kinzin, I was responsible for the first alpha release and helped with the development of the subsequent two beta releases.&lt;/p&gt;


	&lt;p&gt;With Kinzin, I had the pleasure to work with a sharp and specialized team, which was a great opportunity for me to forego being a jack of all trades and focus on being a master of one.  I was responsible not only for much of the engineering of the internals of the site, but also for several plugins and Rails extensions we developed internally to aid development, testing, and general usage.&lt;/p&gt;</description><pubDate>2008-04-13T13:58:57+01:00</pubDate></item><item><title>Aaron Wheeler</title><link>http://fightinjoe.com/2008/4/aaron-wheeler</link><guid>http://fightinjoe.com/2008/4/aaron-wheeler</guid><description>&lt;p&gt;I&amp;#8217;m a &lt;a href="http://www.workingwithrails.com/person/7482-aaron-wheeler"&gt;freelance web application developer&lt;/a&gt; with almost 10 years of experience.  I have a math and computer science background and currently live in Japan.&lt;/p&gt;


	&lt;p&gt;My main interest is in creative forms of communication.  I use this interest as an excuse to pursue my programming career, arts and crafts pastimes, &lt;a href="http://flickr.com/photos/fightinjoe"&gt;photography money-sink&lt;/a&gt;, and world travels.  When I&amp;#8217;m all out of excuses, I like playing &lt;a href="http://throwlife.com/"&gt;Ultimate Frisbee&lt;/a&gt;, cycling, and &lt;a href="http://www.opensourcefood.com/people/fightinjoe/"&gt;cooking&lt;/a&gt; (when my &lt;a href="http://masayowheeler.com"&gt;wife&lt;/a&gt; lets me).&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.linkedin.com/in/fightinjoe" &gt;&lt;img src="http://www.linkedin.com/img/webpromo/btn_viewmy_160x33.gif" width="160" height="33" border="0" alt="View Aaron Wheeler's profile on LinkedIn"&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>2008-04-13T13:27:29+01:00</pubDate></item><item><title>Changing RESTful URL mappings</title><link>http://fightinjoe.com/2008/3/changing-restful-url-mappings</link><guid>http://fightinjoe.com/2008/3/changing-restful-url-mappings</guid><description>&lt;p&gt;&lt;span class="caps"&gt;REST&lt;/span&gt; is a style of representing web resources.  Rails has popularized the RESTful style, interpreting it into a full set of url patterns and request methods.  These patterns have become convention.  I&amp;#8217;ve got a problem with these conventions.&lt;/p&gt;


	&lt;p&gt;My issue is when problems arrive when creating or updating a resource.  Consider the following scenario for creating a new comment:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;GET&lt;/span&gt;: /comment/new&lt;/strong&gt; is opened, displaying the form for creating a comment&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;&lt;span class="caps"&gt;POST&lt;/span&gt;: /comment&lt;/strong&gt; is called when the empty form is accidentally submitted&lt;/li&gt;
		&lt;li&gt;The comment is not saved because of a validation error, but&amp;#8230;&lt;/li&gt;
		&lt;li&gt;the request is not redirected because the error information would be lost, so&amp;#8230;&lt;/li&gt;
		&lt;li&gt;the &lt;strong&gt;comment/new&lt;/strong&gt; view is rendered, but the url is &lt;strong&gt;/comment&lt;/strong&gt;&lt;/li&gt;
		&lt;li&gt;Should the page be manually refreshed, a different page will display&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;In this situation, the view corresponds to the action, but the &lt;span class="caps"&gt;URL&lt;/span&gt; doesn&amp;#8217;t.&lt;/p&gt;


	&lt;p&gt;It would be better, instead if:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;The &lt;strong&gt;&lt;span class="caps"&gt;CREATE&lt;/span&gt;&lt;/strong&gt; action mapped to the &lt;strong&gt;&lt;span class="caps"&gt;POST&lt;/span&gt;: resource/new&lt;/strong&gt; method/url pattern.&lt;/li&gt;
		&lt;li&gt;The &lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;&lt;/strong&gt; action mapped to the &lt;strong&gt;&lt;span class="caps"&gt;PUT&lt;/span&gt;: resource/&lt;em&gt;id&lt;/em&gt;/edit&lt;/strong&gt; method/url pattern.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;The cool thing is, if you&amp;#8217;re using Merb, it&amp;#8217;s easy to disagree.  But first it&amp;#8217;s good to know about Merb&amp;#8217;s routing.&lt;/p&gt;


	&lt;p&gt;Merb&amp;#8217;s routing is Rails-inspired, so much of it will appear the same, especially regarding RESTful resources:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Merb supports namespaces&lt;/li&gt;
		&lt;li&gt;Merb supports both &lt;a href="http://merbivore.com/documentation/merb-core/0.9.1/index.html?a=M000758&amp;#38;name=resource"&gt;#resource&lt;/a&gt; and &lt;a href="http://merbivore.com/documentation/merb-core/0.9.1/index.html?a=M000757&amp;#38;name=resources"&gt;#resources&lt;/a&gt;, for specifying either singleton or collection resource&lt;/li&gt;
		&lt;li&gt;Merb&amp;#8217;s names routes in the same way as Rails (though they&amp;#8217;re exposed through the &lt;a href="http://merbivore.com/documentation/merb-core/0.9.1/index.html?a=M000646&amp;#38;name=url"&gt;#url&lt;/a&gt; method instead of as magic methods)&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;For specific examples, sometimes it&amp;#8217;s quicker to &lt;a href="http://github.com/wycats/merb-core/tree/master/lib/merb-core/dispatch/router/behavior.rb"&gt;browse the codebase&lt;/a&gt; than it is to troll through the docs.&lt;/p&gt;


	&lt;p&gt;Merb&amp;#8217;s routing code is different from Rails, though, in that there is much less magic happening.  That makes it easy to change the way it behaves in order to customize the RESTful &lt;span class="caps"&gt;URL&lt;/span&gt; mappings.&lt;/p&gt;


	&lt;p&gt;The mappings are in &lt;a href="http://github.com/wycats/merb-core/tree/master/lib/merb-core/dispatch/router/behavior.rb"&gt;merb-core/lib/merb-core/dispatch/router/behavior.rb&lt;/a&gt; and are a simple set of regular expressions.  Adding the alternate behavior described above is as easy as swapping a few regular expressions:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
Behavior.new({ :path =&amp;gt; %r[^/?(.:format)?$],     :method =&amp;gt; :post },   { :action =&amp;gt; "create" },  parent),
#...
Behavior.new({ :path =&amp;gt; %r[^/:id(.:format)?$],   :method =&amp;gt; :put },    { :action =&amp;gt; "update" },  parent),
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;... becomes &amp;#8230;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
Behavior.new({ :path =&amp;gt; %r[^/new(.:format)?$],         :method =&amp;gt; :post },   { :action =&amp;gt; "create" },  parent),
# ...
Behavior.new({ :path =&amp;gt; %r[^/:id[;/]edit(.:format)?$], :method =&amp;gt; :put },    { :action =&amp;gt; "update" },  parent),
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Extract these changes into a &lt;a href="http://pastie.caboo.se/private/d9uothverwor0jjyk0oweg"&gt;separate file&lt;/a&gt; and then include them in init.rb to override Merb&amp;#8217;s default behavior.  Easy!&lt;/p&gt;


	&lt;p&gt;Resources:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href="http://www.xfront.com/REST-Web-Services.html"&gt;Building Web Services the &lt;span class="caps"&gt;REST&lt;/span&gt; Way&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Inspiration from an old discussion with &lt;a href="http://www.prescod.net"&gt;Paul Prescod&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;</description><pubDate>2008-03-24T11:55:36+00:00</pubDate></item><item><title>Parts, Builder, and Caching</title><link>http://fightinjoe.com/2008/3/parts-builder-and-caching</link><guid>http://fightinjoe.com/2008/3/parts-builder-and-caching</guid><description>&lt;p&gt;&lt;a href="http://www.rubyonrails.com"&gt;Rails&lt;/a&gt; is clever.  &lt;a href="http://www.merbivore.com"&gt;Merb&lt;/a&gt; is smart.&lt;/p&gt;


	&lt;p&gt;Case in point: Components / Cells / Parts.  The goal: to be able to extract generic view code for ease of use across the whole application.  This doesn&amp;#8217;t work well in Rails; &lt;a href="http://mikepence.wordpress.com/2008/03/16/cells-bring-clean-re-use-to-your-rails-views/"&gt;Mike on Tech explains why here.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;The solution in Rails to this problem is clever: using the &lt;a href="http://rails-engines.org/"&gt;Engines plugin&lt;/a&gt; (which hack Rails to make it easy to specify controller, view, and model code in a plugin), extend Rails to support &lt;a href="http://cells.rubyforge.org/"&gt;cells&lt;/a&gt; in an efficient manner.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;&lt;/strong&gt; Looks like Cells no longer has the &lt;a href="http://mikepence.wordpress.com/2008/03/22/removing-the-engines-dependency-from-cells/"&gt;Engines dependency&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The solution in Merb is smart: build the framework from the beginning to support components (called Parts).&lt;/p&gt;


	&lt;h3&gt;Parts&lt;/h3&gt;


	&lt;p&gt;From the &lt;a href="http://github.com/wycats/merb-more/tree/master/merb-parts/lib/merb-parts/part_controller.rb"&gt;source&lt;/a&gt; :&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# A Merb::PartController is a light weight way to share logic and templates
# amongst controllers.  
# Merb::PartControllers work just like Merb::controller.  
# There is a filter stack, layouts (if needed) all the render functions,
# and url generation.  
#
# Cookies, params, and even the request object are shared with the web controller
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;To start using Parts in Merb, generate a new Parts controller&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
$ merb-gen part_controller generic
# =&amp;gt; exists  app
# =&amp;gt; exists  app/helpers
# =&amp;gt; exists  app/parts
# =&amp;gt; exists  app/parts/views
# =&amp;gt; create  app/parts/views/generic_part
# =&amp;gt; create  app/helpers/generic_part_helper.rb
# =&amp;gt; create  app/parts/generic_part.rb
# =&amp;gt; create  app/parts/views/generic_part/index.html.erb
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;To enable parts, include merb-parts as a dependancy in config/init.rb.  Make sure that the merb-parts gem is installed (it&amp;#8217;s installed with merb-more).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# config/init.rb
dependency( "merb-parts")
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Each part will correspond to an action in a part controller.  To create a menu part:&lt;/p&gt;


	&lt;p&gt;Add the #menu action to app/parts/generic_part.rb&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# app/parts/generic_part.rb
def menu
  render
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Create the menu part view&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# app/parts/views/generic_part/menu.html.erb
&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;&amp;lt;a href="http://www.google.com"&amp;gt;Google&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;% params[:menu_items].each do |name, link| %&amp;gt;
    &amp;lt;li&amp;gt;&amp;lt;a href="&amp;lt;%= link %&amp;gt;"&amp;gt;&amp;lt;%= name %&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Reference the part in your regular controller views.  Any additional hash values are included in the params hash available to part controller actions.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# app/views/blogs/index.html.erb
...
&amp;lt;%= part( GenericPart =&amp;gt; :menu, :menu_items =&amp;gt; { :yahoo =&amp;gt; 'http://www.yahoo.com' } ) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Builder&lt;/h3&gt;


	&lt;p&gt;Builder is the same as XmlBuilder in Rails.  It is a templating engine that makes it easy to write &lt;span class="caps"&gt;XML&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;In Rails, access to the XmlBuilder object is made available to templates ending in .rxml.  In Merb, this is how make a Builder template:&lt;/p&gt;


	&lt;p&gt;Inlude merb-builder as a dependency in config/init.rb.  Make sure that the merb-builder gem is installed (it&amp;#8217;s installed with merb-more).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# config/init.rb
dependency( "merb-buidler" )
&lt;/code&gt;&lt;/pre&gt;
Create your template with the .builder suffix.  This template will have access to the xml object used by Builder.

&lt;pre&gt;&lt;code&gt;
# app/views/blogs/index.xml.builder
xml.posts do
  for post in @posts
    xml.post do
      xml.id post.id
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Caching&lt;/h3&gt;


	&lt;p&gt;Caching is similarly turned on in Merb.  Merb supports page, action, fragment, and object caching.  Merb also supports the following cache stores: Database (ActiveRecord, DataMapper, and Sequel support), filesystem, memory, and memcache.&lt;/p&gt;


	&lt;p&gt;The &lt;a href="http://github.com/wycats/merb-more/tree/master/merb-cache"&gt;merb-cache Readme&lt;/a&gt; has examples for cache usage and configuration.&lt;/p&gt;


	&lt;p&gt;One gotcha is that at the time of this writing, disabling caching does not turn off page caching.  To enable turning off the page cache, see &lt;a href="http://github.com/fightinjoe/merb-more/commit/feaed59155bc9d762176914802284a46a0cf50db"&gt;this fix.&lt;/a&gt;&lt;/p&gt;</description><pubDate>2008-03-23T07:05:53+00:00</pubDate></item><item><title>Internet in New Zealand</title><link>http://fightinjoe.com/2007/12/internet-in-new-zealand</link><guid>http://fightinjoe.com/2007/12/internet-in-new-zealand</guid><description>&lt;p&gt;What&amp;#8217;s not to love about New Zealand? The internet.  Capped bandwidth, slow speeds, expensive fees, no naked &lt;span class="caps"&gt;DSL&lt;/span&gt;, an a lack of wifi hotspots are all examples of why telecom monopolies are bad things.  Don&amp;#8217;t get me started on Telecom&amp;#8217;s current puppet ad campaign.&lt;/p&gt;


	&lt;p&gt;The most affordable short-term internet connection option in New Zealand is also the most versatile.  Vodafone&amp;#8217;s &amp;#8220;Vodem&amp;#8221; device and service provides a broadband internet connection via their 3G network.  When in the country, the device &amp;#8220;seamlessly&amp;#8221; downgrades to the nation-wide &lt;span class="caps"&gt;GPRS&lt;/span&gt; network to keep you connected.&lt;/p&gt;


	&lt;p&gt;With a Vodem purchased off of TradeMe and a subscription-free contract, we can surf 6 gigs worth of the net per month for a mere $90 &lt;span class="caps"&gt;NZD&lt;/span&gt;.  And this is our cheapest option (for three 3 months, including the installation and disconnect fees of the other options).&lt;/p&gt;


	&lt;p&gt;Traveling all around the north island, we haven&amp;#8217;t had any geographical issues with the Vodem.  In the cities, 3G works well and in the country, &lt;span class="caps"&gt;GPRS&lt;/span&gt; is slow but gets the job done.  The main issue we&amp;#8217;ve had is dropped connections to the network.&lt;/p&gt;


	&lt;p&gt;Typically, we&amp;#8217;re able to authenticate and get online within 15 &amp;#8211; 20 seconds of plugging in the Vodem to one of our Mac notebooks.  Pinging a server like google.com gives us an average of a 300ms response, with about 1 &amp;#8211; 2% of the packets dropped.  This is good enough to make &lt;span class="caps"&gt;VOIP&lt;/span&gt; calls to the States and work within &lt;span class="caps"&gt;SSH&lt;/span&gt; tunnels to remote servers, not to mention read email, update blogs, and surf the web.&lt;/p&gt;


	&lt;p&gt;What will happen without warning, however, is that responses from the network will disappear.  We&amp;#8217;ll notice that web pages aren&amp;#8217;t loading.  From a terminal window, pings to our favorite domains don&amp;#8217;t even hit the &lt;span class="caps"&gt;DNS&lt;/span&gt; server.  The Vodem thinks it is still connected, but there is no response.  Manually disconnecting and reconnecting the Vodem usually solves the problem, but can be a hassle when in the middle of a phone call or a download.&lt;/p&gt;


	&lt;p&gt;There aren&amp;#8217;t many documents online helping to troubleshoot this issue.  Vodafone solution support team (0800-921-021), however, has been very helpful.  This morning they said that this sounded like a typical issue other customers have been having, and they suggested that I change the &lt;span class="caps"&gt;APN&lt;/span&gt; (access point name) from &amp;#8216;www.vodafone.net.nz&amp;#8217; to &amp;#8216;internet&amp;#8217;.&lt;/p&gt;


	&lt;p&gt;Changing this on a Mac running Tiger (OS &lt;span class="caps"&gt;X 10&lt;/span&gt;.4.10) isn&amp;#8217;t straightforward but can be done.  Vodafone support said that in the Device Manager, there would be an option section and an &lt;span class="caps"&gt;APN&lt;/span&gt; tab where this value could be changed.  I couldn&amp;#8217;t find the Device Manager, so instead, inspired by a &lt;a href="http://the.taoofmac.com/space/HOWTO/Setup%20GPRS/UMTS%20Access%20on%20a%20Mac"&gt;Tao of Mac&lt;/a&gt; article, I hacked the configs myself.&lt;/p&gt;


	&lt;p&gt;The Vodem, when installed, installs a modem script that Internet Connect uses to dail into Vodafone&amp;#8217;s network.  This file is:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;/Library/Modem Scripts/MMHS Modem&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Opening the file, line 87 has the string string we&amp;#8217;re looking to change.  Change line 87 to look like this:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;! write "AT+CGDCONT=1,*IP*,*www.vodafone.net.nz*,,0,0*" 
write "AT+CGDCONT=1,*IP*,*internet*,,0,0*"&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;That exclamation mark comments out the old line, and then below that we the &amp;#8216;internet&amp;#8217; value.&lt;/p&gt;


	&lt;p&gt;This is my first time every dealing with modem scripts.  My hack was led more by my deductive reasoning skills than any advanced knowledge I have on the subject.  Additionally, I&amp;#8217;ve only so far tested this fix with a 30 minute &lt;span class="caps"&gt;VOIP&lt;/span&gt; call.  But all seems to be well.  Initially my ping response time was ~360ms, but now is around ~320ms, with the dropped rate remaining about the same.  Here&amp;#8217;s hoping the fix lasts more than 30 minutes!&lt;/p&gt;</description><pubDate>2007-12-04T12:56:40+00:00</pubDate></item><item><title>What did I do?</title><link>http://fightinjoe.com/2007/10/what-did-i-do</link><guid>http://fightinjoe.com/2007/10/what-did-i-do</guid><description>&lt;p&gt;Before heading to Fiji to work with &lt;a href="http://www.tribewanted.com"&gt;Tribewanted&lt;/a&gt;, I got a lot of questions, the main one being &amp;#8220;WHAT? ! ? !&amp;#8221;  After the dust settled from my original announcement, however, the questions became a bit more articulate. &amp;#8220;Where will you be?&amp;#8221;  &amp;#8220;How long will you be there?&amp;#8221;  &amp;#8220;What will you be doing?&amp;#8221;  &amp;#8220;Yeah, but what will you be doing?&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Before departing it was difficult to correctly answer the last question.  Often, when people asked what I&amp;#8217;d be doing, I&amp;#8217;d describe typical IT work and how it usually maroons professionals in an island chain of cubicles, each it&amp;#8217;s own private island.  So if I was building websites and changing the face of the internet, it didn&amp;#8217;t much matter whether I was on a virtual island or a real one.  Some pointed out that the lack of power and an internet connection might make a difference.  I agreed, but tried not to focus on these minor technicalities, and instead would draw the conversation back to the bigger picture of working in Fiji.&lt;/p&gt;


	&lt;p&gt;The big picture did little to answer the reoccurring question of &amp;#8220;Yeah, but what will you be doing?&amp;#8221;  As it ends up &amp;#8211; a little bit of everything.  And in lieu of the broken big picture that did very little to answer the question before, here are a series of small pictures that should better approximate my life on Vorovoro.  Choose five to ten of the small sentence fragment snapshots below and you&amp;#8217;ve got a typical day.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Waking up in a coconut-frond thatched hut shaded by wind-blown trees and backed up by a 20 foot stone cliff and looking out the 9 &amp;#8221; x 3&amp;#8217; window ten yards down the beach to the ocean.&lt;/li&gt;
		&lt;li&gt;Disguising a quick walk to the compost toilets as a casual morning stroll while dodging chickens that have been awake since 4am.&lt;/li&gt;
		&lt;li&gt;Checking automated emails received on a Blackberry mobile to see if there have been any server crashes overnight.&lt;/li&gt;
		&lt;li&gt;Sitting down with a dozen other tribe members and discussing our dislike of the non-biting yet ubiquitously annoying ants over one of our five daily meals (being a British operation, there are two tea times during the day + 3 regular meals)&lt;/li&gt;
		&lt;li&gt;Frantically looking for and finding my sandals that I haven&amp;#8217;t worn in 3 days as the boat into town threatens to leave me behind.&lt;/li&gt;
		&lt;li&gt;Hunkered down trying to read the last Harry Potter book on a 10 foot boat powered by a 40hp engine for thirty minute commute into Labasa where power and internet can be found.&lt;/li&gt;
		&lt;li&gt;Walking through town during lunch, trying to decide which greasy Chinese restaurant to eat at while trying to blend in amongst the throngs of Fijians and Indo-Fijians on the sidewalks (which are equally congested with people as the streets are with cars)&lt;/li&gt;
		&lt;li&gt;Heading to the only internet cafe after packing my computer and change of clothes into my bag as we&amp;#8217;re informed that the boardroom at the hotel today won&amp;#8217;t be at our disposal.&lt;/li&gt;
		&lt;li&gt;Biting my tongue while listening to the cab driver (5 minute ride ~$1.50 &lt;span class="caps"&gt;FJD&lt;/span&gt;) espouse the benefits of polygamy, the majesty of the local HIbiscus Fair, and then ask me if I had change smaller than the $2 bill I&amp;#8217;d given him, then waiting by the side of the road for another cab to break the $2 bill for change.&lt;/li&gt;
		&lt;li&gt;Taking pictures &amp;#8211; &lt;a href="http://flickr.com/people/fightinjoe"&gt;lots and lots of pictures&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Meeting new arrivals, taking them into the market to buy a bundle of yagona roots as a token gift for the chief, explaining how a sarong is called a sulu in Fiji, and carting luggage to the jetty to watch the tide go out and wait for boat.&lt;/li&gt;
		&lt;li&gt;Taking off my shirt, hopping in the boat, and getting settled to read my book, looking up when we reach the mouth of the river and can see Vorovoro 15 minutes away from us halfway between the horizon.&lt;/li&gt;
		&lt;li&gt;Gardening, picking up trash, gathering firewood, washing dishes, foraging for flowers and leaves for our meke (tribal dance) outfits, raking leaves, bathing in the sea, brushing my teeth on the edge of the ocean from water in water bottle, watching the phosphorescence light up with little blips of purple as the waves disturb the water in the middle of the night&lt;/li&gt;
		&lt;li&gt;Watching the slow sweeping of the Milky Way across the sky while trying to mentally match up the phases of the moon with the tides for tomorrow (high tide in the morning was perfect for a morning bath, while in the evening you&amp;#8217;d be refreshed for dinner)&lt;/li&gt;
		&lt;li&gt;Sitting around the fire or kava bowl, legs falling asleep, chatting with friends, listening to the singing of the local Fijians relaxing after a long day of work.&lt;/li&gt;
	&lt;/ul&gt;</description><pubDate>2007-10-27T12:13:18+01:00</pubDate></item></channel></rss>
