<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Ruby on ZiGzAg</title>
 <link href="http://zigzag.github.com/atom.xml" rel="self"/>
 <link href="http://zigzag.github.com/"/>
 <updated>2010-04-01T02:58:29-07:00</updated>
 <id>http://zigzag.github.com/</id>
 <author>
   <name>Zigzag Chen</name>
   <email>zigzag.chen@gmail.com</email>
 </author>

 
 <entry>
   <title>Grep in Ruby - A powerful Enumerable method</title>
   <link href="http://zigzag.github.com/2010/03/31/grep-in-ruby----a-powerful-enumerable-method.html"/>
   <updated>2010-03-31T00:00:00-07:00</updated>
   <id>http://zigzag.github.com/2010/03/31/grep-in-ruby----a-powerful-enumerable-method</id>
   <content type="html">&lt;h1&gt;Grep in Ruby &amp;#8211; A powerful Enumerable method&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;31 Mar 2010 &amp;#8211; ZhuHai&lt;/p&gt;
&lt;p&gt;If you were a Unix shell fan, I bed that the &amp;#8220;grep&amp;#8221; command would be in your top-used list. But as for the Ruby programming, are you still prefer &amp;#8220;grep&amp;#8221; to the other methods come with the &amp;#8220;Enumerable&amp;#8221; module?&lt;br /&gt;
Do you know in most of the situation, using &amp;#8220;grep&amp;#8221; is more handy and powerful than the commonly used &amp;#8220;map&amp;#8221; or &amp;#8220;select&amp;#8221; methods? I will try to unveil the power of &amp;#8220;grep&amp;#8221; method in this post.&lt;/p&gt;
&lt;p&gt;First of all, let&amp;#8217;s review what &amp;#8220;grep&amp;#8221; do for an Enumerable object:&lt;br /&gt;
(Quoted from the Rdoc document of Ruby)&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;    &lt;span class=&quot;n&quot;&gt;enum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pattern&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;n&quot;&gt;array&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;enum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pattern&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;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&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;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; 
    &lt;span class=&quot;no&quot;&gt;Returns&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;every&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;If&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;optional&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supplied&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matching&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;passed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stored&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Simple enough,right? Here I will show you some convenient use cases:&lt;/p&gt;
