<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
  <title>AQ's Tech Blog</title>
  <subtitle>where Ruby is Awesome and JavaScript Kicks Ass</subtitle>
  <link href="http://aaronqian.com//" rel="self" />
  <link href="http://aaronqian.com/" />
  <updated>2010-02-08T22:37:16+08:00</updated>
  <author>
    <name>Aaron Qian</name>
    <email>aq1018@gmail.com</email>
  </author>
  <id>http://aaronqian.com/</id>
  
  <entry>
    <title>dm-is-slug 0.10.2 Now on GemCutter</title>
    <link href="/articles/2010/02/08/dm-is-slug-is-now-on-gem-cutter.html" />
    <id>tag:aaronqian.com,2010-02-08:1265637907</id>
    <updated>2010-02-08T22:05:07+08:00</updated>
    <content type="html">&lt;h3&gt;I&amp;#8217;m so forgetful&lt;/h3&gt;
&lt;p&gt;I created a &lt;a href=&quot;http://datamapper.org&quot;&gt;datamapper&lt;/a&gt; plugin called &lt;a href=&quot;http://github.com/aq1018/dm-is-slug&quot;&gt;dm-is-slug&lt;/a&gt; in 2009 to ease the pain of handling permalinks or url slugs in my &lt;a href=&quot;http://www.merbivore.com&quot;&gt;merb&lt;/a&gt; project. I have to admit, I have totally forgotten about it until now!&lt;/p&gt;
&lt;p&gt;So, I spent some time merging commits from &lt;a href=&quot;http://github.com/cheba&quot;&gt;Alex Mankuta&lt;/a&gt; whom has fixed many bugs, and now it works much better. Thanks, cheba!&lt;/p&gt;
&lt;p&gt;I also added support for &lt;a href=&quot;http://rubyforge.org/projects/unidecode/&quot;&gt;unidecoding&lt;/a&gt;, which allows you to turn strings like &lt;em&gt;&amp;#8220;你好&amp;#8221;&lt;/em&gt; into &lt;em&gt;&amp;#8220;ni-hao&amp;#8221;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Lastly, the gem is pushed to &lt;a href=&quot;http://gemcutter.org&quot;&gt;gemcutter&lt;/a&gt; for easy gem install. That didn&amp;#8217;t take too long! :)&lt;/p&gt;
&lt;h3 style=&quot;text-align:center;&quot;&gt;&lt;a href=&quot;http://github.com/aq1018/dm-is-slug&quot;&gt;Find out how to use dm-is-slug on github!&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Updates on Inspec - Javascript BDD Framework</title>
    <link href="/articles/2009/04/24/updates-on-inspec-javascript-bdd-framework.html" />
    <id>tag:aaronqian.com,2009-04-24:1240583821</id>
    <updated>2009-04-24T22:37:01+08:00</updated>
    <content type="html">&lt;p&gt;For the past two weeks, a lot of improvements has been done for &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;Inspec&lt;/a&gt;, here is the list:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Better scoping / sandboxing&lt;/li&gt;
	&lt;li&gt;Support for &lt;a href=&quot;http://www.mozilla.org/rhino/&quot;&gt;Rhino&lt;/a&gt;, &lt;a href=&quot;http://www.mozilla.org/js/spidermonkey/&quot;&gt;SpiderMonkey&lt;/a&gt;, &lt;a href=&quot;http://github.com/jbarnette/johnson/tree/master/&quot;&gt;Johnson&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Windows_Script_Host&quot;&gt;WSCript&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Tested to work with IE7, Firefox 3, Chrome and Safari 3&lt;/li&gt;
	&lt;li&gt;Added a lot more specs to test &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;Inspec&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Fixed a bug where cascading before / after blocks not getting the correct scoping / sandboxing&lt;/li&gt;
	&lt;li&gt;Changed BDD syntax a bit to be compatible with &lt;a href=&quot;http://github.com/nkallen/screw-unit/tree/master&quot;&gt;Screw.Unit&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Shamelessly stole all matchers from &lt;a href=&quot;http://github.com/nkallen/screw-unit/tree/master&quot;&gt;Screw.Unit&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Added the following matchers:
	&lt;ul&gt;
		&lt;li&gt;beA  &amp;#8211; instanceof test&lt;/li&gt;
		&lt;li&gt;throwError &amp;#8211; takes an function, and see if it throws an error&lt;/li&gt;
		&lt;li&gt;respondTo &amp;#8211; test if an object has a function&lt;/li&gt;
		&lt;li&gt;have &amp;#8211; see if an object or array contains something&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;m working on some &lt;b&gt;advanced features&lt;/b&gt; that requires some pretty big structural changes right now. They are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Support for multiple definition of same behaviors.&lt;/li&gt;
	&lt;li&gt;Support for multiple definition of before / after blocks.&lt;/li&gt;
	&lt;li&gt;Redo shared example groups ( Allows for sharing local scope variables inside shared example groups)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I plan to finish this feature while I&amp;#8217;m taking a business trip to Boston this coming Sunday.&lt;/p&gt;