&lt;h3&gt;Simpler select &amp;#8211; Filtering by pattern matching rather than giving a block to &amp;#8220;select&amp;#8221;.&lt;/h3&gt;
&lt;p&gt;Most of the time, we use the &amp;#8220;select&amp;#8221; method for filtering the elements in an Enumerable object by giving a block as criterion. Such as using &lt;code&gt;['a','1','b'].select{|x| /^\d*$/ === x}&lt;/code&gt; to filter out the numeric string. But by applying &amp;#8220;grep&amp;#8221; method with a Regexp pattern instead of a block, we get a shorter version: &lt;code&gt;['a','1','b'].grep(/^\d*$/)&lt;/code&gt;. This shortcut not only works for the RegExp pattern matching, But also works for all objects that overwrote the &amp;#8220;===&amp;#8221; method. Such as &amp;#8220;Range&amp;#8221; and &amp;#8220;Class&amp;#8221;. Therefore we can easily filter out elements like:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;[1,10,100,1000].grep(1..100) # =&amp;gt; [1, 10, 100]&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;[1,'a',2,'b'].grep(Integer) # =&amp;gt; [1,2]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is very easy to customize your filtering as well, just have you categorization logic defined as case equal(&amp;#8220;===&amp;#8221;) in your own class, then the instances of that class can be easily filtered out from an Enumerable object using the &amp;#8220;grep&amp;#8221; method.&lt;/p&gt;
&lt;h3&gt;Easier transforming using grep with Regexp and $n&lt;/h3&gt;
&lt;p&gt;It is not uncommon that we need to select some elements from a String collection according to some pattern and want to strip out part of the origin. Like the below example:&lt;br /&gt;
Given a String Array like &lt;code&gt;['hello.rb','world.rb','public.html']&lt;/code&gt;, and what we expected is the Ruby files without the extension name like: &lt;code&gt;['hello','world']&lt;/code&gt;.&lt;br /&gt;
Without thinking it too much, we can achieve this goal by combining the &amp;#8220;select&amp;#8221; and &amp;#8220;map&amp;#8221; methods just like #1 line below. But after we get familiar with the &amp;#8220;grep&amp;#8221; method and convention of the Regexp, we can have a more compact and elegant expression like #2 line:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;code&gt;['hello.rb','world.rb','public.html'].select{|x|x=~/\.rb/}.map{|x|x[0..-4]}&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;['hello.rb','world.rb','public.html'].grep(/(.*)\.rb/){$1}&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Selective bulk transforming &amp;#8211; combination of &amp;#8220;select&amp;#8221; and &amp;#8220;map&amp;#8221;&lt;/h3&gt;
&lt;p&gt;Among the Ruby methods of Enumerable, normally we use &amp;#8220;select&amp;#8221; for filtering and use &amp;#8220;map&amp;#8221; for bulk transforming. But as the examples showed before, the &amp;#8220;grep&amp;#8221; method can act as a combination of those two methods. Here it is called &amp;#8220;selective bulk transforming&amp;#8221;. A simple example is to pickup the numeric string and transfer them into Integer instances. See the following two versions for comparison:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;code&gt;['a','1','b','2'].select{|x| /^\d*$/ === x}.map{|x| x.to_i}&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;['a','1','b','2'].grep(/^\d*$/){|x| x.to_i}&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Or, even we make them shorter by the &amp;amp;symbol block, the version using &amp;#8220;grep&amp;#8221; looks more lovely:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;code&gt;['a','1','b','2'].select{|x| /^\d*$/ === x}.map(&amp;amp;:to_i)&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;['a','1','b','2'].grep(/^\d*$/,&amp;amp;:to_i)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Although the definition and implementation of the &amp;#8220;grep&amp;#8221; method from Enumerable module is simple, but by combing with other Ruby expression like case equal(&amp;#8220;===&amp;#8221;), Regexp, and &amp;#8220;&amp;amp;symbol&amp;#8221; block, It become a very handy and powerful method. Therefore next time when you come across some situation need to use &amp;#8220;select + map&amp;#8221;, keep &amp;#8220;grep&amp;#8221; in your mind beforehand.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>From TextMate to VIM for Rails Coders</title>
   <link href="http://zigzag.github.com/2010/02/14/from-textmate-to-vim-for-rails-coders.html"/>
   <updated>2010-02-14T00:00:00-08:00</updated>
   <id>http://zigzag.github.com/2010/02/14/from-textmate-to-vim-for-rails-coders</id>
   <content type="html">&lt;h1&gt;From TextMate to &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; for Rails Coders&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;18 Feb 2010 &amp;#8211; GuangXi, China&lt;/p&gt;
&lt;p&gt;In this post I will show you my experience of switching editor from TextMate to &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; for Rails developing. I will do a comparison with them in major aspects of coding efficiency. Hope it will help you choose the best editor fit for yourself. Your comments of either TextMate or &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; are all welcomed here.&lt;/p&gt;
&lt;p&gt;When started coding in Rails, I chose TextMate as my editor because it seems amazing as showed in the fantastic &lt;a href=&quot;http://railscasts.com&quot;&gt;RailsCasts from Ryan Bate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Indeed the journey ramping up the learning curve of Rails with TextMate was very delightful. I continued using it in several projects and became familiar with it until one day I had to give off my deer Mac Book and fall back to a Windows laptop. During the period waiting for my next Mac, I need to write Rails code without TextMate.&lt;/p&gt;
&lt;p&gt;Developing Rails on Windows is a miserable experience for me. Therefore I rather chose to &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; my remote Linux box with &lt;span class=&quot;caps&quot;&gt;PUTTY&lt;/span&gt; instead of using any windows &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;. I used to write script in VI on Linux but for daily rails coding, &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; with some plugins would be better.&lt;/p&gt;
&lt;p&gt;After I switched from TextMate, I found myself even more efficient and comfortable working with &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; at some points and still miss some stuff in TextMate. Here are the major differences I could count:&lt;/p&gt;
&lt;h2&gt;The mouse is not needed anymore.&lt;/h2&gt;
&lt;p&gt;If you are a keyboard shortcut lover, I bet you don&amp;#8217;t like shifting your hand between the keyboard and mouse while coding. Believe it or not, relocating the finger position, finding your mouse on desk and pointer on screen may be not a time-killer but it would distracts your attention all the time. While in TextMate, the shortcut system is powerful but still not powerful enough to support your work without the help from your Mickey.&lt;/p&gt;
&lt;p&gt;But in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;. After get used to the navigation keys, you will found it very efficient and do not need the mouse anymore. Here are some examples:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Locate your cursor: Using keys like &lt;code&gt;hjklwb$^&lt;/code&gt; to move your cursor. Pain at the beginning but works pretty good after you get familiar with them.&lt;/li&gt;
	&lt;li&gt;Go there quicker: Jumping to the line using &lt;code&gt;***G&lt;/code&gt; or Jumping to the word using &lt;code&gt;/XXX&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;Find the previous/next occurrence of current word: Just type &lt;code&gt;#&lt;/code&gt; or &lt;code&gt;*&lt;/code&gt;. Simpler than &lt;code&gt;CMD+E&lt;/code&gt; plus &lt;code&gt;CMD+G&lt;/code&gt; in TextMate.&lt;/li&gt;
	&lt;li&gt;Even the Columnar editing works pretty good with Block-wise visual mode activated by &lt;code&gt;CTRL+v&lt;/code&gt;. Good enough comparing the &lt;code&gt;ALT+Drag&lt;/code&gt; in TextMate.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Project Drawer: Miss it sometimes but not much.&lt;/h2&gt;
&lt;p&gt;When you just involved in a project, the tree opened in the project drawer could do you a favor for showing the structure clearly. But after you dig into the project deeper, you will find the Project Tree became more and more useless. Usually I close the drawer and using &lt;code&gt;CMD+T&lt;/code&gt; to open files quickly. In &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, I installed a tree plugin called &lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=1658&quot;&gt;NERDtree&lt;/a&gt;, but frankly I don&amp;#8217;t use it very often. With the &lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=1567&quot;&gt;Rails plugin&lt;/a&gt;. I used the file navigation commands below(Press tab when typing those command save a lot of time):&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;:Rmodel&lt;/code&gt;,&lt;code&gt;:Rcontroller&lt;/code&gt;,&lt;code&gt;:Rview&lt;/code&gt;,&lt;code&gt;:Rmigration&lt;/code&gt; for jumping to the file when the name came into my head.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;:A&lt;/code&gt;,&lt;code&gt;:R&lt;/code&gt; for jumping to the &amp;#8216;Alternative&amp;#8217; or &amp;#8216;Relative&amp;#8217; file of current file. Just like &lt;code&gt;ALT+CMD+DOWN&lt;/code&gt; in TextMate.&lt;/li&gt;
	&lt;li&gt;Want to open the file named under the cursor, just type &lt;code&gt;gf&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;File tabs: Would not miss it after get used to Window-splitting.&lt;/h2&gt;