&lt;p&gt;For future, the plan follows:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Spec, spec spec, 100% coverage require!&lt;/li&gt;
	&lt;li&gt;Extract and improve rendering logic from HTMLReporter to HTMLReporter.FlatFormatter&lt;/li&gt;
	&lt;li&gt;Implement HTMLReporter.NestedFormater&lt;/li&gt;
	&lt;li&gt;Implement HTMLReporter.CompactFormater&lt;/li&gt;
	&lt;li&gt;Implement ConsoleReporter.FlatFormatter&lt;/li&gt;
	&lt;li&gt;Implement ConsoleReporter.NestedFormater&lt;/li&gt;
	&lt;li&gt;Implement ConsoleReporter.CompactFormater&lt;/li&gt;
	&lt;li&gt;Implement options for choose formatters, need to consider extending&lt;/li&gt;
	&lt;li&gt;Add statistics functionality to Reporter Class&lt;/li&gt;
	&lt;li&gt;Test on different browsers&lt;/li&gt;
	&lt;li&gt;Selective Behavior Execution support&lt;/li&gt;
	&lt;li&gt;Prioritize object printing with toString() if object has customized toString&lt;/li&gt;
	&lt;li&gt;Documentation&lt;/li&gt;
	&lt;li&gt;Make a wiki&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#8217;s a lot of stuff to complete! If anyone interested please &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;fork Inspec&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Inspec - Yet Another Javascript BDD Test Framework</title>
    <link href="/articles/2009/04/13/inspec-yet-another-javascript-bdd-test-framework.html" />
    <id>tag:aaronqian.com,2009-04-13:1239628485</id>
    <updated>2009-04-13T21:14:45+08:00</updated>
    <content type="html">&lt;h3&gt;The &amp;#8220;Why&amp;#8221; Question&lt;/h3&gt;
&lt;p&gt;Why? You ask, we already have BDD Frameworks such as &lt;a href=&quot;http://github.com/nkallen/screw-unit/tree/master&quot;&gt;Screw.Unit&lt;/a&gt;, &lt;a href=&quot;http://visionmedia.github.com/jspec/&quot;&gt;jSpec&lt;/a&gt;, and &lt;a href=&quot;http://jania.pe.kr/aw/moin.cgi/JSSpec&quot;&gt;JSSepc&lt;/a&gt;, you want to make &lt;em&gt;another&lt;/em&gt; Javascript BDD Test Framework?&lt;/p&gt;
&lt;p&gt;To answer your question, you can take a look at my previous article &lt;a href=&quot;/articles/2009/04/12/javascript-bdd-test-frameworks-compared.html&quot;&gt;comparing strengthes and weaknesses&lt;/a&gt; of the above frameworks. So, please &lt;a href=&quot;/articles/2009/04/12/javascript-bdd-test-frameworks-compared.html&quot;&gt;read it&lt;/a&gt; if you haven&amp;#8217;t done so.&lt;/p&gt;
&lt;p&gt;Now, if you are still with me after finish reading my article, allow me to introduce you a new BDD Test Framework that doesn&amp;#8217;t suck.&lt;/p&gt;
&lt;h3&gt;Introducing &lt;b&gt;&lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;Inspec&lt;/a&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;While coding up &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;Inspec&lt;/a&gt;, I was trying to fulfill the following features:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Nested behaviors&lt;/li&gt;
	&lt;li&gt;Shared behaviors (aka. &lt;code&gt;it_should_behave_like&lt;/code&gt; in &lt;a href=&quot;http://rsepc.info&quot;&gt;RSepc&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;Framework agnostic ( You can use it with &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt;, &lt;a href=&quot;http://www.prototypejs.org/&quot;&gt;Prototype&lt;/a&gt;, &lt;a href=&quot;http://mootools.net/&quot;&gt;Mootools&lt;/a&gt;, &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt;, or &lt;a href=&quot;http://extjs.com/&quot;&gt;ExtJS&lt;/a&gt;. it&amp;#8217;s your choice. )&lt;/li&gt;
	&lt;li&gt;An elegent DSL&lt;/li&gt;
	&lt;li&gt;No namespace pollution&lt;/li&gt;
	&lt;li&gt;Able to run in browser, &lt;a href=&quot;http://ajaxian.com/archives/johnson-wrapping-javascript-in-a-loving-ruby-embrace-and-arax&quot;&gt;command-line&lt;/a&gt;, and &lt;a href=&quot;http://en.wikipedia.org/wiki/Server-side_JavaScript&quot;&gt;server side&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;A cystal clear API that is easy to understand and extend&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sound awesome! But how does it work?&lt;/p&gt;
&lt;p&gt;Here is a small example:&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;Inspec&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){

  it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    expect(&lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;).toBeTrue();
  })

  it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should fail&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    expect(&lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;).not().toBeTrue();
  })

  it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should be pending&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)

  describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;with a nested example group&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work as a nested example group&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      expect(&lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;).toBe(&lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;);
    })
  })

  &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;//&lt;/span&gt; W00t?? It's nesting a shared example group&lt;/span&gt;
  itShouldBehaveLike(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;a shared example group&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
})