&lt;p&gt;As for the file tabs. I used it heavily in TextMate and get used to switching tabs using &lt;code&gt;CMD+number&lt;/code&gt;. The version of &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; that I am using(7.2) also contain the support for tab browsing. But It still not work as good as TextMate does. But start to getting more and more familiar with the windows splitting function in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, I do not miss the tab browsing so much. Since the major switching is the Model/UnitTest or Controller/View, and that will be perfectly done by windows splitting.&lt;/p&gt;
&lt;h2&gt;Project searching: Still finding a better way.&lt;/h2&gt;
&lt;p&gt;While I writing rails code,especially when debugging In TextMate,I used the Project searching &lt;code&gt;CMD+SHIFT+F&lt;/code&gt; quite often. But in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, I have to fall back to the shell command like &lt;code&gt;find . -type f|grep rb$|xargs grep xxx&lt;/code&gt;. Do you have any suggestion for it?&lt;/p&gt;
&lt;h2&gt;Snippets: The Killer feature that I miss the most.&lt;/h2&gt;
&lt;p&gt;I thought the Snippets come with different bundles as the killer feature of TextMate. Although there is a similar plugin called &lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=2540&quot;&gt;SinpMate&lt;/a&gt; available for &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, But when it comes to the shortcut name that you are not familiar with, TextMate provides you a quick way &lt;code&gt;CTRL+CMD+T&lt;/code&gt; for hint. I &lt;span class=&quot;caps&quot;&gt;REALLY&lt;/span&gt; expect that this could come into the &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; plugin.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There are still a lot of detail differences between these two excellent editors that I did not list here. But the overall experience for me of switching from TextMate to &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; is exciting. Especially imagine that in the near future, I can bring out my iPad + Wireless Keyboard and go on hacking code quickly with TouchTerm(A &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; client App for iPhone) + &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;&amp;#8230; Doesn&amp;#8217;t it cool enough? Any comments are welcomed here or tweet me &lt;a href=&quot;http://twitter.com/zigzagchen&quot;&gt;@zigzagchen&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Resource&lt;/h2&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=1567&quot;&gt;rails.vim&lt;/a&gt; &amp;#8212; Ruby on Rails: easy file navigation, enhanced syntax highlighting, and more#&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=1658&quot;&gt;The NERDtree&lt;/a&gt; &amp;#8212; A tree explorer plugin for navigating the filesystem.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=2540&quot;&gt;snipMate&lt;/a&gt; &amp;#8212; TextMate-style snippets for Vim.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://github.com/zigzag/dotvim&quot;&gt;Zigzag&amp;#8217;s .vim setting&lt;/a&gt; &amp;#8212; My &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; setting repository on GitHub.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.artfulcode.net/articles/from-textmate-to-vim/&quot;&gt;From TextMate to Vim&lt;/a&gt; &amp;#8212; Annother post in the same topic.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://alexyoung.org/2006/10/22/vim-for-textmate-fans/&quot;&gt;Vim for TextMate Fans&lt;/a&gt; &amp;#8212; Same topic with a screenshoot&lt;/li&gt;
&lt;/ol&gt;</content>
 </entry>
 
 <entry>
   <title>Customizing your scaffold template become easier in Rails3</title>
   <link href="http://zigzag.github.com/2010/01/18/customizing-your-scaffold-template-become-easier-in-rails3.html"/>
   <updated>2010-01-18T00:00:00-08:00</updated>
   <id>http://zigzag.github.com/2010/01/18/customizing-your-scaffold-template-become-easier-in-rails3</id>
   <content type="html">&lt;h1&gt;Customizing your scaffold template become easier in Rails3&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;18 Jan 2010 &amp;#8211; Beijing&lt;/p&gt;
&lt;p&gt;In the weekend of &lt;a href=&quot;http://www.bugmash.com/&quot;&gt;BugMash for Rails3&lt;/a&gt;. I planned to make a experiment of a &lt;a href=&quot;http://github.com/zigzag/iTBD&quot;&gt;showcase using Rails3 and the new released jQuery 1.4&lt;/a&gt;. Rails3 in this experiment would act as a back-end service provider using &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; and the UI stuff would be all handled by jQuery. Therefore making a scaffold generating will save my time for just exposing my simple models in the &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; format.&lt;/p&gt;
&lt;p&gt;After the generating, the controller code is look like:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@tasks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;respond_to&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;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# index.html.erb&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xml&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:xml&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@tasks&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;/div&gt;&lt;p&gt;Actually this is not near from what I need. RESTful methods that handling &lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; are enough and html/xml is not needed.&lt;/p&gt;
&lt;p&gt;In rails 2.x there are no support in the core framework to change the scaffold template easily.&lt;/p&gt;
&lt;p&gt;I anticipated the scaffold generator would become smarter in Rails 3 just like using some options like &amp;#8212;type=&lt;span class=&quot;caps&quot;&gt;JSON&lt;/span&gt; then the generated result will be changed.&lt;br /&gt;
But the magic did not happen. I called for help in &lt;span class=&quot;caps&quot;&gt;IRC&lt;/span&gt; #railsbridge and &lt;a href=&quot;http://github.com/josevalim&quot;&gt;josevalim&lt;/a&gt; told me a easy way to customize my own generating template:&lt;br /&gt;
Just make a copy of the template at &lt;br /&gt;
&lt;code&gt;rails/railties/lib/generators/rails/scaffold_controller/templates&lt;/code&gt; (&lt;a href=&quot;http://github.com/rails/rails/blob/master/railties/lib/generators/rails/scaffold_controller/templates/controller.rb&quot;&gt;or it&amp;#8217;s github link&lt;/a&gt;) to&lt;br /&gt;
&lt;code&gt;RAILS_ROOT/lib/templates/rails/scaffold_controller/controller.rb&lt;/code&gt;&lt;br /&gt;
The code in template is look like&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# GET /&amp;lt;%= table_name %&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# GET /&amp;lt;%= table_name %&amp;gt;.xml&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%= table_name %&amp;gt; =&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%= orm_class.all(class_name) %&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  respond_to do |format|&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;    format.html # index.html.erb&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;    format.xml  { render :xml =&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_name&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;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;/div&gt;&lt;p&gt;I modified it to my own version:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# GET /&amp;lt;%= table_name %&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%= table_name %&amp;gt; =&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;%= orm_class.all(class_name) %&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sx&quot;&gt;  render :json =&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Then run generating again. Then it comes the controller that I need:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# GET /tasks&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@tasks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@tasks&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Easy enough, right?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Ready_for_i18n 0.3 released -- support for non-english projects.</title>
   <link href="http://zigzag.github.com/2009/12/31/ready_for_i18n-0.3-released----support-for-non-english-projects..html"/>
   <updated>2009-12-31T00:00:00-08:00</updated>
   <id>http://zigzag.github.com/2009/12/31/ready_for_i18n-0.3-released----support-for-non-english-projects.</id>
   <content type="html">&lt;h1&gt;Ready_for_i18n 0.3 released &amp;#8212; support for non-english projects.&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;31 Dec 2009 &amp;#8211; Beijing&lt;/p&gt;
&lt;p&gt;In the initial version of ready_for_i18n(&lt;a href=&quot;http://zigzag.github.com/2009/12/17/get-your-local-rails-application-ready-for-i18n.html&quot;&gt;Introduced here&lt;/a&gt;), We had an assumption that the locale of your project to be extracted is English, therefore the key in the dictionary file can be just come from the literal word. But there are also so many non-english local projects that need to be internationalized. So we come out an idea to introduce a simple key-text mapping mechanism. Still simply using one command of &lt;code&gt;ready_for_i18n&lt;/code&gt; and follow these steps to get you non-english project ready for i18n.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Assuming you are in the &lt;code&gt;app/views&lt;/code&gt; directory of your rails project.)&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Using &lt;code&gt;ready_for_i18n . --nokey &amp;gt; cn.txt&lt;/code&gt; to extract all text and label in your views.&lt;/li&gt;
	&lt;li&gt;Open the &lt;em&gt;cn.txt&lt;/em&gt; and go for &lt;a href=&quot;http://translate.google.com/&quot;&gt;google translate&lt;/a&gt; (or other tools you like or do it manually) then paste the result in a new file called &lt;em&gt;en.txt&lt;/em&gt; with the following cautions &amp;#8212; (Do &lt;span class=&quot;caps&quot;&gt;NOT&lt;/span&gt; change anything in &lt;em&gt;cn.txt&lt;/em&gt; but you can change the translated en.txt just remember keeping the same line number of &lt;em&gt;en.txt&lt;/em&gt; with &lt;em&gt;cn.txt&lt;/em&gt;).&lt;/li&gt;
	&lt;li&gt;Using &lt;code&gt;ready_for_i18n . . --keymap=cn.txt:en.txt &amp;gt; cn.yml&lt;/code&gt; Then all your views will be replaced to an i18ned version and the generated &lt;em&gt;cn.yml&lt;/em&gt; dictionary file will use the keys from &lt;em&gt;en.txt&lt;/em&gt; and values from &lt;em&gt;cn.txt&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That is it. It is a bit more steps than extracting the English project, but still simple enough, right?&lt;br /&gt;
Besides, if you do not satisfied with the default simple key mapping for your English local project, you can also using this way to change you key mapping as your will.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.gemcutter.org/gems/ready_for_i18n&quot;&gt;0.3 version of ready_for_i18n&lt;/a&gt; also contain some bug fixes and the following enhancements:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Support for a Dry run mode &amp;#8212; Just using one parameter for your view path, then &lt;code&gt;ready_for_i18n&lt;/code&gt; will not replace any of your view files but just generate an dictionary file to &lt;span class=&quot;caps&quot;&gt;STDOUT&lt;/span&gt;. You can redirect this out to file as you want.&lt;/li&gt;
	&lt;li&gt;Support a lazy-lookup(explained as the following screenshot&amp;#8594; clipped from &lt;a href=&quot;http://guides.rubyonrails.org/i18n.html#looking-up-translations&quot;&gt;Rails i18n guide&lt;/a&gt;) extracting that will help you generate a more structured dictionary file. Just using &lt;code&gt;--dot&lt;/code&gt; options in the &lt;code&gt;ready_for_i18n&lt;/code&gt; command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/images/lazy_lookup.png&quot; title=&quot;lazy-lookup&quot; alt=&quot;lazy-lookup&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Well, Hope this tool will help you in the coming year! Looking forward to your comments.&lt;/p&gt;
&lt;h1&gt;Happy new year!&lt;/h1&gt;</content>
 </entry>
 
 <entry>
   <title>Get your local Rails application ready for I18N</title>
   <link href="http://zigzag.github.com/2009/12/17/get-your-local-rails-application-ready-for-i18n.html"/>
   <updated>2009-12-17T00:00:00-08:00</updated>
   <id>http://zigzag.github.com/2009/12/17/get-your-local-rails-application-ready-for-i18n</id>
   <content type="html">&lt;h1&gt;Get your local Rails application ready for I18N&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;17 Dec 2009 &amp;#8211; Beijing&lt;/p&gt;
&lt;p&gt;Think of the following scenario: &lt;br /&gt;
You have created your lovely Rails application and managed to get it real. After a period of time it become more and more popular. People around the world love your application.  Then somebody start to ask wether you can provide an version in their language. Some active users even made a commitment that they will contribute the translation to their language.&lt;/p&gt;
&lt;p&gt;Pretty good news yet, but when you look back to you application code, you already have over hundreds &lt;span class=&quot;caps&quot;&gt;ERB&lt;/span&gt; pages with many hard-code text being spread in &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and &lt;span class=&quot;caps&quot;&gt;ERB&lt;/span&gt; tags&amp;#8230;&lt;br /&gt;
Although Rails &amp;gt; 2.2 provide a handy way of doing I18N by the I18n.translate( t method in helper), Found out all the text need to transfer is a tedious and error-prone task.&lt;/p&gt;
&lt;p&gt;An &lt;a href=&quot;http://github.com/svenfuchs/rails-i18n/tree/master/tools/Rails%20I18n.tmbundle&quot;&gt;I18N Textmate Bundle&lt;/a&gt; written by &lt;a href=&quot;http://github.com/svenfuchs&quot;&gt;Sven Fuchs&lt;/a&gt; may do you a favor when extracting those text. But you still need to find every explicit string and name the keys of them manually.&lt;/p&gt;
&lt;p&gt;Could we make an automatic tool for this boring task? Since if the hard-coded text is written in English, we can conventionally name the key with the same name. (just lowercase it and connected with underline other than space). And the texts need to be translated in &lt;span class=&quot;caps&quot;&gt;ERB&lt;/span&gt; seem to have some common attributes: they either exist in the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; text node or in some helper methods like &lt;code&gt;link_to&lt;/code&gt;, &lt;code&gt;label_tag&lt;/code&gt;, etc&amp;#8230;&lt;/p&gt;
&lt;p&gt;Based on the above assumption, My colleague &lt;a href=&quot;http://github.com/rainny&quot;&gt;Rainy&lt;/a&gt; pair-programming with me the following tool called &lt;a href=&quot;http://github.com/zigzag/ready_for_i18n&quot;&gt;ready_for_i18n&lt;/a&gt; . and release it at &lt;a href=&quot;http://www.gemcutter.org/gems/ready_for_i18n&quot;&gt;Gemcutter&lt;/a&gt;. After install it by &lt;br /&gt;
&lt;code&gt;gem install ready_for_i18n&lt;/code&gt;&lt;br /&gt;
just run:&lt;br /&gt;
&lt;code&gt;ready_for_i18n &amp;lt;you view path&amp;gt; &amp;lt;target path&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then the tool will transform your view like the screenshot #1(Diff result) and also generate a dictionary &lt;code&gt;en.yml&lt;/code&gt; file looked like screenshot #2.&lt;br /&gt;
Have the similar I18N problem? Check it out and any of your comments are welcome here and also on the &lt;a href=&quot;http://github.com/zigzag/ready_for_i18n&quot;&gt;project home at github&lt;/a&gt; .&lt;/p&gt;
&lt;h2&gt;Screenshot #1: Diff result of the transform result with the original view file&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/images/view_dff.png&quot; title=&quot;Screenshot #1&quot; alt=&quot;Screenshot #1&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Screenshot #2 Auto generated en.yml&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/images/en_yml.png&quot; title=&quot;Screenshot #2&quot; alt=&quot;Screenshot #2&quot; /&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>A Simple Global Setting class</title>
   <link href="http://zigzag.github.com/2009/12/10/simple-global-setting-class.html"/>
   <updated>2009-12-10T00:00:00-08:00</updated>
   <id>http://zigzag.github.com/2009/12/10/simple-global-setting-class</id>
   <content type="html">&lt;h1&gt;A Simple Global Setting class&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;10 Dec 2009 &amp;#8211; Beijing&lt;/p&gt;
&lt;p&gt;Almost in every web application, the administrator user need to setup some system parameters on the fly.&lt;br /&gt;
These parameter settings are different from the application configuration, which normally stored in the yml files under the config directory. Some of the developers incline to create a migration and store such properties into DB.&lt;/p&gt;
&lt;p&gt;But for most of the simple situations, the &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt; file just work fine. We only need to wrap it a little like a GlobalSetting class listed below.&lt;/p&gt;
&lt;p&gt;So that you can save your &lt;code&gt;params&lt;/code&gt; got from controller directly like:&lt;br /&gt;
&lt;code class=&quot;terminal&quot;&gt;GlobalSetting.save param[:setting]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And retrieve them just by:&lt;br /&gt;
&lt;code class=&quot;terminal&quot;&gt;GlobalSetting[:TAX_RATE]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The setting hash you save can have more complex structure combined by arrays or other hashes,like:&lt;br /&gt;
&lt;code class=&quot;terminal&quot;&gt;GlobalSetting.save {:ACCOUNT =&amp;gt; {:TAX_RATE =&amp;gt; 0.2}}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Instead of using &lt;br /&gt;
&lt;code class=&quot;terminal&quot;&gt;GlobalSetting[:ACCOUNT] &amp;amp;&amp;amp; GlobalSetting[:ACCOUNT][:TAX_RATE]&lt;/code&gt;&lt;br /&gt;
for avoiding the NoMethodError, we have a more &lt;span class=&quot;caps&quot;&gt;DRY&lt;/span&gt; way: &lt;br /&gt;
&lt;code class=&quot;terminal&quot;&gt;GlobalSetting[:ACCOUNT, :TAX_RATE]&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Source Code of global_setting.rb&lt;/h3&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GlobalSetting&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cattr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:file_path&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RAILS_ROOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;config&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;setting.yml&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;[]&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;keys&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setting&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;m&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;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&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;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Array&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;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;[]=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;setting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&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;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&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;nb&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setting&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;w+&amp;#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;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_yaml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@setting&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;load&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;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&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;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;setting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merge!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;save&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;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setting&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@setting&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;load&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;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;File&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&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;no&quot;&gt;YAML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&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;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;/div&gt;&lt;h2&gt;The Unit Test Code showing how to use it&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GlobalSettingTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TestCase&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RAILS_ROOT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;tmp&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;test_setting.yml&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:t1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;v1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;v2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a2&amp;#39;&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;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;ss&quot;&gt;:h1&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;ss&quot;&gt;:nh&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;nested&amp;quot;&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;test_load&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;v1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t1&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;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;v2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t2&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;n&quot;&gt;assert_equal&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;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_update&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;v1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t1&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;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;c1&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;c1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t1&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_load_from_top&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;v1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t1&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_dig&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&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;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:arr&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;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;nested&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:nh&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;n&quot;&gt;assert_nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bar&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;n&quot;&gt;assert_nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:arr&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;ss&quot;&gt;:dd&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_merge&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:h1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;new Value&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;v1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:t1&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;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;new Value&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GlobalSetting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:h1&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
 </entry>
 
 <entry>
   <title>Rails Rock Me</title>
   <link href="http://zigzag.github.com/2009/12/09/rails-rock-me.html"/>
   <updated>2009-12-09T00:00:00-08:00</updated>
   <id>http://zigzag.github.com/2009/12/09/rails-rock-me</id>
   <content type="html">&lt;h1&gt;Rails Rock Me&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;9 Dec 2009 &amp;#8211; Beijing&lt;/p&gt;
&lt;p&gt;Since as a 7 years experienced Java developer, I have to admitted that the stuff that rock me this year is the Ruby language and the Rails framework. Here is the list:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;In the construction of the project-portal within the company, &lt;a href=&quot;http://www.redmine.org/&quot;&gt;Redmine&lt;/a&gt; (a flexible project management web application. Written using Ruby on Rails) is a big win against the awkward &lt;a href=&quot;http://www.liferay.com&quot;&gt;Liferay&lt;/a&gt;. We even think about replacing it for our commercial &lt;a href=&quot;http://www.atlassian.com/software/jira/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;JIRA&lt;/span&gt;&lt;/a&gt; instance which used for years in our issue tracking. &lt;br /&gt;
The winning factor is that the &amp;#8220;Keep It Simple&amp;#8221; philosophy being gone through the language, framework and the application.&lt;/li&gt;
	&lt;li&gt;Happily fixed a small web project written in Ruby on Rails by a novice team. Cut the &lt;span class=&quot;caps&quot;&gt;LOC&lt;/span&gt; from 7600 to 5500 while bring significant feature &amp;amp; performance improvements.&lt;/li&gt;
	&lt;li&gt;Adopted the &lt;a href=&quot;http://sonar.codehaus.org/&quot;&gt;Sonar&lt;/a&gt; as the quality metrics tool for the company. Glad to cooperated with the Sonar team in JRuby on Rails.&lt;/li&gt;
	&lt;li&gt;Following the &lt;a href=&quot;http://railscasts.com/&quot;&gt;RailsCasts&lt;/a&gt; and &lt;a href=&quot;http://ruby5.envylabs.com/&quot;&gt;Ruby5&lt;/a&gt; news keep me exciting about the community growth with the contribution from lots of clever guys here.&lt;/li&gt;
	&lt;li&gt;Learning Ruby by reading the Book named &lt;a href=&quot;http://www.manning.com/black2/&quot;&gt;The Well-Grounded Rubyist&lt;/a&gt; and scripted it in small tasks bring me back the joyful memory of learning programing in the early day.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://github.com/&quot;&gt;Github&lt;/a&gt; inspired me to dig deeper into the beauty of the open-source world and start &lt;a href=&quot;http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html&quot;&gt;blogging like a hacker&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;To be continue &amp;#8230;&lt;/li&gt;
&lt;/ol&gt;</content>
 </entry>
 
 
</feed>