sharedExamplesFor(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;a shared example group&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
  it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work as shared example&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    expect(&lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;).toBeTrue();
  })

  &lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;//&lt;/span&gt; Yes! Shared nested Example Groups!&lt;/span&gt;
  describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;with nested example groups in shared&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work as a nested example group in shared&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      expect(&lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;).toBeTrue();
    })
  })
})
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is another example that uses more matchers:&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;Matchers&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
  describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;TypeMatcher&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with String&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; aString &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;abc&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
      expect(aString).toBeType(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;string&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with Number&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; aNumber &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;123&lt;/span&gt;;
      expect(aNumber).toBeType(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;number&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with Object&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; anObject &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; {};
      expect(anObject).toBeType(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;object&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    })
 
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with Boolean&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; aBoolean &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;false&lt;/span&gt;;
      expect(aBoolean).toBeType(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;boolean&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with undefined&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; undefinedValue;
      expect(undefinedValue).toBeType(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;undefined&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    })
 
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with function&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;aFunction&lt;/span&gt; = &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){};
      expect(aFunction).toBeType(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;function&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    })
  })
  
  describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;InstanceMatcher&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with String&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; aString &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;String&lt;/span&gt;(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;abc&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
      expect(aString).toBeA(&lt;span class=&quot;Support&quot;&gt;String&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with Number&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; aNumber &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Number&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;123&lt;/span&gt;);
      expect(aNumber).toBeA(&lt;span class=&quot;Support&quot;&gt;Number&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with a class&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Foo&lt;/span&gt; = &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){};
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; foo &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Foo&lt;/span&gt;();
      expect(foo).toBeA(Foo);
    })
 
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with a sub-class&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; Foo &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; Inspec.Class.extend({});
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; foo &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;Foo&lt;/span&gt;();
      expect(foo).toBeA(Foo);
      expect(foo).toBeA(Inspec.Class);
      expect(foo).toBeA(&lt;span class=&quot;Support&quot;&gt;Object&lt;/span&gt;);
    })
  })
  
  describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;ComparisonMatcher&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with toBeAtLeast&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      expect(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;).toBeAtLeast(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
      expect(&lt;span class=&quot;Constant&quot;&gt;6&lt;/span&gt;).toBeAtLeast(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with toBeAtMost&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      expect(&lt;span class=&quot;Constant&quot;&gt;4&lt;/span&gt;).toBeAtMost(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
      expect(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;).toBeAtMost(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with toBeGreaterThan&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      expect(&lt;span class=&quot;Constant&quot;&gt;6&lt;/span&gt;).toBeGreaterThan(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
      expect(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;).not().toBeGreaterThan(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should work with toBeLessThan&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      expect(&lt;span class=&quot;Constant&quot;&gt;4&lt;/span&gt;).toBeLessThan(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
      expect(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;).not().toBeLessThan(&lt;span class=&quot;Constant&quot;&gt;5&lt;/span&gt;);
    })
  })
  
  describe(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;RegexMatcher&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should match correct string&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; emailRegex &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt; &lt;span class=&quot;String&quot;&gt;/&lt;/span&gt;^([0-9a-zA-Z]([-.&lt;span class=&quot;Constant&quot;&gt;\w&lt;/span&gt;]*[0-9a-zA-Z])*@([0-9a-zA-Z][-&lt;span class=&quot;Constant&quot;&gt;\w&lt;/span&gt;]*[0-9a-zA-Z]&lt;span class=&quot;Constant&quot;&gt;\.&lt;/span&gt;)+[a-zA-Z]{2,9})$&lt;span class=&quot;String&quot;&gt;/&lt;/span&gt;&lt;/span&gt;;
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; email &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;abc@efg.com&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
      expect(email).toMatch(emailRegex);
    })
    
    it(&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;should not match incorrect string&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Storage&quot;&gt;function&lt;/span&gt;(){
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; emailRegex &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;String&quot;&gt; &lt;span class=&quot;String&quot;&gt;/&lt;/span&gt;^([0-9a-zA-Z]([-.&lt;span class=&quot;Constant&quot;&gt;\w&lt;/span&gt;]*[0-9a-zA-Z])*@([0-9a-zA-Z][-&lt;span class=&quot;Constant&quot;&gt;\w&lt;/span&gt;]*[0-9a-zA-Z]&lt;span class=&quot;Constant&quot;&gt;\.&lt;/span&gt;)+[a-zA-Z]{2,9})$&lt;span class=&quot;String&quot;&gt;/&lt;/span&gt;&lt;/span&gt;;
      &lt;span class=&quot;Storage&quot;&gt;var&lt;/span&gt; email &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;abc_efg.com&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
      expect(email).not().toMatch(emailRegex);
    })
  })
})
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;What&amp;#8217;s working so far&lt;/h3&gt;
&lt;p&gt;As this is still an early release (Let&amp;#8217;s see, It is about 3 weeks old so far. Let&amp;#8217;s call it version 0.0.1??), most of the core features are already working. Here is the list:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Basic Matchers&lt;/li&gt;
	&lt;li&gt;Nested describes&lt;/li&gt;
	&lt;li&gt;Shared describes&lt;/li&gt;
	&lt;li&gt;Sandboxed Example Scope&lt;/li&gt;
	&lt;li&gt;Tested to work in FireFox&lt;/li&gt;
	&lt;li&gt;Basic HTML Reporter&lt;/li&gt;
	&lt;li&gt;Works with &lt;a href=&quot;http://www.mozilla.org/rhino/&quot;&gt;Rhino&lt;/a&gt; and &lt;a href=&quot;http://ajaxian.com/archives/johnson-wrapping-javascript-in-a-loving-ruby-embrace-and-arax&quot;&gt;Johnson&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Basic Console Reporter for &lt;a href=&quot;http://www.mozilla.org/rhino/&quot;&gt;Rhino&lt;/a&gt; and &lt;a href=&quot;http://ajaxian.com/archives/johnson-wrapping-javascript-in-a-loving-ruby-embrace-and-arax&quot;&gt;Johnson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;In The Near Future&amp;#8230;&lt;/h3&gt;
&lt;p&gt;While &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;Inspec&lt;/a&gt; is now working with basic matchers, here are a few things I&amp;#8217;d like to add:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Better syntax and organization of matchers for easier extensions. (Tempted to steal from &lt;a href=&quot;http://github.com/nkallen/screw-unit/tree/master&quot;&gt;Screw.Unit&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;More Matchers. (Makes everyone happy.)&lt;/li&gt;
	&lt;li&gt;Work on WScript environment.&lt;/li&gt;
	&lt;li&gt;Make sure compatibility with all major browsers. (Helps appricated)&lt;/li&gt;
	&lt;li&gt;Allow selective execution of Example groups / Examples.&lt;/li&gt;
	&lt;li&gt;Make a better HTML Reporter, that hooks into selective executions.&lt;/li&gt;
	&lt;li&gt;Better Documentations. (Helps appricated)&lt;/li&gt;
	&lt;li&gt;Better Error messages on Failure and Exception.&lt;/li&gt;
	&lt;li&gt;Package and maybe minify(why not?).&lt;/li&gt;
	&lt;li&gt;A LOT more rigid and concrete tests to reach 100% coverage. (Also serve as uage examples, helps appricated)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;For Developers&lt;/h3&gt;
&lt;p&gt;I have been very busy with my date job lately, and never have enough time to work on my own projects. Any help is very much appricated. So if you are interested in developing &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;Inspec&lt;/a&gt; together, just &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;fork me&lt;/a&gt;, make some improvements, rebase, push, and shoot me a pull request. If you are a regular contributor, your name will be in the co-author&amp;#8217;s list as well.&lt;/p&gt;
&lt;h3&gt;Suggestions? Comments?&lt;/h3&gt;
&lt;p&gt;While I primarily developed this for my own need. I hope this will benefit everyone who has similiar needs. So your suggestions and critics are very welcome. Tell me what you like about it, what you don&amp;#8217;t like about it, and how &lt;a href=&quot;http://github.com/aq1018/inspec&quot;&gt;Inspec&lt;/a&gt; can be improved. Sorry that there is nothing like google group or irc or mailing list setup yet. You can leave a comment here, and I will be notified automatically through email. If this project grows bigger, I will setup a google group and an irc channel. But for now, you can either leave a comment, or scroll down to the bottom of the page, and my contact information is on the lower right.&lt;/p&gt;













</content>
  </entry>
  
  <entry>
    <title>Javascript BDD Test Frameworks Compared</title>
    <link href="/articles/2009/04/12/javascript-bdd-test-frameworks-compared.html" />
    <id>tag:aaronqian.com,2009-04-12:1239544687</id>
    <updated>2009-04-12T21:58:07+08:00</updated>
    <content type="html">&lt;p&gt;Lately, I&amp;#8217;ve been trying to find a good JavaScript BDD style test framework, and I have come across a few of them such as &lt;a href=&quot;http://github.com/nkallen/screw-unit/tree/master&quot;&gt;Screw.Unit&lt;/a&gt;, &lt;a href=&quot;http://visionmedia.github.com/jspec/&quot;&gt;jSpec&lt;/a&gt;, and &lt;a href=&quot;http://jania.pe.kr/aw/moin.cgi/JSSpec&quot;&gt;JSSepc&lt;/a&gt;. They all have their own unique set of features, and are all very innovative. But I couldn&amp;#8217;t find a exact fit for my requirements. While they are all unique in their own ways, and provide some rather innovative approach to the BDD problem domain, they all have some drawbacks that I find either not acceptable or not easy to use.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s have a little analysis on the strength and weakness of each frameworks listed above. Ok, you must note that the strength and weakness I describe is obviously a subjective opinion of my own, that entirely pertains to my own need. You may find the weakness I mentioned to be a strength in your case. Don&amp;#8217;t flame me about it!&lt;/p&gt;
&lt;h3&gt;Screw.Unit&lt;/h3&gt;
&lt;p&gt;Screw.Unit is the one I found to be the closest to my needs, and I believe it is the most popular BDD JavaScript test framework at the momenent of this writing.&lt;/p&gt;
&lt;h4&gt;Things I like about Screw.Unit&lt;/h4&gt;
&lt;p&gt;A key feature of Screw.Unit is the support for nested &lt;code&gt;describes&lt;/code&gt; and the cascading &lt;code&gt;before&lt;/code&gt; (and &lt;code&gt;after&lt;/code&gt;) behavior. For presentation, it has a good HTML runner that generates good looking HTML pages to present the test results. You can also create custom matchers in a easy and declaritive manner to extend Screw.Unit. Because adding member functions to &lt;code&gt;Object&lt;/code&gt; is consider a bad practice, the use of &lt;code&gt;foo.should be_true&lt;/code&gt; cannot be done easily without polluting the Object prototype. However they came up with an alternative DSL that looks like this: &lt;code&gt;expect(foo).to(equal, true)&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;Things I don&amp;#8217;t like about Screw.Unit&lt;/h4&gt;
&lt;p&gt;However, there is a few things I don&amp;#8217;t like about it.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;No support for shared specs. (aka &lt;code&gt;it_should_behave_like&lt;/code&gt; in &lt;a href=&quot;http://rspec.info&quot;&gt;RSpec&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;Does not support commandline (due to dependcy on jQuery, DOM, and &lt;a href=&quot;http://http://github.com/nkallen/effen/tree/master&quot;&gt;concrete Javascript&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;Does not support server-side javascript (Same reason above)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;jSpec&lt;/h3&gt;
&lt;p&gt;jSpec is probably the most innovative JavaScript BDD, and sometimes I feel that it might be a bit too innovative&amp;#8230;&lt;/p&gt;
&lt;h4&gt;Things I like about jSpec&lt;/h4&gt;
&lt;p&gt;In jSpec, you don&amp;#8217;t write true JavaScript, but a higher level DSL, which later being parsed and converted to JavaScript and executed. It also supports nested &lt;code&gt;describes&lt;/code&gt; and &lt;code&gt;before&lt;/code&gt;, &lt;code&gt;after&lt;/code&gt; blocks. It has a wealth of matchers, and has formatters that supports DOM, console, and terminal. The size of the script is very small as well.&lt;/p&gt;
&lt;h4&gt;Things I don&amp;#8217;t like about jSpec&lt;/h4&gt;
&lt;p&gt;First, doesn&amp;#8217;t support shared behaviors.&lt;/p&gt;
&lt;p&gt;The DSL looks nice at first sight. In fact I almost mistook it as rSpec test suits. But after careful analysis, I have a few doubts about jSpec&amp;#8217;s DSL. First, from the source code, the DSL to JavaScript transformation is done using a few lines of Regex only. I&amp;#8217;m afraid that it might not work on edge cases. Next, I looked at the tests for the Regex transformation, and I found that the tests are not very strict either. Also, I think this makes error tracking rather difficult, since the DSL is transformed, it is hard to figure out where the error is if you run into some edge cases. I&amp;#8217;d rather write JavaScript and be at ease, instead of write poorly supported FrankensteinScript, and have no clue where went wrong.&lt;/p&gt;
&lt;p&gt;Another part I don&amp;#8217;t like about jSpec is the source code is rather cryptic. I have to say the author of jSpec is a very smart person. To me, his code is 50% recursive functional rocket science and 50% regex dark magic. It took me a long time to decrypt how the code is working under the hood, and I can&amp;#8217;t say I understood it 100%. This makes contributing and extending very difficult for most busy programmers (including me) that just want to get the things done.&lt;/p&gt;
&lt;h3&gt;JSSpec&lt;/h3&gt;
&lt;p&gt;JSSepc is probably the oldest Framework that started to tackle the BDD domain in JavaScript. The initial release is dated July 16, 2007. Its features are relatively simple compare to above two frameworks.&lt;/p&gt;
&lt;h4&gt;Things I like about jSpec&lt;/h4&gt;
&lt;p&gt;JSSepc&amp;#8217;s source code is simple and clean, and relatively easy to extend. It has very original syntax as well, Instead of using &lt;code&gt;expect(foo).to(equal, true)&lt;/code&gt;, its format is &lt;code&gt;value_of(foo).should().be_true()&lt;/code&gt;, a bit less sweet&amp;#8230; However, it is the first (I think) to tackle BDD in JavaScript, it is nice that they first invented this approach, and paved way for newer frameworks to learn from. The HTML report is very nice too. You can selectively run a set of suit right in the browser.&lt;/p&gt;
&lt;h4&gt;Things I don&amp;#8217;t like about jSpec&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;It doesn&amp;#8217;t support nested &lt;code&gt;describe&lt;/code&gt; blocks.&lt;/li&gt;
	&lt;li&gt;It doesn&amp;#8217;t support shared behaviors.&lt;/li&gt;
	&lt;li&gt;Not in active development. (Last commit was Dec. 2008)&lt;/li&gt;
&lt;/ul&gt;



</content>
  </entry>
  
  <entry>
    <title>Redcloth Ate My notextile Tag</title>
    <link href="/articles/2009/04/07/redcloth-ate-my-notextile.html" />
    <id>tag:aaronqian.com,2009-04-07:1239036237</id>
    <updated>2009-04-07T00:43:57+08:00</updated>
    <content type="html">&lt;p&gt;While playing with textile and UltraViolet in Webby, I found textile is re-rendering my UltraViolet generated HTML contents disregarding  tags. The problem is with UltraVilet versions 4.1.1 to 4.1.9 has ignored this tag somehow. There is even a &lt;a href=&quot;http://jgarber.lighthouseapp.com/projects/13054/tickets/119-notextile-blocks-included-in-following-paragrap&quot;&gt;bug ticket&lt;/a&gt; about it.&lt;/p&gt;
&lt;p&gt;The solution?&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;sudo gem uninstall RedCloth -a
sudo gem install RedCloth -v=4.1.0
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This installs RedCloth version 4.1.0 which doesn&amp;#8217;t eat your &lt;code&gt;&amp;lt;notextile&amp;gt;&lt;/code&gt; tags and behave correctly for me.&lt;br /&gt;
Next I just did a &lt;code&gt;webby rebuild&lt;/code&gt; and everything worked out for me!&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Adding Blog Tags using Webby</title>
    <link href="/articles/2009/04/06/adding-blog-tags-using-webby.html" />
    <id>tag:aaronqian.com,2009-04-06:1239016320</id>
    <updated>2009-04-06T19:12:00+08:00</updated>
    <content type="html">&lt;p&gt;The blog now looks better and better, but it is still missing a key feature &amp;#8212; tags.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s bust it out! Here is my plan:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Adding a tags attribute under each blog&amp;#8217;s meta data&lt;/li&gt;
	&lt;li&gt;Make a helper that reads each blog and count the occurance of each tag&lt;/li&gt;
	&lt;li&gt;Make a partial that links to each tags&lt;/li&gt;
	&lt;li&gt;Make a rake task that auto generates tags folder&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Adding a tags attribute under each blog&amp;#8217;s meta data&lt;/h3&gt;
&lt;p&gt;This is easy, just open up a post and add a &lt;b&gt;tags&lt;/b&gt; attribute to the meta data:&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;Entity&quot;&gt;title         &lt;span class=&quot;Entity&quot;&gt;:&lt;/span&gt;&lt;/span&gt;   &lt;span class=&quot;String&quot;&gt;Adding Blog Tags using Webby&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;Entity&quot;&gt;created_at    &lt;span class=&quot;Entity&quot;&gt;:&lt;/span&gt;&lt;/span&gt;   &lt;span class=&quot;String&quot;&gt;2009-04-06 19:12:00.343030 +08:00&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;Entity&quot;&gt;blog_post     &lt;span class=&quot;Entity&quot;&gt;:&lt;/span&gt;&lt;/span&gt;   &lt;span class=&quot;String&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;erb&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;textile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; Add some tags for this post&lt;/span&gt;
&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;ruby&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;webby&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Make tags helper&lt;/h3&gt;
&lt;p&gt;All I need to do is to make a tags helper module that does the counting for me, and register it with Webby. Here is the code:&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; lib/tags_helper.rbS&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;TagsHelper&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;  &lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; find all blog posts&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;posts&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;limit&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;all&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;,&lt;/span&gt; find_options&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;)
    options &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; { &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;in_directory&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;articles&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, 
                &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;recursive&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;,
                &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;blog_post&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;,
                &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;sort_by&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;created_at&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
                &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;reverse&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;}
    options.&lt;span class=&quot;Entity&quot;&gt;merge!&lt;/span&gt;(find_options) &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; find_options
    ::&lt;span class=&quot;Entity&quot;&gt;Webby&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Resources&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;pages&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;find&lt;/span&gt;(limit, options)
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;tags_hash&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;tags_hash&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;tags_hash&lt;/span&gt;
    &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;tags_hash&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; {}
    posts.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;post&lt;/span&gt;|
      post.&lt;span class=&quot;Entity&quot;&gt;tags&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;tag&lt;/span&gt;|
        &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;tags_hash&lt;/span&gt;[tag] &lt;span class=&quot;Keyword&quot;&gt;||=&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;tags_hash&lt;/span&gt;[tag] &lt;span class=&quot;Keyword&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;if&lt;/span&gt; post.&lt;span class=&quot;Entity&quot;&gt;tags&lt;/span&gt;
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;Variable&quot;&gt;&lt;span class=&quot;Variable&quot;&gt;@&lt;/span&gt;tags_hash&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;Keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Entity&quot;&gt;posts_with_tag&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;tag&lt;span class=&quot;Variable&quot;&gt;,&lt;/span&gt; limit&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;all&lt;/span&gt;&lt;span class=&quot;Variable&quot;&gt;,&lt;/span&gt; find_options&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;nil&lt;/span&gt;&lt;/span&gt;)
    &lt;span class=&quot;Entity&quot;&gt;posts&lt;/span&gt;(limit, find_options) &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;post&lt;/span&gt;|
      post.&lt;span class=&quot;Entity&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; post.&lt;span class=&quot;Entity&quot;&gt;tags&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;include?&lt;/span&gt;(tag)
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;Support&quot;&gt;Webby&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Helpers&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;register&lt;/span&gt;(&lt;span class=&quot;Variable&quot;&gt;TagsHelper&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;posts&lt;/code&gt; is a handy little short cut for getting all blog posts, much shorter to type. You can also pass in the &lt;code&gt;limit&lt;/code&gt;, and &lt;code&gt;find_options&lt;/code&gt; to customize your find. Example:&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt; finding first 10 posts in blogs dir, and sorted in descending chronological order&lt;/span&gt;
&lt;span class=&quot;Entity&quot;&gt;posts&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;in_directory&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;blogs&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;sort_by&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;created_at&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;reverse&lt;/span&gt; =&amp;gt; &lt;span class=&quot;Constant&quot;&gt;true&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;tags_hash&lt;/code&gt; returns a hash with tag name and occurance as the key and value.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;posts_with_tag&lt;/code&gt; finds all the blog posts related to a tag.&lt;/p&gt;
&lt;h3&gt;Make a partial&lt;/h3&gt;
&lt;p&gt;Now that we have the helper, we can make a partial that displays the tags. I made it in HAML:&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;ul&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;  &lt;span class=&quot;Comment&quot;&gt;/&lt;/span&gt; sort tags in alphabetical order, and then generate links for each tag&lt;/span&gt;
  -tags_hash.&lt;span class=&quot;Entity&quot;&gt;keys&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;sort&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt; |tag|
    &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;li&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;MetaTag&quot;&gt;&lt;span class=&quot;MetaTag&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;MetaTag&quot;&gt;a&lt;/span&gt;&lt;/span&gt;{&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;href&lt;/span&gt;=&amp;gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;/tags/&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;tag&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}= tag
      =&lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt;(&lt;span class=&quot;Comment&quot;&gt;#{tags_hash[tag]})&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can see the partial in effect on the lower right side of the page in footer. This is basic and nothing fancy&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Make a Rake Task&lt;/h3&gt;
&lt;p&gt;Now the tags are in place, we want actually display the tags pages. We make a new rake task to generate all the tags page for us.&lt;/p&gt;
&lt;div class=&quot;UltraViolet&quot;&gt;
&lt;pre class=&quot;blackboard&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;&lt;span class=&quot;Comment&quot;&gt;#&lt;/span&gt;tags.rake&lt;/span&gt;

&lt;span class=&quot;Keyword&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;lib/tags.rb&lt;span class=&quot;String&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;Keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;Variable&quot;&gt;TagsHelper&lt;/span&gt;
namespace &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;tags&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
  desc &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;auto generate all tags page&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  task &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;generate&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    ::&lt;span class=&quot;Entity&quot;&gt;Webby&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;load_files&lt;/span&gt;
    tags_hash.&lt;span class=&quot;Entity&quot;&gt;keys&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do &lt;/span&gt;|&lt;span class=&quot;Variable&quot;&gt;tag&lt;/span&gt;|
      dir &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Webby&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;site&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;tags_dir&lt;/span&gt;
      page &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;join&lt;/span&gt;(dir, &lt;span class=&quot;Support&quot;&gt;File&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;basename&lt;/span&gt;(tag))
      page &lt;span class=&quot;Keyword&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Webby&lt;/span&gt;::&lt;span class=&quot;Entity&quot;&gt;Builder&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;create&lt;/span&gt;(page, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;from&lt;/span&gt; =&amp;gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;Support&quot;&gt;Webby&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;site&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;Entity&quot;&gt;template_dir&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;String&quot;&gt;}&lt;/span&gt;&lt;/span&gt;/tags/generate.erb&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
                 &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;locals&lt;/span&gt; =&amp;gt; {&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;tag&lt;/span&gt; =&amp;gt; tag, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;directory&lt;/span&gt; =&amp;gt; dir})
    &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  
  desc &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;remove all tags page&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  task &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;remove&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;do&lt;/span&gt;
    rm_r &lt;span class=&quot;Support&quot;&gt;Webby&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;site&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;content_dir&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;/&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;Keyword&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;Support&quot;&gt;Webby&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;site&lt;/span&gt;.&lt;span class=&quot;Entity&quot;&gt;tags_dir&lt;/span&gt;
  &lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
  
  desc &lt;span class=&quot;String&quot;&gt;&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;regenerate all tags page&lt;span class=&quot;String&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  task &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;regenerate&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;remove&lt;/span&gt;, &lt;span class=&quot;Constant&quot;&gt;&lt;span class=&quot;Constant&quot;&gt;:&lt;/span&gt;generate&lt;/span&gt;]
&lt;span class=&quot;Keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You will also need the corresponding &lt;code&gt;templates/tags/generate.erb&lt;/code&gt;, which you can find in &lt;a href=&quot;http://github.com/aq1018/aaron-blog/&quot;&gt;my github account&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>This Blog is Made using Webby</title>
    <link href="/articles/2009/04/06/this-blog-is-made-using-webby.html" />
    <id>tag:aaronqian.com,2009-04-06:1238950260</id>
    <updated>2009-04-06T00:51:00+08:00</updated>
    <content type="html">&lt;p&gt;After a few days of work, I finally finished the layout for my blog. During the construction of this blog, I wanted to use a very light framework. Being mainly a Ruby On Rails developer I found a ruby framework called &lt;a href=&quot;http://webby.rubyforge.org/&quot;&gt;Webby&lt;/a&gt; that works perfectly with my requirements.&lt;/p&gt;
&lt;p&gt;From the Webby describes itself as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Webby is a fantastic little website management system. It would be called a content management system if it were a bigger kid. But, it’s just a runt with a special knack for transforming text. And that’s really all it does – manages the legwork of turning text into something else, an ASCII Alchemist if you will.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sounds nice?&lt;/p&gt;
&lt;p&gt;It supports ERB, haml, sass, Textile, Markdown and a set of other arsenels you can use at your disposal. Another reason I choose Webby is because it supports &lt;a href=&quot;http://ultraviolet.rubyforge.org/&quot;&gt;UltraViolet&lt;/a&gt; which comes in handy when you need to demonstrate a few lines of code. Even though it also supports &lt;a href=&quot;http://coderay.rubychan.de/&quot;&gt;CodeRay&lt;/a&gt; , but I much perfer UltraViolet as it supports a lot more css hightlighting templates and languages.&lt;/p&gt;
&lt;p&gt;Another highlight of Webby is that it uses A CSS framework called &lt;a href=&quot;http://code.google.com/p/blueprintcss/&quot;&gt;BluePrint&lt;/a&gt; This little CSS framework makes website layout a breeze. Plus it has a powerful customization utility that can generate custom sized grid with meaningful class names.&lt;/p&gt;
&lt;h3&gt;What about commenting?&lt;/h3&gt;
&lt;p&gt;As Maxime once commented about my idea of using Webby to generate a static Blog:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;A blog without comments aint a blog!&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sure, you&amp;#8217;ve got a point! My answer to this problem is &lt;a href=&quot;http://disqus.com/&quot;&gt;Disqus&lt;/a&gt;. It provides a JavaScript Widget that handles all the blog comments for you. No more custom coding for comments, wrestling with SPAM, etc. Just drop in their code, and sit and relax. You&amp;#8217;ve got a powerful commenting system on your blog already! Sweet&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Lastly, a Gift if you care&lt;/h3&gt;
&lt;p&gt;if the idea of making a blog with Webby sounds nice to you, maybe you can give it a try as well!&lt;/p&gt;
&lt;p&gt;The source of this blog is &lt;a href=&quot;http://github.com/aq1018/aaron-blog&quot;&gt;hosted&lt;/a&gt; on &lt;a href=&quot;http://github.com/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anyways, it was a lot of fun playing around using this little powerful framework, and through fun experiments, a blog is actually born! Life is beautiful&amp;#8230;&lt;/p&gt;</content>
  </entry>
  
</feed>
