<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

  <title>solnic.eu</title>
  
  <link href="http://solnic.eu/" />
  <updated>2012-02-08T12:05:34+01:00</updated>
  <id>http://solnic.eu/</id>
  <author>
    <name>Piotr Solnica</name>
    
  </author>

  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/solnic-on-blog" /><feedburner:info uri="solnic-on-blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>New Virtus Release With Truly Awesome Features</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/L6w_yELfS3k/new-virtus-release-with-truly-awesome-features.html" />
    <updated>2012-02-08T10:18:00+01:00</updated>
    <id>http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features</id>
    <content type="html">&lt;p&gt;Just a quick announcement that I just pushed a &lt;a href="https://rubygems.org/gems/virtus/versions/0.2.0"&gt;new version&lt;/a&gt; of &lt;a href="https://github.com/solnic/virtus"&gt;Virtus&lt;/a&gt; with support for long awaited features: EmbeddedValue, member type coercions for array/set attributes and ValueObject. Current version is 0.2.0, please give it a try and tell me what you think.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s a quick sneak-preview of what you can do with Virtus:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;virtus_examples.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;span class=’line-number’&gt;29&lt;/span&gt;
&lt;span class=’line-number’&gt;30&lt;/span&gt;
&lt;span class=’line-number’&gt;31&lt;/span&gt;
&lt;span class=’line-number’&gt;32&lt;/span&gt;
&lt;span class=’line-number’&gt;33&lt;/span&gt;
&lt;span class=’line-number’&gt;34&lt;/span&gt;
&lt;span class=’line-number’&gt;35&lt;/span&gt;
&lt;span class=’line-number’&gt;36&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GeoLocation&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ValueObject&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Float&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:lng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Float&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;City&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="no"&gt;GeoLocation&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:districts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nb"&gt;Integer&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;City&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="ss"&gt;:age&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="ss"&gt;:city&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="ss"&gt;:name&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;NYC&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="ss"&gt;:location&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:lat&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1234567.89&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:lng&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;9876543.21&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="ss"&gt;:districts&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;three&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1234567.89&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;districts&lt;/span&gt;    &lt;span class="c1"&gt;# =&amp;gt; [ :one, :two, :three ]&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;I hope you&amp;#8217;re going to enjoy it and find it useful in your projects. In case of any issues please report them on &lt;a href="https://github.com/solnic/virtus/issues"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Huge props go to &lt;a href="https://github.com/dkubb"&gt;Dan Kubb&lt;/a&gt;, &lt;a href="https://github.com/emmanuel"&gt;Emmanuel Gomez&lt;/a&gt; and &lt;a href="https://github.com/senny"&gt;Yves Senn&lt;/a&gt; for helping me with recent releases! Thanks guys!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/L6w_yELfS3k" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2012/02/08/new-virtus-release-with-truly-awesome-features.html</feedburner:origLink></entry>
  
  <entry>
    <title>Yes, You Should Write Controller Tests!</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/TeAFSW_V-vs/yes-you-should-write-controller-tests.html" />
    <updated>2012-02-02T12:25:00+01:00</updated>
    <id>http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests</id>
    <content type="html">&lt;p&gt;It really surprises me that there are people arguing that writing controller tests doesn&amp;#8217;t make sense. Probably the most common argument is that actions are covered in acceptence tests along with checking if views are properly rendered. Right? Right&amp;#8230;well that&amp;#8217;s just wrong! Are you trying to say that your slow acceptance tests are covering every possible controller action scenario? Are you trying to say that, for instance, every redirect that should take place is tested within an &lt;em&gt;acceptance test&lt;/em&gt;? Are you also checking every invalid request in acceptance tests? Are you telling me that your acceptance test suite takes 27 hours and 13 minutes to finish because you fully test your controllers there?! Oh I&amp;#8217;m sure that your acceptance test suite runs faster and you probably cover only &amp;#8216;the happy scenarios&amp;#8217; there&amp;#8230;which basically means you miss A LOT of test coverage.&lt;/p&gt;

&lt;h2&gt;A Simple Fact About a Controller&lt;/h2&gt;

&lt;p&gt;Here&amp;#8217;s a simple fact about a controller - &lt;em&gt;it&amp;#8217;s a class with methods&lt;/em&gt;! Yes, it&amp;#8217;s a class with methods I repeat. It should have tests. Every method (action) should be covered by a test.&lt;/p&gt;

&lt;p&gt;Why? Well, for the same reason that you write tests for any other class in your application. We want to make sure that our code behaves like expected. It&amp;#8217;s also much easier to keep your controllers thin when you have tests. If it&amp;#8217;s trivial to write a test for a controller then it&amp;#8217;s probably a well implemented controller. If you&amp;#8217;re drowning in mocks then you probably want to refactor your controller.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an example of a users controller with a sample create action:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;users_controller.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;before_filter&lt;/span&gt; &lt;span class="ss"&gt;:load_group&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;rescue_from&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordNotFound&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:not_found&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;persisted?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="n"&gt;users_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:notice&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;User created!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_group&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:group_id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;As you can see we load a group object in the before filter and then we use that object to create a new user. Pretty dead-simple. If you just write an acceptance spec for this controller I bet you will not cover the case when the group cannot be found. After all people usually write acceptance tests for optimistic scenarios. If they want to cover every case then I&amp;#8217;m sure they will miss the deadline ;)&lt;/p&gt;

&lt;p&gt;But it&amp;#8217;s not just about covering every path! It&amp;#8217;s also about the quality of the code. When you look at the example above you probably won&amp;#8217;t see any code smells, right? OK so let me write a spec for the create action:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;users_controller_spec.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;span class=’line-number’&gt;29&lt;/span&gt;
&lt;span class=’line-number’&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;UsersController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;#create&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:group_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;group_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;group&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;users&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:find&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;when attributes are valid&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;saves the user and redirects to the index page&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:persisted?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;when attributes are not valid&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;saves the user and redirects to the index page&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:persisted?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;What happens there? Because we reach deeper into group object, get its users and then use it to build a new user the spec requires more mocks then it should. This is a trivial example but you can probably imagine how a spec would look like if the action was more complicated, had more branching logic and even more &lt;em&gt;structural coupling&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s quickly make a small refactor of the action:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;users_controller.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# stuff&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;persisted?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="n"&gt;users_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:notice&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;User created!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# more stuff&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now the spec will be a bit simpler:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;users_controller_spec.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;UsersController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;#create&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:group_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;group_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;group&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:find&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:create_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;when attributes are valid&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;saves the user and redirects to the index page&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:persisted?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;when attributes are not valid&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;saves the user and redirects to the index page&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:persisted?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;We should also add an example checking the case where a group is not found. This is going to be a rather rare case but this doesn&amp;#8217;t change the fact that we should have a test for it:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;users_controller_spec.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;UsersController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:group_id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;group_id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;group&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;#create&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;when group is not found&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:find&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;          &lt;span class="n"&gt;and_raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:not_found&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;That&amp;#8217;s it! Small test, fast test. Code is covered. Controller is thin. Now it&amp;#8217;s probably a good idea to write some views specs for users controller too but I&amp;#8217;m not going to write about it here, that&amp;#8217;s boring ;)&lt;/p&gt;

&lt;h2&gt;Summing up&lt;/h2&gt;

&lt;p&gt;Yes, you should write tests for controllers. Whenever somebody asks you if he/she should write them, your answer should be &amp;#8216;yes!&amp;#8217;. There are no good arguments against writing controller tests. It&amp;#8217;s code after all, it should be covered by tests. Let the tests drive your design and you will be happy with your controllers, otherwise you might end up with a mess. Without proper tests you won&amp;#8217;t be able to truly verify if your controllers are thin and well designed. So please go and write controller tests!&lt;/p&gt;

&lt;p&gt;In case you missed it you might want to read Avdi&amp;#8217;s great post about &lt;a href="http://avdi.org/devblog/2011/07/05/demeter-its-not-just-a-good-idea-its-the-law/"&gt;&amp;#8220;Law of Demeter&amp;#8221;&lt;/a&gt; where he writes about structural coupling which is mentioned in this post too.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/TeAFSW_V-vs" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html</feedburner:origLink></entry>
  
  <entry>
    <title>Ruby DataMapper Status</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/Jlg-obA72wU/ruby-datamapper-status.html" />
    <updated>2012-01-10T00:00:00+01:00</updated>
    <id>http://solnic.eu/2012/01/10/ruby-datamapper-status</id>
    <content type="html">&lt;p&gt;In my recent post I gave you a brief
overview of what I think about &lt;a href="http://solnic.eu/2011/11/29/the-state-of-ruby-orm.html"&gt;the state of Ruby ORMs&lt;/a&gt;.
Since I’m involved in the development of &lt;a href="http://datamapper.org"&gt;DataMapper&lt;/a&gt;
project I want to write a little more lines of text to give you a good overview
of the current state of DataMapper project and how the future version 2.0 is
going to look like.&lt;/p&gt;

&lt;h2&gt;DataMapper 1.x&lt;/h2&gt;

&lt;p&gt;Let’s get this straight once and for all: DataMapper was never a pure
implementation of the Data Mapper pattern. It has elements of both Data Mapper
and Active Record patterns. It has a mapping layer where you can configure
mappings between model properties and database columns but this doesn’t change
the fact that your models have direct access to the persistence layer and a lot
of persistence-related functionality is mixed into them. This is what makes
DataMapper an ‘ActiveRecord-ish’ library. After a few years of development it’s
become clear that this approach, despite its advantages over ActiveRecord, is
still not good enough.&lt;/p&gt;

&lt;p&gt;Probably one of the biggest wins of DataMapper is support for many different
kinds of data stores. Apart from supporting most common RDBMS databases there are
adapters for various key-value stores, NoSQL databases and more. The flip side
is that working with multiple data stores at once is not very stable at the
moment and that you can’t easily use the full power of various databases, like
MongoDB, due to limitations in DataMapper’s API.&lt;/p&gt;

&lt;p&gt;The good news is that while working on DataMapper and many of its adapters we’ve
learned our lessons. With all that knowledge and experience the work on
DataMapper 2.0 has been started.&lt;/p&gt;

&lt;h2&gt;DataMapper 2.0&lt;/h2&gt;

&lt;p&gt;First of all the next major version of DataMapper will implement the Data Mapper
pattern as described in the PoEAA:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.&lt;/p&gt;&lt;footer&gt;&lt;strong&gt;Martin Fowler&lt;/strong&gt; &lt;cite&gt;&lt;a href=’http://martinfowler.com/eaaCatalog/dataMapper.html’&gt;martinfowler.com/eaaCatalog/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/footer&gt;&lt;/blockquote&gt;


&lt;p&gt;DataMapper 2 won’t be a big monolithic library, it will consist of multiple
independent pieces that are glued together. Each piece of DM2 is a standalone
library so that you could use it separately from the DM itself.&lt;/p&gt;

&lt;p&gt;Let me describe all the related projects.&lt;/p&gt;

&lt;h3&gt;Veritas - the new relational algebra engine&lt;/h3&gt;

&lt;p&gt;The core of DM2 is &lt;a href="https://github.com/dkubb/veritas"&gt;Veritas&lt;/a&gt; - the new
relational algebra engine developed by Dan Kubb. Why not ARel? The answer is
simple - ARel is designed to generate SQL whereas DataMapper needs something more
abstract with adapters that can handle different kinds of query dialects. With
that premise Veritas is a full-featured relational algebra implementation and
there’s already an &lt;a href="https://github.com/dkubb/veritas-sql-generator"&gt;SQL generator&lt;/a&gt;
which can build pretty complex queries. More generators will be written soon.&lt;/p&gt;

&lt;p&gt;Here’s a quick sneak-preview of how you can build relations with Veritas:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;veritas-sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;span class=’line-number’&gt;29&lt;/span&gt;
&lt;span class=’line-number’&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;header_one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="nb"&gt;Integer&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;header_two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="nb"&gt;Integer&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Integer&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;tuples_one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;john&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;jane&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;tuples_two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;john&amp;#39;s project&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;jane&amp;#39;s project&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="c1"&gt;# build base relations&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;relation_one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Veritas&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Relation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header_one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tuples_two&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;relation_two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Veritas&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Relation&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header_two&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tuples_two&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="c1"&gt;# rename conflicting attributes&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;relation_two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;relation_two&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:project_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="c1"&gt;# join the two relations on id == user_id&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;new_relation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;relation_one&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relation_two&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;What’s great about Veritas is that with its level of abstraction you can use
it for various things - not just to generate queries. For example there’s an
idea of using Veritas to build a new “migrations” library for DM2 that will
easily handle even very complex scenarios.&lt;/p&gt;

&lt;h3&gt;Virtus - the new model definition and introspection layer&lt;/h3&gt;

&lt;p&gt;I’ve already introduced &lt;a href="http://solnic.eu/2011/06/06/virtus—attributes-for-your-plain-ruby-objects.html"&gt;Virtus&lt;/a&gt;
- it’s an extraction of DataMapper’s Property API. During the last few months we’ve made many
significant improvements and more features will be added soon too. Virtus
already supports defining attributes on your models and can handle many kinds
of coercions. You can also implement your own coersion methods if you need them.
In the near future Virtus will be supporting more complex functionality like
&lt;a href="http://martinfowler.com/eaaCatalog/embeddedValue.html"&gt;EmbeddedValue&lt;/a&gt; and
&lt;a href="http://martinfowler.com/eaaCatalog/valueObject.html"&gt;ValueObject&lt;/a&gt;. It’s also
possible that with Virtus you will be able to define relationships between POROs.&lt;/p&gt;

&lt;p&gt;The important thing about Virtus is that it’s designed to work with PORO and
it has nothing to do with any persistence concerns. For example there were
people asking me about things like support for dirty attributes tracking - it’s
not going to be included in Virtus.&lt;/p&gt;

&lt;p&gt;I should mention that &lt;em&gt;DataMapper 2.0 will be designed to work with POROs&lt;/em&gt; that &lt;em&gt;are
not&lt;/em&gt; extended by Virtus. Virtus will be optional but since it provides a very
common functionality I suspect most people will want to use it.&lt;/p&gt;

&lt;h3&gt;Aequitas - the new validation library&lt;/h3&gt;

&lt;p&gt;Developed by Emmanuel Gomez, &lt;a href="https://github.com/emmanuel/aequitas"&gt;Aequitas&lt;/a&gt; is
designed to work with any Ruby object and it also has support for Virtus. The
idea is similar to what we have in DataMapper 1.x where validations can be
derived from property declarations. Aquitas is based on the current
&lt;a href="https://github.com/datamapper/dm-validations"&gt;dm-validations&lt;/a&gt; and the API is
very similar, if not identical. Aequitas has support for custom error messages,
I18n, validation contexts and built-in data types which come with their own set
of validation rules.&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;aequitas_example.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;virtus&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;aequitas/virtus_integration&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Aequitas&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:required&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:published_at&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid?&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [ &amp;quot;can&amp;#39;t be blank&amp;quot; ]&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [ &amp;quot;must be a date&amp;quot; ]&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h3&gt;Session, Dirty Tracking and Unit of Work&lt;/h3&gt;

&lt;p&gt;In the Data Mapper world every change made to the models loaded into memory is
tracked by a specialized object which works like a session. When you’re done
with making changes you can either commit them or rollback. The important thing
is that all the complex logic behind tracking what was changed, what was deleted
and what was added is handled by the session object. Your models are dumb in
this regard, they don’t care about dirty tracking, it’s not their responsibility.
It’s one of the major differences between AR and DM.&lt;/p&gt;

&lt;p&gt;The session object will be an implementation of the Unit of Work pattern described in PoEAA as:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Maintains a list of objects affected by a business transaction and coordinates&lt;br/&gt;the writing out of changes and the resolution of concurrency problems.&lt;/p&gt;&lt;footer&gt;&lt;strong&gt;Martin Fowler&lt;/strong&gt; &lt;cite&gt;&lt;a href=’http://martinfowler.com/eaaCatalog/unitOfWork.html’&gt;martinfowler.com/eaaCatalog/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/footer&gt;&lt;/blockquote&gt;


&lt;p&gt;More technically speaking a session will hold a &lt;a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph"&gt;DAG&lt;/a&gt;
of commands sorted by their dependencies so that when you commit the
session it will know in what order those commands should be executed.&lt;/p&gt;

&lt;p&gt;When you think about it you will realize that this pattern is quite common.
That’s why it would probably make sense to come up with a general UoW library
and then create an extended version for DataMapper needs.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an example of how such a session &lt;em&gt;may&lt;/em&gt; look like:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample_uow_session.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;DataMapper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;John&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rollback&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h3&gt;The Mapper&lt;/h3&gt;

&lt;p&gt;Probably &lt;a href="https://github.com/datamapper/dm-core"&gt;dm-core&lt;/a&gt;, the current core
DataMapper library, will be completely rewritten and become the mapper layer
with a thin query API that delegates most of the heavy work down to a veritas
adapter. For your convenience there will be a veritas mapper class that you
can inherit from but this doesn’t mean that you won’t be able to write
custom mapper classes. The idea is really simple here, a mapper class defines
mappings between PORO and the database schema. In most of the cases this means
a direct 1:1 mapping but the huge advantage is that once you need something
custom - you will be able to define it.&lt;/p&gt;

&lt;p&gt;This is really the key aspect of using a data mapper library - you define your
domain objects so that they correspond to your real world domain as close as
possible. It makes applying practices like &lt;a href="http://confreaks.net/videos/641-gogaruco2011-fast-rails-tests"&gt;“Fast Rails Tests”&lt;/a&gt;
suggested by Corey Haines come in a natural way because you’ll be implementing
the business logic in POROs and have them unit tested in an isolation without
the database access.&lt;/p&gt;

&lt;p&gt;You will be able to define a mapper class more or less like this:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;example_mapper.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="no"&gt;IdentityField&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:birthday_year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Integer&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Mapper&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;VeritasMapper&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# default 1:1 mapping&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# custom field name&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:email_address&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# map to 2 fields&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# map to a result of a function call&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="ss"&gt;:birthday_year&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:birthday_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:function&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:date&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Roadmap? ETA?&lt;/h2&gt;

&lt;p&gt;There&amp;#8217;s a work-in-progress roadmap for DM2 available &lt;a href="https://github.com/datamapper/dm-core/wiki/Roadmap"&gt;here&lt;/a&gt;.
Regarding ETA it&amp;#8217;s really hard to say. We&amp;#8217;re taking our time to build all these
libraries, there&amp;#8217;s a big focus on code quality and proper test &lt;em&gt;and&lt;/em&gt; docs coverage.
Once the roadmap is finalized we will be able to come up with some ETA.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the full list of related projects on &lt;a href="https://github.com"&gt;Github&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas"&gt;veritas&lt;/a&gt; - core library&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas-sql-generator"&gt;veritas-sql-generator&lt;/a&gt; - SQL generator&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas-do-adapter"&gt;veritas-do-adapter&lt;/a&gt; - DataObjects adapter&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dkubb/veritas-optimizer"&gt;veritas-optimizer&lt;/a&gt; - relation optimizer&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/virtus"&gt;virtus&lt;/a&gt; - attributes/coercions&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/emmanuel/aequitas"&gt;aequitas&lt;/a&gt; - validations&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&amp;#8230;and more will come soon, so stay tuned!&lt;/p&gt;

&lt;p&gt;Make sure to follow &lt;a href="http://twitter.com/datamapper"&gt;@datamapper&lt;/a&gt; on twitter too :)&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re eager to learn more you can always join #datamapper IRC channel. I
also understand that this post doesn&amp;#8217;t answer many possible questions - feel
free to ask them in the comments.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/Jlg-obA72wU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2012/01/10/ruby-datamapper-status.html</feedburner:origLink></entry>
  
  <entry>
    <title>The State of Ruby ORM</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/j2lBVEt1oeg/the-state-of-ruby-orm.html" />
    <updated>2011-11-29T10:11:00+01:00</updated>
    <id>http://solnic.eu/2011/11/29/the-state-of-ruby-orm</id>
    <content type="html">&lt;p&gt;We have a lot of different Object-Relational Mapper implementations in Ruby (and a ton and a half of Mongo mappers ;)) and it&amp;#8217;s probably a good thing. It seems like the only ORM that really matters right now is ActiveRecord although in &amp;#8220;the background&amp;#8221; we still have DataMapper and Sequel with growing communities. So I&amp;#8217;m wondering&amp;#8230;what&amp;#8217;s the state of these ORMs? This post is my brain-dump on the subject with a potential to start a disccusion about the future of Ruby ORMs. This is a huge subject but I&amp;#8217;ll keep it short.&lt;/p&gt;

&lt;h2&gt;(beloved) ActiveRecord&lt;/h2&gt;

&lt;p&gt;I’ve been a rails developer for almost 5 years now and I remember my initial excitement about ActiveRecord just like if it happened yesterday. I remember how blown away I was when I saw ‘an empty’ class in app/models with a ton of functionality added dynamically. I remember how happy I was when I started setting up associations for the first time and seeing that I can easily use them and everything just works OOTB. I remember how awesome it was to use built-in validations - a few lines of simple ruby code and my model is “secured” and invalid data won’t be persisted. Just like that! I also remember what a great feeling it was to use migrations for the first time, oh man there was even a generator which creates files for me, wonderful! Yeah, that was really great and I loved it.&lt;/p&gt;

&lt;p&gt;Years were passing and my excitement was slowly disappearing and now it’s almost completely gone. Why? What happened? First of all I’m disappointed with AR3. I thought transition to ARel and the general Rail3 refactor will lead to a better codebase and nicer API. What we have now is like a hybrid of AR2 and something that was promised as AR3 which was not finished in 100%.  The general lack of consistency in the API worries me. Too bad because making a major bump in the version number was a great opportunity to clean things up for good. Now we have to wait for 4.0. I’m also still facing various “WTF moments” when I see things like that:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;wtf-ar.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:active&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kind_of?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Enumerable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Yeah I know that’s just rude to point things like that, right? On the other hand is this what you would expect from a library which has a version number &gt; 3.0? I’d expect some level of maturity but what I see now is still a bit of a mess. It’s definitely getting better so probably, with this level of support that AR has now, version ~5.0 will be truly great and mature. I’m really looking forward to that.&lt;/p&gt;

&lt;p&gt;Through all those years ActiveRecord got a lot of great features though. Lazy
queries, attribute serializers, prepared statements just to name a few.
Extracting ActiveModel was also a huge step into the right direction and I&amp;#8217;m
very happy with it. It&amp;#8217;s all great and the improvement is clearly visible.&lt;/p&gt;

&lt;p&gt;On the other hand there are still cases where ActiveRecord fails. For instance it still has
problems with proper handling of object graph. Which isn&amp;#8217;t a great surprise
because &lt;em&gt;it&amp;#8217;s a tough problem to solve&lt;/em&gt; and none of the 3 ORMs has solved it
yet.&lt;/p&gt;

&lt;h2&gt;(bold) &lt;a href="http://datamapper.org"&gt;DataMapper&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;With ActiveRecord you get things done, that’s true. Just read the recent post from Xavier Shay &lt;a href="http://rhnh.net/2011/11/29/datamapper-retrospective"&gt;&amp;#8220;DataMapper Retrospective&amp;#8221;&lt;/a&gt; where he writes why he likes DataMapper and despite that why he chooses ActiveRecord. He writes &amp;#8220;This is my responsible choice at the moment&amp;#8221; - I would expect that in many, many cases people pragmaticaly and wisely choose ActiveRecord because the support from community is important and ActiveRecord does have the best support at the moment. When you get yourself into trouble with AR you will likely find help relatively quickly.&lt;/p&gt;

&lt;p&gt;After reading Xavier’s post I feel obliged to comment on it. First of all I agree with him and his decisions. DataMapper is trying to solve bigger problems than AR and Sequel. It’s obviously much harder to support any kind of a storage system and it requires a lot of work. It definitely requires more than a couple of years of development and one stable version. DataMapper 1.x series was a great milestone as the API became stable and it’s truly great, just look at this:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="c1"&gt;# DataMapper&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:created_at&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lt&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="c1"&gt;# ActiveRecord&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:posts&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:comment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:comments&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:created_at&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lt&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;DataMapper introduced a lot of fantastic solutions and just recently ActiveRecord started catching up. It doesn’t change the fact that DataMapper 1.x is much harder to use when you have to resort to raw SQL. That’s why I perfectly understand why Xavier prefers AR and Sequel - both ORMs are built specifically to handle RDBMS and they do it in a decent way.&lt;/p&gt;

&lt;p&gt;This post would get too big if I started to write more about DataMapper that’s why I’m stopping now. I will write about what’s happening in the DataMapper camp in a separate post where I will give you an overview of our plans for the near future - expect a lot of goodness to say the least.&lt;/p&gt;

&lt;p&gt;To quickly sum up - DataMapper is not there either but getting to the point
where we are now was a great experience that&amp;#8217;s given us knowledge about how certain problems should
be solved. More about this in a separate post&amp;#8230;&lt;/p&gt;

&lt;h2&gt;(impressive) &lt;a href="http://sequel.rubyforge.org"&gt;Sequel&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;I’ve never been a sequel user. I only tried it out a couple of times in the past and it was really nice. The codebase looks much cleaner than in case of ActiveRecord and the feature set is truly impressive. I’m also absolutely amazed that this project has 0 issues on github - HUGE congratulations to Jeremy Evans. He’s doing a fantastic work and I’m really impressed so you should be.&lt;/p&gt;

&lt;p&gt;I remember that Sequel introduced various advanced features before AR did - like lazy data sets (aka lazy execution of queries). You probably quickly forgot or you aren&amp;#8217;t aware of the fact that AR was &lt;em&gt;the last&lt;/em&gt; Ruby ORM that introduced this feature.&lt;/p&gt;

&lt;p&gt;I’ve heard from many people that are familiar with Sequel that it’s simply better than ActiveRecord in every aspect. I would not be surprised if this turns out to be true.&lt;/p&gt;

&lt;p&gt;I would love to hear more about your experiences with Sequel so please feel free to leave comments!&lt;/p&gt;

&lt;h2&gt;The State of ORMs?&lt;/h2&gt;

&lt;p&gt;Right. So where are we now with our favorite ORMs? In my opinion whether it’s ActiveRecord, DataMapper or Sequel - we’re still “not there yet”. I’ve been looking at other languages lately and it’s pretty clear that in Java, Python and PHP most popular ORMs implement the Data Mapper pattern. I’m not saying that this pattern is better. There’s been an open debate about AR vs DM patterns since for ever and there’s no ultimate answer. The fact is, though, that in most of the cases DM &lt;em&gt;is the preffered one&lt;/em&gt;. And ORMs in other languages reflect that. Java with its powerful Hibernate, Python with its SQLAlchemy and PHP with its Doctrine. All those projects are mature, have solid codebases and solve hard problems using well known design patterns.&lt;/p&gt;

&lt;p&gt;I really like what I see in those ORMs. They all implement &lt;a href="http://martinfowler.com/eaaCatalog/unitOfWork.html"&gt;Unit Of Work&lt;/a&gt;, &lt;a href="http://martinfowler.com/eaaCatalog/identityMap.html"&gt;Identity Map&lt;/a&gt; and a lot of other patterns that I didn’t have time to identify. It’s all there. Damn hard problems solved in a clean way with OOP approach and design patterns that were known for many years. When you open up sources of SQLAlchemy or Doctrine you are able to quickly navigate through those projects - classes are well organized and it&amp;#8217;s easy to figure things out.&lt;/p&gt;

&lt;p&gt;I understand why people like &amp;#8220;the less is more&amp;#8221; and &amp;#8220;convention over configuration&amp;#8221; but personally I would love to see more explicitness in Ruby ORMs. Metaprogramming is a dangerous weapon and we shouldn&amp;#8217;t forget about this. You probably think &amp;#8220;STFU and switch to Java&amp;#8221; now. Well, that&amp;#8217;s not gonna happen :)&lt;/p&gt;

&lt;p&gt;All of this doesn&amp;#8217;t change the fact that I believe &lt;em&gt;we can still do better&lt;/em&gt;. By looking at other languages we can find a lot of inspirations but many things can be done in a much better way in Ruby.&lt;/p&gt;

&lt;p&gt;I would love to get some feedback from you. Are you happy with your ORM of
choice?&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/j2lBVEt1oeg" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2011/11/29/the-state-of-ruby-orm.html</feedburner:origLink></entry>
  
  <entry>
    <title>Making ActiveRecord Models Thin</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/20tb6sDCQwo/making-activerecord-models-thin.html" />
    <updated>2011-08-01T14:20:00+02:00</updated>
    <id>http://solnic.eu/2011/08/01/making-activerecord-models-thin</id>
    <content type="html">&lt;p&gt;&amp;#8220;Skinny Controller, Fat Model&amp;#8221; is a well known best practice in Ruby
community. Everybody seems to agree with it and follows it. It&amp;#8217;s pretty clear
what a skinny controller means. The question is what is a fat model and what
should we do if it gets too fat? Even better, what should we do to avoid too fat
model? I think many people still confuse Domain Model with ActiveRecord. It&amp;#8217;s
something more and in this post I will try to explain my new approach to writing
Ruby on Rails applications.&lt;/p&gt;

&lt;p&gt;Also, I would like to thank Steve Klabnik who triggered the process of writing
this post by tweeting this:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;We need something better. Persistance and logic are two separate responsibilities&lt;br/&gt;that every rails app combines.&lt;/p&gt;&lt;footer&gt;&lt;strong&gt;Steve Klabnik&lt;/strong&gt; &lt;cite&gt;&lt;a href=’http://twitter.com/#!/steveklabnik/status/96260768823123968’&gt;twitter.com/#!/steveklabnik/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/footer&gt;&lt;/blockquote&gt;


&lt;p&gt;I&amp;#8217;m really glad more and more people are starting to realize this.&lt;/p&gt;

&lt;h2&gt;Behavior vs Data&lt;/h2&gt;

&lt;p&gt;When we say &amp;#8220;model&amp;#8221; we usually think about ActiveRecord. In Ruby on Rails world
this is how we established things. &amp;#8220;M&amp;#8221; in the MVC means app/models with a bunch
of ActiveRecord model files. This is where the domain logic of our applications
lives. I think we should stop thinking like that.&lt;/p&gt;

&lt;p&gt;Martin Fowler defines Domain Model as:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;An object model of the domain that incorporates both behavior and data.&lt;/p&gt;&lt;footer&gt;&lt;strong&gt;Martin Fowler&lt;/strong&gt; &lt;cite&gt;&lt;a href=’http://martinfowler.com/eaaCatalog/domainModel.html’&gt;martinfowler.com/eaaCatalog/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/footer&gt;&lt;/blockquote&gt;


&lt;p&gt;We should remember though that the way your Domain Model &lt;em&gt;behaves&lt;/em&gt; and the way
your data are &lt;em&gt;persisted&lt;/em&gt; are two separate concerns. ActiveRecord objects
represent your data. They give you a low level interface to access your data.
Yes, low level. If you mix domain specific behavior into ActiveRecord models you
will create classes with too many responsibilities. By violating &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;Single
Responsibility Principle&lt;/a&gt;
model code becomes difficult to extend, maintain and test. I have seen it many
times, I&amp;#8217;m pretty sure you have too.&lt;/p&gt;

&lt;p&gt;A few months ago I stumbled upon this quote:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;I pull the behavior out of my models into other objects that wrap the models.&lt;br/&gt;I prefer to make the AR objects simple wrappers around the db-access stuff in AR.&lt;/p&gt;&lt;p&gt;I have a fairly strict rule that controller actions cannot use AR finders or,&lt;br/&gt;in fact, interact with AR at all. AR should be accessed within api methods&lt;br/&gt;inside your model, not from the outside.&lt;/p&gt;&lt;footer&gt;&lt;strong&gt;Corey Haines&lt;/strong&gt; &lt;cite&gt;&lt;a href=’http://www.adomokos.com/2011/04/running-rails-rspec-tests-without-rails.html?showComment=1302880085636#c8190505485489994604’&gt;www.adomokos.com/2011/04/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/footer&gt;&lt;/blockquote&gt;


&lt;p&gt;This describes exactly what I&amp;#8217;ve started doing in my recent Rails
projects. The outcome of this approach is more than great. I literally left
ActiveRecord models with only validation rules, scopes and before/after hooks.
The rest is handled by a separate class hierarchy with domain-specific
functionality. Those clases use ActiveRecord models only for the persistence.&lt;/p&gt;

&lt;h2&gt;Well Defined API&lt;/h2&gt;

&lt;p&gt;Something that always bothers me in a typical Rails application is the lack of
a well defined model API. Your Domain Model should have an interface to every
action your application should be able to perform. If you have an online shop
where a user can buy a product then with a well-written Rails application you
should be able to fire up the console and be able to &lt;em&gt;easily&lt;/em&gt; perform this
operation. If it&amp;#8217;s not so simple then you probably want to think about your
model implementation again.&lt;/p&gt;

&lt;p&gt;What makes it so hard for us to design and implement a good API for our model?
In my opinion it happens because we &lt;em&gt;start with the data&lt;/em&gt; instead of behavior. For
example if you&amp;#8217;re building an online shop, how do you start the design and
implementation process? In Rails you probably create migration files to create a
db schema. Right? You initially think about the database columns you need to
create and validation rules you need to define in the models. After you have all
this done you start thinking about the behavior. You add various methods to your
ActiveRecord models so they can create new objects, validate and persist them.
In the end both data and behavior of your system is mixed together in
ActiveRecord models. If you change a column in some table, your system stops
working and it&amp;#8217;s relatively difficult to fix. Why? Because the domain behavior
is tightly coupled with the database schema. Because you started with the db
schema and added behavior later.&lt;/p&gt;

&lt;p&gt;How about reversing that process and starting with the behavior implemented in
separate classes that are not coupled with the database schema? This way you
will define your API at a higher level. What&amp;#8217;s more important you will &lt;em&gt;start&lt;/em&gt;
with an API and you will add the persistence logic later.&lt;/p&gt;

&lt;h2&gt;Behavior &amp;amp; API&lt;/h2&gt;

&lt;p&gt;The key difference between using ActiveRecord models and domain model classes is
that in case of the latter you clearly specify the behavior. For instance if I
want to find a product in my online shop, how do I do that? Well, with
ActiveRecord Product model I have plenty of choices. I can #find or #find_by_id
or #where(:id =&gt; id).first etc. This is problematic because the same operation can
be done in many different ways. Our goal is to create &lt;em&gt;a consistent&lt;/em&gt; behavior
that is the same in every place of our application.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s use a simplified example of an online shop and focus on one core behavior -
selling a product. Here&amp;#8217;s a code spike how it could be modelled:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;shop.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;span class=’line-number’&gt;29&lt;/span&gt;
&lt;span class=’line-number’&gt;30&lt;/span&gt;
&lt;span class=’line-number’&gt;31&lt;/span&gt;
&lt;span class=’line-number’&gt;32&lt;/span&gt;
&lt;span class=’line-number’&gt;33&lt;/span&gt;
&lt;span class=’line-number’&gt;34&lt;/span&gt;
&lt;span class=’line-number’&gt;35&lt;/span&gt;
&lt;span class=’line-number’&gt;36&lt;/span&gt;
&lt;span class=’line-number’&gt;37&lt;/span&gt;
&lt;span class=’line-number’&gt;38&lt;/span&gt;
&lt;span class=’line-number’&gt;39&lt;/span&gt;
&lt;span class=’line-number’&gt;40&lt;/span&gt;
&lt;span class=’line-number’&gt;41&lt;/span&gt;
&lt;span class=’line-number’&gt;42&lt;/span&gt;
&lt;span class=’line-number’&gt;43&lt;/span&gt;
&lt;span class=’line-number’&gt;44&lt;/span&gt;
&lt;span class=’line-number’&gt;45&lt;/span&gt;
&lt;span class=’line-number’&gt;46&lt;/span&gt;
&lt;span class=’line-number’&gt;47&lt;/span&gt;
&lt;span class=’line-number’&gt;48&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Shop&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Warehouse&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# returns a product&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="kp"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# returns a user&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# perform the payment&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Transaction&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="kp"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@customer&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;commit&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;success?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;commit!&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;commit!&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# do some stuff to persist data about a successful transaction&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;success?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;So, Warehouse can find a product, Customer can find a user, a customer instance can pay for a
product and Transaction handles selling a product to a customer. With this ridiculously
basic example let&amp;#8217;s see how we can write a spec for Transaction:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;shop_transaction_spec.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Shop&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;#commit&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;customer&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;product&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:transaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;described_class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should_receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:pay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment_status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;when payment is successful&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:payment_status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;when payment is not successful&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:payment_status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Running the spec gives you this output:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=”&gt;&lt;span class=’line’&gt;Shop::Transaction#commit
&lt;/span&gt;&lt;span class=’line’&gt;  when payment is successful
&lt;/span&gt;&lt;span class=’line’&gt;    success
&lt;/span&gt;&lt;span class=’line’&gt;      should equal true
&lt;/span&gt;&lt;span class=’line’&gt;  when payment is not successful
&lt;/span&gt;&lt;span class=’line’&gt;    success
&lt;/span&gt;&lt;span class=’line’&gt;      should equal false
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;Finished in 0.00182 seconds
&lt;/span&gt;&lt;span class=’line’&gt;2 examples, 0 failures&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This way we started off by defining our API, it&amp;#8217;s pretty simple to use:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;customer&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Shop&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;product&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Shop&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Warehouse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Shop&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Transaction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Note that we designed and implemented the behavior and we could easily write a
spec that checks if that behavior is correct. What about real data and
persistence?&lt;/p&gt;

&lt;h2&gt;Behavior + Persistence&lt;/h2&gt;

&lt;p&gt;To continue with the shop example let&amp;#8217;s add ActiveRecord models:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;models.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:presence&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:presence&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:product&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now let&amp;#8217;s use these models in our domain model classes:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;shop.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;span class=’line-number’&gt;29&lt;/span&gt;
&lt;span class=’line-number’&gt;30&lt;/span&gt;
&lt;span class=’line-number’&gt;31&lt;/span&gt;
&lt;span class=’line-number’&gt;32&lt;/span&gt;
&lt;span class=’line-number’&gt;33&lt;/span&gt;
&lt;span class=’line-number’&gt;34&lt;/span&gt;
&lt;span class=’line-number’&gt;35&lt;/span&gt;
&lt;span class=’line-number’&gt;36&lt;/span&gt;
&lt;span class=’line-number’&gt;37&lt;/span&gt;
&lt;span class=’line-number’&gt;38&lt;/span&gt;
&lt;span class=’line-number’&gt;39&lt;/span&gt;
&lt;span class=’line-number’&gt;40&lt;/span&gt;
&lt;span class=’line-number’&gt;41&lt;/span&gt;
&lt;span class=’line-number’&gt;42&lt;/span&gt;
&lt;span class=’line-number’&gt;43&lt;/span&gt;
&lt;span class=’line-number’&gt;44&lt;/span&gt;
&lt;span class=’line-number’&gt;45&lt;/span&gt;
&lt;span class=’line-number’&gt;46&lt;/span&gt;
&lt;span class=’line-number’&gt;47&lt;/span&gt;
&lt;span class=’line-number’&gt;48&lt;/span&gt;
&lt;span class=’line-number’&gt;49&lt;/span&gt;
&lt;span class=’line-number’&gt;50&lt;/span&gt;
&lt;span class=’line-number’&gt;51&lt;/span&gt;
&lt;span class=’line-number’&gt;52&lt;/span&gt;
&lt;span class=’line-number’&gt;53&lt;/span&gt;
&lt;span class=’line-number’&gt;54&lt;/span&gt;
&lt;span class=’line-number’&gt;55&lt;/span&gt;
&lt;span class=’line-number’&gt;56&lt;/span&gt;
&lt;span class=’line-number’&gt;57&lt;/span&gt;
&lt;span class=’line-number’&gt;58&lt;/span&gt;
&lt;span class=’line-number’&gt;59&lt;/span&gt;
&lt;span class=’line-number’&gt;60&lt;/span&gt;
&lt;span class=’line-number’&gt;61&lt;/span&gt;
&lt;span class=’line-number’&gt;62&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Shop&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Warehouse&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="no"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="kp"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# perform the payment&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Transaction&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="kp"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@product&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;commit&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;success?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;commit!&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;commit!&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;create_order&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;persisted?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;mark_product_as_sold&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;success?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="kp"&gt;private&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_order&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:product&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mark_product_as_sold&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:sold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This way we hide all the details about our db schema behind objects holding the
domain logic behavior of our shop application. If something changes with the
ActiveRecord models you will only need to change the implementation in one
place because there&amp;#8217;s one way of finding a user and a product and placing an
order.&lt;/p&gt;

&lt;h2&gt;Testing Benefits&lt;/h2&gt;

&lt;p&gt;With the approach I described it&amp;#8217;s really easy to write solid tests. You can
test the behavior in a complete isolation from the db models which results in
fast execution of those tests. Most of the logic of your system can be
unit-tested without touching the database, this means thousands of test examples
running in less than a second. On the other hand when testing ActiveRecord models
you are only concerned about validation rules, hooks and finder methods cause
there&amp;#8217;s no more logic there. It makes the AR tests &lt;em&gt;really clean&lt;/em&gt; and easy to maintain.&lt;/p&gt;

&lt;h2&gt;Feedback?&lt;/h2&gt;

&lt;p&gt;I understand that it may seem like a heavy approach and Ruby on Rails is all
about rapid development and writing less code. However, every project I&amp;#8217;ve seen
that evolved in something more than a blog written in 15 minutes, sooner or
later become a huge mess. I don&amp;#8217;t think programmers are guilty here. We&amp;#8217;ve been
taught to use certain tools and practices and now it&amp;#8217;s time to move on, take a
step forward.&lt;/p&gt;

&lt;p&gt;Still here? Awesome! I would love to get feedback about how you&amp;#8217;re dealing with
complex logic in your Rails applications - so feel free to comment and let&amp;#8217;s
start an interesting discussion.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/20tb6sDCQwo" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2011/08/01/making-activerecord-models-thin.html</feedburner:origLink></entry>
  
  <entry>
    <title>Virtus - Attributes For Your Plain Ruby Objects</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/8gfhgxy-ANQ/virtus---attributes-for-your-plain-ruby-objects.html" />
    <updated>2011-06-06T00:00:00+02:00</updated>
    <id>http://solnic.eu/2011/06/06/virtus—attributes-for-your-plain-ruby-objects</id>
    <content type="html">&lt;p&gt;I&amp;#8217;m happy to announce the first release of Virtus gem. It is an extraction of
DataMapper &lt;a href="http://datamapper.org/docs/properties.html"&gt;Property API&lt;/a&gt;
with various tweaks and improvements. If you like how properties work in
DataMapper and would like to use such functionality in your plain ruby objects
then you should give Virtus a try.&lt;/p&gt;

&lt;p&gt;It is an early release but I would not expect many API changes before 1.0.0
since the code is based on the stable DataMapper API and I&amp;#8217;m quite happy with it.&lt;/p&gt;

&lt;h2&gt;How to install?&lt;/h2&gt;

&lt;p&gt;Virtus is just a gem and comes with &lt;strong&gt;no dependencies&lt;/strong&gt;. To install just run this
in your shell:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.sh &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’sh’&gt;&lt;span class=’line’&gt;gem install virtus
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Why?&lt;/h2&gt;

&lt;p&gt;As some of you know we&amp;#8217;re starting to work on DataMapper 2.0. It will be a true
implementation of the Data Mapper pattern and will use a certain set of
libraries under the hood. &lt;a href="https://github.com/dkubb"&gt;Dan Kubb&lt;/a&gt; has already
finished his absolutely fantastic relational algebra engine called
&lt;a href="https://github.com/dkubb/veritas"&gt;Veritas&lt;/a&gt; along with
&lt;a href="https://github.com/dkubb/veritas-sql-generator"&gt;Veritas SQL Generator&lt;/a&gt; - these
gems will be the core part of DataMapper 2.0 Query System.&lt;/p&gt;

&lt;p&gt;When we were talking with Dan about the future of Property API in DataMapper we
both agreed we need an abstraction for defining your classes that would be
decoupled from any persistence logic. We also agreed that we actually don&amp;#8217;t like
&amp;#8220;property&amp;#8221; word in that context and would prefer &amp;#8220;attribute&amp;#8221;. There you go -
Virtus was borned :)&lt;/p&gt;

&lt;h2&gt;How does it work?&lt;/h2&gt;

&lt;p&gt;Virtus works in an almost identical way as Property in DataMapper. You can
define attributes in your classes and it will create accessors to these attributes
along with typecasting abilities. It comes with a set of builtin attribute types
but you are free to add your own types too.&lt;/p&gt;

&lt;p&gt;The API is dead-simple. Here&amp;#8217;s an example class:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:publish_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="no"&gt;Date&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:readers_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Integer&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This creates 4 attribute objects that are associated with your class. Each of
these attributes is responsible for reading and writing values. Values are stored
as standard instance variables.&lt;/p&gt;

&lt;p&gt;You can easily inspect what attributes a class has:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;span class=’line-number’&gt;29&lt;/span&gt;
&lt;span class=’line-number’&gt;30&lt;/span&gt;
&lt;span class=’line-number’&gt;31&lt;/span&gt;
&lt;span class=’line-number’&gt;32&lt;/span&gt;
&lt;span class=’line-number’&gt;33&lt;/span&gt;
&lt;span class=’line-number’&gt;34&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;#&amp;lt;Virtus::Attributes::String:0x8aeb548&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@instance_variable_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;@title&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:primitive&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:complex&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@reader_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@writer_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;#&amp;lt;Virtus::Attributes::String:0x8aea300&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@instance_variable_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;@author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:primitive&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:complex&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@reader_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@writer_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt; &lt;span class="ss"&gt;:publish_date&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;#&amp;lt;Virtus::Attributes::Date:0x8ae90e0&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@instance_variable_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;@publish_date&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:publish_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:primitive&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:complex&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@reader_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@writer_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt; &lt;span class="ss"&gt;:readers_count&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;#&amp;lt;Virtus::Attributes::Integer:0x8ae7e84&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@instance_variable_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;@readers_count&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:readers_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:primitive&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:complex&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@reader_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;   &lt;span class="vi"&gt;@writer_visibility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;:public&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Every attribute type has the primitive option set. When you are setting a value
of an attribute, the corresponding attribute object will check if the value has
the correct type. If the type doesn&amp;#8217;t match the primitive, then the attribute
will typecast the value.&lt;/p&gt;

&lt;h2&gt;Available Attribute Types&lt;/h2&gt;

&lt;p&gt;As I mentioned Virtus comes with various attribute types built-in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Array&lt;/li&gt;
&lt;li&gt;Boolean&lt;/li&gt;
&lt;li&gt;Date&lt;/li&gt;
&lt;li&gt;DateTime&lt;/li&gt;
&lt;li&gt;Decimal&lt;/li&gt;
&lt;li&gt;Float&lt;/li&gt;
&lt;li&gt;Hash&lt;/li&gt;
&lt;li&gt;Integer&lt;/li&gt;
&lt;li&gt;Object&lt;/li&gt;
&lt;li&gt;String&lt;/li&gt;
&lt;li&gt;Time&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;These classes are organized in a hierarchy where Object inherits from an
abstract Attribute class and all other types inherit from Object.&lt;/p&gt;

&lt;h2&gt;Options For Defining Attributes&lt;/h2&gt;

&lt;p&gt;When defining an attribute you can provide additional options. Every attribute
class has a list of options that it accepts.&lt;/p&gt;

&lt;p&gt;At the moment you can only use options for access control:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="ss"&gt;:accessor&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:public&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="ss"&gt;:reader&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:protected&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="nb"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:writer&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:private&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;It is possible to set a default value of an option directly on an attribute class:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;Virtus&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Attributes&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:protected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# :reader option will be set to :protected&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="c1"&gt;# you can override the default if you want&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:reader&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:public&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Custom Attribute Types and Options&lt;/h2&gt;

&lt;p&gt;Just like in DataMapper you can implement your own attribute types. Whenever you
need some twisted typecasting logic or you need to use extra options you can
create a custom attribute class.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s an example use-case - let&amp;#8217;s say you want a hash and you need to stringify or
symbolize the keys.&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;active_support/core_ext/hash/keys&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;virtus&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;MyApp&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Attributes&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hash&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Attributes&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;primitive&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# Define extra options that this attribute class accepts&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;accept_options&lt;/span&gt; &lt;span class="ss"&gt;:stringify_keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:symbolize_keys&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# Set up default values for our extra options&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;stringify_keys&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;symbolize_keys&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="c1"&gt;# Typecast logic is depends on the options&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;typecast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:stringify_keys&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stringify_keys&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:symbolize_keys&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbolize_keys&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Let&amp;#8217;s use our custom attribute:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Virtus&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Attributes&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Attributes&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:stringify_keys&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="ss"&gt;:settings&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bar&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="ss"&gt;:meta&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:foo&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bar&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; {:foo =&amp;gt; &amp;#39;bar&amp;#39;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;     &lt;span class="c1"&gt;# =&amp;gt; {&amp;#39;foo&amp;#39; =&amp;gt; &amp;#39;bar&amp;#39;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Other ORMs?&lt;/h2&gt;

&lt;p&gt;It&amp;#8217;s a bit early to talk about that but I would love to see other Ruby ORM
libraries using a common gem for model attributes. After we integrate DataMapper
with Virtus it should be feasible for others like Mongoid, MongoMapper or even
ActiveRecord (sic!) to use Virtus too. Well, at least that&amp;#8217;s my ultimate goal.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s not reinvent the wheel!&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;p&gt;Here are links related to the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/virtus"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rubygems.org/gems/virtus"&gt;Virtus on RubyGems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/virtus/issues"&gt;Issue Tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rubydoc.info/gems/virtus/0.0.2/frames"&gt;API Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/8gfhgxy-ANQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2011/06/06/virtus---attributes-for-your-plain-ruby-objects.html</feedburner:origLink></entry>
  
  <entry>
    <title>Custom RSpec-2 Matchers</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/GNuh5ntK2GU/custom-rspec-2-matchers.html" />
    <updated>2011-01-14T00:00:00+01:00</updated>
    <id>http://solnic.eu/2011/01/14/custom-rspec-2-matchers</id>
    <content type="html">&lt;p&gt;RSpec is one of my favorite tools. I have literally fallen in love with this
fantastic BDD library, especially with its second version. While using RSpec I
realized it teaches me how to write tests. Yes, exactly - learning RSpec DSL,
its syntax and structure of spec examples you actually learn the best practices
in writing tests. RSpec, despite many built-in matchers, comes with a DSL for
defining your own, custom matchers. It&amp;#8217;s so easy that you&amp;#8217;re not gonna believe
this.&lt;/p&gt;

&lt;h2&gt;Basics&lt;/h2&gt;

&lt;p&gt;In RSpec matchers are nothing but methods available in the context of an
example. You use them to make sure that a given expectation is met. There are
many matchers that come with RSpec for instance here is how you can use the
respond_to matcher:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;respond_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:gsub&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;It&amp;#8217;s so clean and beautiful that I probably don&amp;#8217;t have to explain what this
piece of code does, right?&lt;/p&gt;

&lt;p&gt;Tip: When you call describe with a class as an argument, RSpec will
automatically create an instance of that class and make it available via subject
method. Subject is also the default context of an example block. That&amp;#8217;s why we
don&amp;#8217;t have to write &amp;#8220;subject.should respond_to(:gsub)&amp;#8221;, because by default
&amp;#8220;should&amp;#8221; or &amp;#8220;should_not&amp;#8221; is called on the subject.&lt;/p&gt;

&lt;p&gt;Alright, for a list of available matchers check out
&lt;a href="http://relishapp.com/rspec/rspec-expectations"&gt;the official docs&lt;/a&gt;. Let&amp;#8217;s
focus on writing our own matchers. If you&amp;#8217;re wondering why you would need to
do that, let me show a simple example of a User model spec:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;foobar&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;should have errors on email&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;have_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;should have correct error message&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="kp"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Email is invalid&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now, you probably can imagine that almost identical code could be used in many
other cases for many other model classes. Those 6 lines of code can be written
as 1. You just need a custom matcher.&lt;/p&gt;

&lt;p&gt;Defining a custom matcher is simple. Let&amp;#8217;s start with a basic one that
checks if a given model instance has validation errors:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Matchers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:have_errors_on&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid?&lt;/span&gt; &lt;span class="c1"&gt;# call it here so we don&amp;#39;t have to write it in before blocks&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;And we can use it like that:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;foobar&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;have_errors_on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;It covers only the first expectation, but it&amp;#8217;s a good starting point.&lt;/p&gt;

&lt;h2&gt;Chaining&lt;/h2&gt;

&lt;p&gt;The second expectation in the example is to see if the correct validation
error message is set. It&amp;#8217;s possible to run matchers in a chain so let&amp;#8217;s see
how we can implement chaining in our custom matcher:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Matchers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:have_errors_on&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="ss"&gt;:with_message&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="vi"&gt;@message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="vi"&gt;@has_errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@message&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@has_errors&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@has_errors&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;It&amp;#8217;s really that simple. Now the matcher checks two things and returns true
only if the message exists &lt;em&gt;and&lt;/em&gt; if it matches the expected one.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s use it:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;foobar&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;have_errors_on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Email has an invalid format&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Nice! One line instead of six. But that&amp;#8217;s not everything, with a failing spec
failure messages might look like that:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.sh &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’sh’&gt;&lt;span class=’line’&gt;F
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;Failures:
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  1&lt;span class="o"&gt;)&lt;/span&gt; User when email is not valid
&lt;/span&gt;&lt;span class=’line’&gt;     Failure/Error: it &lt;span class="o"&gt;{&lt;/span&gt; should have_errors_on&lt;span class="o"&gt;(&lt;/span&gt;:email&lt;span class="o"&gt;)&lt;/span&gt;.with_message&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Email has an invali format&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;       expected &lt;span class="c"&gt;#&amp;lt;User @id=nil @email=&amp;quot;foobar&amp;quot;&amp;gt; to have errors on :email&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;Finished in 0.00047 seconds
&lt;/span&gt;&lt;span class=’line’&gt;1 examples, 1 failure
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;It&amp;#8217;s automatically generated by RSpec based on the matcher name. It&amp;#8217;s ok, but
notice that it won&amp;#8217;t tell us if the error message was incorrect. That&amp;#8217;s why we
need to set custom failure messages.&lt;/p&gt;

&lt;h2&gt;Custom failure messages and it&amp;#8217;s done!&lt;/h2&gt;

&lt;p&gt;It is really recommended to use meaningful failure messages. We need to set 2 types of
them, first one for &amp;#8220;should&amp;#8221; and second one for &amp;#8220;should_not&amp;#8221; expectations. The
idea is that if there is an error and the message is not correct, we need to
show that information in the failure output.&lt;/p&gt;

&lt;p&gt;So, our complete matcher looks like that:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;span class=’line-number’&gt;27&lt;/span&gt;
&lt;span class=’line-number’&gt;28&lt;/span&gt;
&lt;span class=’line-number’&gt;29&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Matchers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="ss"&gt;:have_errors_on&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="ss"&gt;:with_message&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="vi"&gt;@message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;valid?&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="vi"&gt;@has_errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@message&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@has_errors&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="vi"&gt;@has_errors&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;failure_message_for_should&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@message&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="s2"&gt;&amp;quot;Validation errors &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; should include &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; should have errors on attribute &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;failure_message_for_should_not&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; should not have an error on attribute &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now if we run our example and it fails because an error message doesn&amp;#8217;t match
the expectation, we will get following failure message in the output:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.sh &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’sh’&gt;&lt;span class=’line’&gt;F
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;Failures:
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  1&lt;span class="o"&gt;)&lt;/span&gt; User
&lt;/span&gt;&lt;span class=’line’&gt;     Failure/Error: it &lt;span class="o"&gt;{&lt;/span&gt; should have_errors_on&lt;span class="o"&gt;(&lt;/span&gt;:email&lt;span class="o"&gt;)&lt;/span&gt;.with_message&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Email has an invalid format&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;       Validation errors &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Email is blah&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; should include &lt;span class="s2"&gt;&amp;quot;Email has an invalid format&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;     &lt;span class="c"&gt;# ./_examples/rspec2_matchers.rb:55:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;Finished in 0.00053 seconds
&lt;/span&gt;&lt;span class=’line’&gt;1 example, 1 failure
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Summing up&lt;/h2&gt;

&lt;p&gt;As you can see implementing custom RSpec matchers is
&lt;span style="text-decoration:line-through"&gt;easy&lt;/span&gt;
trivial and it&amp;#8217;s a highly recommended practice. There are plenty of use cases
where you want to write custom matchers. It makes your specs clean and even
more readable and what&amp;#8217;s most important it keeps your spec&amp;#8217;s code DRY and
extendable.&lt;/p&gt;

&lt;p&gt;Here are some resources if you want to learn more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dchelimsky/rspec/wiki/"&gt;Official RSpec wiki on Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://relishapp.com/rspec/"&gt;RSpec Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.davidchelimsky.net/tag/rspec-2/"&gt;David Chelimsky Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://teachmetocode.com/screencasts/rspec-matchers/"&gt;RSpec matchers screencast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.arailsdemo.com/posts"&gt;A Rails Demo with posts about RSpec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/GNuh5ntK2GU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2011/01/14/custom-rspec-2-matchers.html</feedburner:origLink></entry>
  
  <entry>
    <title>Moving from WordPress to Jekyll</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/5TEAh0Bmo38/moving-from-wordpress-to-jekyll.html" />
    <updated>2011-01-05T00:00:00+01:00</updated>
    <id>http://solnic.eu/2011/01/05/moving-from-wordpress-to-jekyll</id>
    <content type="html">&lt;p&gt;Hello World! As usual it&amp;#8217;s been a while since I wrote anything here. Just wanted to say
that I&amp;#8217;m moving the site from WordPress to Jekyll and I like to share what I have
learned so far. If you are considering a migration too here are the steps I have
taken in order to port most of the tiny content of my blog. Read on and let me
know if something can be done in a better (or even completely different) way.&lt;/p&gt;

&lt;h2&gt;Posts migration&lt;/h2&gt;

&lt;p&gt;I followed &lt;a href="https://github.com/mojombo/jekyll/wiki/Blog-Migrations/"&gt;the instruction&lt;/a&gt;
on the official Jekyll wiki. It worked without any troubles. I only had to
manually change file extensions from &amp;#8220;html&amp;#8221; to &amp;#8220;textile&amp;#8221;, since that&amp;#8217;s what
I was using with WordPress to format my posts. Generated post files have
&lt;a href="https://github.com/mojombo/jekyll/wiki/YAML-Front-Matter"&gt;YAML fronts&lt;/a&gt; with
additional information taken from WordPress, specifically post ids and
permalinks.&lt;/p&gt;

&lt;h2&gt;Nginx setup&lt;/h2&gt;

&lt;p&gt;I had to make sure that old urls from WordPress will redirect correctly to the
new ones. Fortunatelly it&amp;#8217;s easy to do that with Nginx, here&amp;#8217;s my config:&lt;/p&gt;

&lt;p&gt;Liquid error: ClassNotFound: no lexer for alias &amp;#8216;conf&amp;#8217; found&lt;/p&gt;

&lt;p&gt;This makes sure that urls with format &amp;#8220;/year/month/day/post-title&amp;#8221; will be
redirected to &amp;#8220;/year/month/day/post-title.html&amp;#8221;. I didn&amp;#8217;t take care of
categories and tags urls, but it would be as easy to handle as in case of post
permalinks.&lt;/p&gt;

&lt;h2&gt;Setting up Jekyll&lt;/h2&gt;

&lt;p&gt;This was (actually still is as I haven&amp;#8217;t finished) also a straightfoward task.
There is a nice &lt;a href="https://github.com/mojombo/jekyll/wiki/Usage"&gt;overview&lt;/a&gt; on the
wiki that describes the basics you need to know about Jekyll.
&lt;a href="https://github.com/mojombo/jekyll/wiki/Configuration"&gt;Configuration&lt;/a&gt; has
defaults that work for me except pygments that I use for code highlighting which
is turned off by default. Every additional setting that you add to _config.yml
will be available via &amp;#8220;site&amp;#8221; object in your templates, so it&amp;#8217;s handy
to configure at least your site&amp;#8217;s url.&lt;/p&gt;

&lt;h2&gt;Layouts&lt;/h2&gt;

&lt;p&gt;In Jekyll you can easily nest layouts. I use 4 layouts, where &amp;#8220;default&amp;#8221; is
the base one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/solnic.eu/blob/master/_layouts/default.html"&gt;default&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/solnic.eu/blob/master/_layouts/page.html"&gt;page&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;this is used for &amp;#8220;static&amp;#8221; pages, like About, Contact etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/solnic.eu/blob/master/_layouts/post.html"&gt;post&lt;/a&gt; -
used by blog posts&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/solnic.eu/blob/master/_layouts/tag.html"&gt;tag&lt;/a&gt; -
used by &amp;#8220;tag&amp;#8221; pages which show all posts tagged with a given tag&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;Posts&lt;/h2&gt;

&lt;p&gt;Index page displays a list of post excerpts. With Jekyll you can include
&amp;#8220;partial&amp;#8221; templates by adding them to _includes folder. Here&amp;#8217;s how you can use
it, given you have &amp;#8220;_includes/excerpt.html&amp;#8221; in your project:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=”&gt;&lt;span class=’line’&gt;—
&lt;/span&gt;&lt;span class=’line’&gt;layout: default
&lt;/span&gt;&lt;span class=’line’&gt;title: Home
&lt;/span&gt;&lt;span class=’line’&gt;—
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&amp;lt;ul class="posts"&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  \{\% for post in site.posts limit: 15 \%\}
&lt;/span&gt;&lt;span class=’line’&gt;  &amp;lt;li&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    \{\% include excerpt.html \%\}
&lt;/span&gt;&lt;span class=’line’&gt;  &amp;lt;/li&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  \{\% endfor \%\}
&lt;/span&gt;&lt;span class=’line’&gt;&amp;lt;/ul&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;where excerpt.html could look like this:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;excerpt&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;time&lt;/span&gt; &lt;span class="na"&gt;pubdate&lt;/span&gt; &lt;span class="na"&gt;datetime=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;\{\{ post.date | date_to_xmlschema \}\}&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        \{\{ post.date | date_to_string \}\}
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;/time&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      »
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;\{\{ post.url \}\}&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;\{\{ post.title \}\}&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  \{\{ post.content | truncatewords:80 \}\}
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Tags&lt;/h2&gt;

&lt;p&gt;I had troubles using categories with Jekyll so after all I decided to just use
tags. You can tag a post with YAML front:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;template.erb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’erb’&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;—&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;title: My Post&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;tags:&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;  - foo&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;  - bar&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;—&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;post content&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Then all the tags will be accessible via site object in your templates. For
example you can list your tags along with post counts like that:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  \{\% for tag_data in site.tags \%\}
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      \{\{ tag_data[0] }} (\{\{ tag_data[1].size \}\})
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  \{\% endfor \%\}
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;I put pages that list tagged posts in &amp;#8220;tags&amp;#8221; folder which makes them accessible
via &amp;#8220;/tags/some-tag.html&amp;#8221; urls. &lt;span style="text-decoration:line-through"&gt;
I still need to write a rake task which dynamically generates these templates&lt;/span&gt;.
Rake task is done and it looks like that:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;tags&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Generate tag pages&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:generate_pages&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;tags&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="n"&gt;tag_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.html&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag_page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOS&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="sh"&gt;—&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="sh"&gt;layout: tag&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="sh"&gt;title: solnic.eu / tags / #{tag}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="sh"&gt;name: #{tag}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="sh"&gt;—&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="sh"&gt;&amp;lt;ul class=&amp;quot;posts&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="sh"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="no"&gt;        EOS&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Code highlighting&lt;/h2&gt;

&lt;p&gt;I use &lt;a href="http://pygments.org"&gt;Pygments&lt;/a&gt; to highlight code snippets. Installation
instruction for various platforms is also &lt;a href="https://github.com/mojombo/jekyll/wiki/Install"&gt;on the wiki&lt;/a&gt;.
Once you got it installed you will need to generate CSS:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.sh &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’sh’&gt;&lt;span class=’line’&gt;pygmentize -f html -S default &amp;gt; pygments.css
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Where &amp;#8220;default&amp;#8221; is the name of a pygment theme. Here are available built-in pygments
themes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;autumn&lt;/li&gt;
&lt;li&gt;borland&lt;/li&gt;
&lt;li&gt;bw&lt;/li&gt;
&lt;li&gt;colorful&lt;/li&gt;
&lt;li&gt;default&lt;/li&gt;
&lt;li&gt;emacs&lt;/li&gt;
&lt;li&gt;friendly&lt;/li&gt;
&lt;li&gt;fruity&lt;/li&gt;
&lt;li&gt;manni&lt;/li&gt;
&lt;li&gt;monokai&lt;/li&gt;
&lt;li&gt;murphy&lt;/li&gt;
&lt;li&gt;native&lt;/li&gt;
&lt;li&gt;pastie&lt;/li&gt;
&lt;li&gt;perldoc&lt;/li&gt;
&lt;li&gt;tango&lt;/li&gt;
&lt;li&gt;trac&lt;/li&gt;
&lt;li&gt;vs&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;To learn more about Pygments you can check out &lt;a href="http://pygments.org/docs"&gt;the docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to highlight a code sample in your post you just wrap everything in a
liquid &amp;#8220;highlight&amp;#8221; block providing language name as an argument. Check out &lt;a href="http://pygments.org/languages/"&gt;the
 list of all languages&lt;/a&gt; supported by
Pygments, pretty impressive, BrainFuck included :). For instance if you want to
highlight a ruby snippet you do this:&lt;/p&gt;

&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.sh &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’sh’&gt;&lt;span class=’line’&gt;&lt;span class="se"&gt;\{\%&lt;/span&gt; codeblock sample.rb &lt;span class="se"&gt;\%\}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;puts &lt;span class="s2"&gt;&amp;quot;Hello World!&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="se"&gt;\{\%&lt;/span&gt; endcodeblock &lt;span class="se"&gt;\%\}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Comments - importing to Disqus&lt;/h2&gt;

&lt;p&gt;This is still a work in progress. You can export entire content of your
WordPress blog to a special XML feed called &amp;#8220;WordPress eXtended RSS&amp;#8221;. Then you
upload this file via Disqus&amp;#8217; import tool. There is also another way, you can
use Disqus WordPress plugin to do the import automatically. Unfortunately neither
of these methods worked for me. It seems like the generated file is corrupted,
but the data are there so I will have to manually parse it and generate a new
import XML file. YAY&amp;#8230;!&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;p&gt;Here are some related links that you may find useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://metaskills.net/2010/12/27/let-it-go-moving-from-mephisto-to-jekyll/"&gt;&amp;#8220;Let It Go - Moving From Mephisto To
Jekyll&amp;#8221;&lt;/a&gt; - an awesome post by Ken Collins, my biggest inspiration to do the migration too&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ilkka.github.com/2010/12/08/rakefile_for_jekyll_site_management.html"&gt;&amp;#8220;Rakefile for Jekyll site management&amp;#8221;&lt;/a&gt; - a good start if you want to write some convenient rake tasks&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tobi/liquid/wiki/liquid-for-designers"&gt;&amp;#8220;Liquid For Designers&amp;#8221; docs&lt;/a&gt; - I&amp;#8217;ve found it useful because I didn&amp;#8217;t remember liquid syntax :)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mojombo/jekyll/wiki"&gt;Official Jekyll Wiki on Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://daringfireball.net/projects/markdown/syntax"&gt;Markdown Syntax Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pygments.org/docs/"&gt;Pygments Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/webfonts"&gt;Google Font Directory&lt;/a&gt; - I discovered that
while doing the migration. I use Ubuntu and Droid Sans Mono fonts.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/solnic/solnic.eu"&gt;Sources of this site on Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;script type="text/javascript"&gt;
$(‘code’).each(function() {
  $(this).html(this.innerHTML.replace(/\{/g, "&amp;#123;"));
  $(this).html(this.innerHTML.replace(/\}/g, "&amp;#125;"));
  $(this).html(this.innerHTML.replace(/\%/g, "%"));
});
&lt;/script&gt;

&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/5TEAh0Bmo38" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2011/01/05/moving-from-wordpress-to-jekyll.html</feedburner:origLink></entry>
  
  <entry>
    <title>Rack Middleware Contest</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/e6o2UYUTM4U/rack-middleware-contest.html" />
    <updated>2009-10-12T00:00:00+02:00</updated>
    <id>http://solnic.eu/2009/10/12/rack-middleware-contest</id>
    <content type="html">&lt;p&gt;CodeRack is a coding contest dreamed up by a group of the Ruby programmers at &lt;a href="http://www.lunarlogicpolska.com"&gt;Lunar Logic Polska&lt;/a&gt; who were excited about the possibilities of Rack middleware. The team wants to encourage Ruby developers to explore the possibilities and what better way than to hold a contest? The secondary goal of the contest is to generate a set of open source solutions that will solve real problems and inspire others. Every entry will be released under the &lt;span class="caps"&gt;MIT&lt;/span&gt; open source license.&lt;/p&gt;
&lt;p&gt;Programmers are encouraged to submit contest entries that will be judged based on the cleverness of the application and the elegance of the code. Entries can be submitted at &lt;a href="http://www.coderack.org"&gt;coderack.org&lt;/a&gt; until midnight &lt;span class="caps"&gt;EST&lt;/span&gt; November 15th. Finalists are scheduled to be announced on the 1st of December and public voting will run for one month. The final winners will be announced on the 5th of January.&lt;/p&gt;
&lt;p&gt;The first round of the contest will be judged by an elite panel of judges including Ben Bangert of O&amp;#8217;Reilly Media, Chris Wanstrath and PJ Hyett of GitHub, Joshua Peek of 37Signals, Yehuda Katz of Engine Yard and Rails core team member, Ryan Tomayko of Heroku, Core Rails team member Matt Aimonetti, and the Rails Envy team of Gregg Pollack and Jason Seifer.&lt;/p&gt;
&lt;p&gt;Once the finalists have been selected by the panel, the public will vote for the top prize winners.&lt;/p&gt;
&lt;p&gt;Prizes have been donated by Bytemark Hosting, GitHub, Jetbrains, Mindmeister, Freelance Total, Heroku, Rackspace Hosting, Peepcode, BDDCasts, and Zenbe Shareflow. The top prize includes a dedicated quad core server package and is valued at over $3000. Every entrant will receive a credit from bddcasts.com and $30 credit from Heroku. All finalists will receive a package including Zenbe Shareflow subscriptions, a RubyMine license from JetBrains, and five credits from bddcasts.com. Details of all of the prize packages will soon be available on the coderack.org website.&lt;/p&gt;
&lt;p&gt;More information about the contest, including the contest rules, can be found at &lt;a href="http://coderack.org"&gt;coderack.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ps. This post is a copy from &lt;a href="http://www.lunarlogicpolska.com/2009/10/8/lunar-logic-polska-launches-coderack-global-coding-contest"&gt;Lunar Logic Polska blog&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/e6o2UYUTM4U" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2009/10/12/rack-middleware-contest.html</feedburner:origLink></entry>
  
  <entry>
    <title>Unobtrusive JavaScript helpers in Rails 3</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/SdDV-0KFSt4/unobtrusive-javascript-helpers-in-rails-3.html" />
    <updated>2009-09-08T00:00:00+02:00</updated>
    <id>http://solnic.eu/2009/09/08/unobtrusive-javascript-helpers-in-rails-3</id>
    <content type="html">&lt;p&gt;A while ago I have written a post about &lt;a href="http://blog.solnic.eu/2007/10/30/why-javascript-helpers-in-rails-are-evil"&gt;JavaScript helpers in Ruby on Rails&lt;/a&gt; and tried to explain why they are a bad idea. It&amp;#8217;s hard to believe for me that it was almost 2 years ago! Since then so many things have happened in the Ruby world&amp;#8230;Now Rails 3 is on its way and we already know what significant improvements and changes it will include. One of them is related to JavaScript helpers and the way how remote links and forms will be handled and I must admit that the new idea is absolutely great.&lt;/p&gt;
&lt;p&gt;The new way is based on unobtrusive approach to JavaScript. This means that &lt;span class="caps"&gt;HTML&lt;/span&gt; code will be separated from JavaScript. I have checked out the latest sources of Ruby on Rails and found out that some of the work is already done. There is a new helper called AjaxHelper, it implements link_to_remote method which in the moment of writing this post looks like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.rb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’rb’&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;link_to_remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data-update-success&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:success&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data-update-failure&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:failure&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data-update-success&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data-update-position&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data-method&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data-remote&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="n"&gt;link_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;What you see here will generate a clean markup with HTML5-compliant attributes prefixed with a word &amp;#8220;data-&amp;#8221;. If you are not familiar with them you can checkout a nice article by John Resig &lt;a href="http://ejohn.org/blog/html-5-data-attributes"&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; 5 data- Attributes&lt;/a&gt;. Those attributes will instruct the additional JavaScript code how it should handle the behavior. Basically all links, buttons and forms that have the special attribute &amp;#8220;data-remote&amp;#8221; set to &amp;#8220;true&amp;#8221; will issue an &lt;span class="caps"&gt;AJAX&lt;/span&gt; request. There has been a discussion on &lt;a href="http://www.mail-archive.com/rubyonrails-core@googlegroups.com/msg09122.html"&gt;the Rails on Rails Core group&lt;/a&gt; about how to implement corresponding JavaScript code. People are worried about its performance since finding all elements with data-remote=true appears to be slow in case of Prototype and jQuery. Moreover there is a problem of new elements that may be dynamically inserted after the page was loaded and all the event listeners were attached. Fortunately there is no need to be worried as our situation is a perfect example where we should use &lt;a href="http://www.sitepoint.com/blogs/2008/07/23/javascript-event-delegation-is-easier-than-you-think/"&gt;Event Delegation&lt;/a&gt;. &lt;span class="caps"&gt;DHH&lt;/span&gt; has already showed in his &lt;a href="http://www.scribd.com/doc/15010095/Rails-3-and-the-Real-Secret-to-High-Productivity"&gt;Rails 3 and the Real Secret to High Productivity&lt;/a&gt; presentation how links and buttons can be handled by &lt;a href="http://www.prototypejs.org"&gt;Prototype&lt;/a&gt; library and it looks absolutely reasonable to me.&lt;/p&gt;
&lt;p&gt;I would like to focus on jQuery though as it&amp;#8217;s getting more popular even in the Rails community. Great example is &lt;a href="http://www.lunarlogicpolska.com"&gt;my job&lt;/a&gt; where we use jQuery in every of our new projects. So how can we handle new remote links and forms using this popular library? Actually it&amp;#8217;s ridiculously easy. Thanks to &lt;a href="http://docs.jquery.com/Events/live"&gt;jQuery.live&lt;/a&gt; function we can easily use &lt;a href="http://www.sitepoint.com/blogs/2008/07/23/javascript-event-delegation-is-easier-than-you-think"&gt;Event Delegation&lt;/a&gt; to handle &lt;span class="caps"&gt;AJAX&lt;/span&gt; calls. Just take a look at this sample of a markup that new helpers in Rails 3 will generate:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="c"&gt;&amp;lt;!– the new link to remote –&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/users&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;data-remote=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Users&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="c"&gt;&amp;lt;!– the new remote form –&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/users&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;post&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;data-remote=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;login&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Pretty clean, I really like it! Now let&amp;#8217;s see how we can implement jQuery handler that will send &lt;span class="caps"&gt;AJAX&lt;/span&gt; requests:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’js’&gt;&lt;span class=’line’&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;get&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="c1"&gt;// remote links handler&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a[data-remote=true]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;live&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="c1"&gt;// remote forms handler&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;form[data-remote=true]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;live&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;submit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;The above code will send an &lt;span class="caps"&gt;AJAX&lt;/span&gt; request when you click on a remote link or submit a remote form. Note that it will work also with new elements dynamically inserted to the &lt;span class="caps"&gt;DOM&lt;/span&gt;. The example JavaScript code is the bare minimum of course, we could have something much more sophisticated. We will be able to specify success and failure handlers and also elements that should be updated with an &lt;span class="caps"&gt;AJAX&lt;/span&gt; response text (and probably much more!), hence the JavaScript is going to be more complicated.&lt;/p&gt;
&lt;p&gt;This is definitely a step into the right direction. I&amp;#8217;m looking forward to Rails 3!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/SdDV-0KFSt4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2009/09/08/unobtrusive-javascript-helpers-in-rails-3.html</feedburner:origLink></entry>
  
  <entry>
    <title>Client-side rendering with Prototype</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/SQEfImnV2tQ/client-side-rendering-with-prototype.html" />
    <updated>2009-01-15T00:00:00+01:00</updated>
    <id>http://solnic.eu/2009/01/15/client-side-rendering-with-prototype</id>
    <content type="html">&lt;p&gt;Web applications are getting more and more complex. The user interface of a modern web application can be as rich as its desktop equivalent. If we use JavaScript/&lt;span class="caps"&gt;HTML&lt;/span&gt;/&lt;span class="caps"&gt;CSS&lt;/span&gt; trio to build this UI then we definitely want to use &lt;span class="caps"&gt;AJAX&lt;/span&gt;. A typical approach is to use &lt;span class="caps"&gt;AJAX&lt;/span&gt; to update parts of our page using an &lt;span class="caps"&gt;HTML&lt;/span&gt; response, everyone knows that, right? Does this approach allow us to create a responsive, fast and flexible UI? The answer is no.&lt;/p&gt;
&lt;p&gt;Here are 4 main downsides of using &lt;span class="caps"&gt;AJAX&lt;/span&gt; requests to load UI parts:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You increase the server load &amp;#8211; yes, you make an &lt;span class="caps"&gt;AJAX&lt;/span&gt; request only because you need a piece of &lt;span class="caps"&gt;HTML&lt;/span&gt; code that you want to insert to an already rendered page. That was cool a few years ago when &lt;span class="caps"&gt;AJAX&lt;/span&gt; was such a great innovation. Nowadays it should be considered as a less efficient solution.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;You complicate the server-side code &amp;#8211; because you need parts of your page to be returned by the server you, obviously, need to handle that by writing more server-side code. You end up having many actions in your controllers that return different fragments of &lt;span class="caps"&gt;HTML&lt;/span&gt;. I know, you think it&amp;#8217;s normal, everyone does that.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;You loose a lot of control over the UI &amp;#8211; you use &lt;span class="caps"&gt;DHTML&lt;/span&gt; techniques to deal with the UI and in the same time you need the server to get parts of that UI. This leads to a code duplication and in many cases ends up with a big mess.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;A user will have to wait until a request is done &amp;#8211; that just sucks, that poor guy has to wait because you went back to the server for a little piece of &lt;span class="caps"&gt;HTML&lt;/span&gt;. How you are going to implement a responsive UI this way? &amp;#8220;Your servers are fast&amp;#8221;. Of course they are, but what if user&amp;#8217;s &lt;span class="caps"&gt;ISP&lt;/span&gt; sucks? What if the user is downloading something and 99% of his bandwidth is gone?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rendering &lt;span class="caps"&gt;HTML&lt;/span&gt; on the client-side is ridiculously simple. Consider the following example. Let&amp;#8217;s say we have a page with a list of some people, the list is just a simple &lt;span class="caps"&gt;HTML&lt;/span&gt; table. It could look like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;First Name&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Last Name&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;E-Mail&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tbody&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;people&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="c"&gt;&amp;lt;!– here go people –&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tfoot&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;colspan=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;4&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;previous&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;next&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Next&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tfoot&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;As you can see the tbody element is empty, we will load its content after the entire page is loaded. Instead of a bunch of &amp;#8220;tr&amp;#8221; elements the server should return a nice &lt;span class="caps"&gt;JSON&lt;/span&gt; data which could look like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’js’&gt;&lt;span class=’line’&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;people&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;John&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Doe&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;john.doe@somewhere.com&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Jane&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Doe&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;jane.doe@anywhere.com&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Third&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Guy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;third.guy@nowhere.com&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;To render these data we obviously need a template. Prototype gives us a handy class called &lt;a href="http://prototypejs.org/api/template"&gt;Template&lt;/a&gt; which is perfect for our needs. To create a template and render the list of people we need a few lines of JavaScript:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’js’&gt;&lt;span class=’line’&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;personRowTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="s1"&gt;&amp;#39;&amp;lt;tr id=&amp;quot;person_#{id}&amp;quot;&amp;gt;&amp;lt;td&amp;gt;#{first_name}&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;#{last_name}&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;#{email}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;peopleRows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nx"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nx"&gt;peopleRows&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;personRowTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;people&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peopleRows&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s pretty much it. It doesn&amp;#8217;t look spectacular, huh? Now just think about the benefits of this approach:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You have the data in &lt;span class="caps"&gt;JSON&lt;/span&gt; format, you can use them to render things like an edit form without going back to the server, thus user experience will be better&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;You can be focused on building a nice &lt;span class="caps"&gt;JSON&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt; for accessing data instead of implementing actions that return small pieces of &lt;span class="caps"&gt;HTML&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;Your client-side code is cleaner and more consistent&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sounds like a good deal, doesn&amp;#8217;t it? :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/SQEfImnV2tQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2009/01/15/client-side-rendering-with-prototype.html</feedburner:origLink></entry>
  
  <entry>
    <title>jQuery vs Prototype - part II</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/fF3rg8U9jyk/jquery-vs-prototype-part-ii.html" />
    <updated>2008-02-03T00:00:00+01:00</updated>
    <id>http://solnic.eu/2008/02/03/jquery-vs-prototype-part-ii</id>
    <content type="html">&lt;p&gt;Recently, new versions of jQuery and Prototype have been released &amp;#8211; it&amp;#8217;s a perfect moment for a part number 2. On the official Prototype blog we &lt;a href="http://www.prototypejs.org/2008/1/25/prototype-1-6-0-2-bug-fixes-performance-improvements-and-security"&gt;can read&lt;/a&gt; that the general performance of &lt;span class="caps"&gt;CSS&lt;/span&gt; selectors is now improved, unfortunately only for Safari 3, but Element#up/#down/#next/#previous should now be faster on all browsers, it&amp;#8217;s a good news as they were really slow. On the other hand we have jQuery &lt;a href="http://jquery.com/blog/2008/01/15/jquery-122-2nd-birthday-present"&gt;official announcement&lt;/a&gt; with information that jQuery is now 300% faster &amp;#8211; we&amp;#8217;ll see!&lt;/p&gt;
&lt;p&gt;This time I made a step forward and decided to use a custom JavaScript-based testing environment instead of running tests using Firebug profiler. The obvious advantage is that I was able to run all the tests on 4 different browsers. New test cases aren&amp;#8217;t much different then in the first part, let&amp;#8217;s say it&amp;#8217;s a modification of the previous ones with some extra operations and a little more complex &lt;span class="caps"&gt;HTML&lt;/span&gt; structure.&lt;/p&gt;
&lt;h3&gt;Test environment setup&lt;/h3&gt;
&lt;p&gt;Libraries:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;jQuery 1.2.2&lt;/li&gt;
	&lt;li&gt;Prototype 1.6.0.2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the tests were run on the following browsers:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Firefox 2.0.0.11&lt;/li&gt;
	&lt;li&gt;Konqueror 4.00.00&lt;/li&gt;
	&lt;li&gt;Opera 9.50_beta1&lt;/li&gt;
	&lt;li&gt;Internet Explorer 7 (&lt;strong&gt;but using Windows on VirtualBox!&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A tiny piece of JavaScript code is responsible for running the tests, each operation is called only once inside a try-catch block, so the essential part looks like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’js’&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resultCell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;div style=&amp;quot;color: red&amp;quot;&amp;gt;Exception caught: &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;There is a 3 seconds break between each test run, results are automatically inserted into the results table. If you want, you can check it out on your own, just go &lt;a href="http://solnic.eu/test_runner/index.html"&gt;right here&lt;/a&gt; and hit the &amp;#8216;run tests!&amp;#8217; button.&lt;/p&gt;
&lt;h3&gt;The results&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;m happy to see that all tests pass on the latest Konqueror, previous version from KDE3 fails on some Prototype tests. I don&amp;#8217;t own Mac, so you won&amp;#8217;t see Safari results here, although I&amp;#8217;ve run the tests on my friend&amp;#8217;s MacBook with very similar hardware as my laptop has (Intel Core Duo 2ghz + 2 gigs of &lt;span class="caps"&gt;RAM&lt;/span&gt;), and it was faster even then Konqueror (no, it doesn&amp;#8217;t mean his MacBook is faster then my laptop!!!! ;)).&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve run everything 3 times, here are average results in ms:&lt;/p&gt;
&lt;table id="test_results" class="test_results"&gt;
&lt;col style="width:12px"/&gt;
&lt;col style="width:55px"/&gt;
&lt;col style="width:220px"/&gt;
&lt;col style="width:24px"/&gt;
&lt;col style="width:24px"/&gt;
&lt;col style="width:24px"/&gt;
&lt;col style="width:24px"/&gt;
&lt;tbody&gt;
&lt;tr&gt;
    &lt;th&gt;#&lt;/th&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Test&lt;/th&gt;
    &lt;th&gt;Firefox&lt;/th&gt;
    &lt;th&gt;Konqueror&lt;/th&gt;
    &lt;th&gt;IE7&lt;/th&gt;
    &lt;th&gt;Opera&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;
$(&amp;#8216;td.counter&amp;#8217;).addClass(&amp;#8216;marked&amp;#8217;)
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;96.6&lt;/td&gt;
    &lt;td&gt;32.3&lt;/td&gt;
    &lt;td class="jq_faster"&gt;70&lt;/td&gt;
    &lt;td class="jq_faster"&gt;37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;
$$(&amp;#8216;td.counter&amp;#8217;).each(function(el){el.addClassName(&amp;#8216;marked&amp;#8217;)})
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;108.3&lt;/td&gt;
    &lt;td&gt;49.6&lt;/td&gt;
    &lt;td&gt;858&lt;/td&gt;
    &lt;td&gt;75.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;2&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;td.counter span.special&amp;#8217;).removeClass(&amp;#8216;special&amp;#8217;)&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;62&lt;/td&gt;
    &lt;td&gt;23.6&lt;/td&gt;
    &lt;td class="jq_faster"&gt;46.6&lt;/td&gt;
    &lt;td&gt;25.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;
$$(&amp;#8216;td.counter span.special&amp;#8217;).each(function(el) {el.removeClassName(&amp;#8216;special&amp;#8217;)})
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td class="proto_faster"&gt;28&lt;/td&gt;
    &lt;td&gt;23.7&lt;/td&gt;
    &lt;td&gt;167&lt;/td&gt;
    &lt;td&gt;24.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;3&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;td.content span.odd&amp;#8217;).css(&amp;#8216;color&amp;#8217;, &amp;#8216;red&amp;#8217;)&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;124.7&lt;/td&gt;
    &lt;td&gt;40.3&lt;/td&gt;
    &lt;td class="jq_faster"&gt;63.7&lt;/td&gt;
    &lt;td&gt;38.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$$(&amp;#8216;td.content span.odd&amp;#8217;).each(function(el) { &lt;br /&gt;
  el.setStyle(&amp;#8216;color: red&amp;#8217;) &lt;br /&gt;
})&lt;/pre&gt;&lt;/td&gt;
    &lt;td class="proto_faster"&gt;55.7&lt;/td&gt;
    &lt;td&gt;31&lt;/td&gt;
    &lt;td&gt;297&lt;/td&gt;
    &lt;td&gt;33.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;4&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;
$(&amp;#8216;td.content span.even&amp;#8217;).before(&amp;#8216;&lt;h3 style="display: none"&gt;text&lt;/h3&gt;&amp;#8217;)
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;382.7&lt;/td&gt;
    &lt;td&gt;177.3&lt;/td&gt;
    &lt;td&gt;373.7&lt;/td&gt;
    &lt;td&gt;205.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;
$$(&amp;#8216;td.content span.even&amp;#8217;).each(function(el) {
el.insert({before:&amp;#8216;&lt;h3 style="display:none"&gt;text&lt;/h3&gt;&amp;#8217;})
})
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;359&lt;/td&gt;
    &lt;td class="proto_faster"&gt;90.7&lt;/td&gt;
    &lt;td&gt;527&lt;/td&gt;
    &lt;td class="proto_faster"&gt;138.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;5&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;td.content h3&amp;#8217;).show()&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;178.7&lt;/td&gt;
    &lt;td&gt;227.7&lt;/td&gt;
    &lt;td class="jq_faster"&gt;83.3&lt;/td&gt;
    &lt;td&gt;1161.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$$(&amp;#8216;td.content h3&amp;#8217;).each(Element.show)&lt;/pre&gt;&lt;/td&gt;
    &lt;td class="proto_faster"&gt;38&lt;/td&gt;
    &lt;td class="proto_faster"&gt;21&lt;/td&gt;
    &lt;td&gt;250.7&lt;/td&gt;
    &lt;td class="proto_faster"&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;6&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;div.special&amp;#8217;).hide()&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;90&lt;/td&gt;
    &lt;td&gt;81.3&lt;/td&gt;
    &lt;td class="jq_faster"&gt;33.7&lt;/td&gt;
    &lt;td&gt;375.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$$(&amp;#8216;div.special&amp;#8217;).each(Element.hide)&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;18&lt;/td&gt;
    &lt;td&gt;7&lt;/td&gt;
    &lt;td&gt;73.3&lt;/td&gt;
    &lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;7&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;div.special, td.content .odd&amp;#8217;).toggle()&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;637.7&lt;/td&gt;
    &lt;td&gt;431.7&lt;/td&gt;
    &lt;td&gt;517&lt;/td&gt;
    &lt;td&gt;1360.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$$(&amp;#8216;div.special, td.content .odd&amp;#8217;).each(Element.toggle)&lt;/pre&gt;&lt;/td&gt;
    &lt;td class="proto_faster"&gt;71&lt;/td&gt;
    &lt;td class="proto_faster"&gt;43.7&lt;/td&gt;
    &lt;td class="proto_faster"&gt;106.7&lt;/td&gt;
    &lt;td class="proto_faster"&gt;43&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;8&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;span.odd&amp;#8217;).remove()&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;132.7&lt;/td&gt;
    &lt;td&gt;59.3&lt;/td&gt;
    &lt;td&gt;123.3&lt;/td&gt;
    &lt;td&gt;66.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$$(&amp;#8216;span.odd&amp;#8217;).each(Element.remove)&lt;/pre&gt;&lt;/td&gt;
    &lt;td class="proto_faster"&gt;29&lt;/td&gt;
    &lt;td class="proto_faster"&gt;11.7&lt;/td&gt;
    &lt;td class="proto_faster"&gt;36.7&lt;/td&gt;
    &lt;td class="proto_faster"&gt;19.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td rowspan="2"&gt;&lt;b&gt;9&lt;/b&gt;&lt;/td&gt;
    &lt;td style="color: red;"&gt;jQuery&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;#data p.lost:first&amp;#8217;).html(&amp;#8216;gotcha!&amp;#8217;)&lt;/pre&gt;&lt;/td&gt;
    &lt;td class="jq_faster"&gt;5&lt;/td&gt;
    &lt;td&gt;1.7&lt;/td&gt;
    &lt;td&gt;10&lt;/td&gt;
    &lt;td class="jq_faster"&gt;3.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td style="color: blue;"&gt;Prototype&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;$(&amp;#8216;data&amp;#8217;).down(&amp;#8216;p.lost&amp;#8217;).update(&amp;#8216;gotcha!&amp;#8217;)&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;11.7&lt;/td&gt;
    &lt;td&gt;2&lt;/td&gt;
    &lt;td&gt;10&lt;/td&gt;
    &lt;td&gt;7.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Conclusion #2&lt;/h3&gt;
&lt;p&gt;Prototype was at least 2 times faster then jQuery in 15 cases, and jQuery was faster then Prototype in 8 cases. What library should I choose? In my case I will stick with Prototype, because it offers the same functionality as jQuery does + more and it&amp;#8217;s faster. jQuery is probably better for projects where there&amp;#8217;s a need for some fancy UI effects and that&amp;#8217;s it, but it&amp;#8217;s just an assumption, correct me if I&amp;#8217;m wrong&amp;#8230;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/fF3rg8U9jyk" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2008/02/03/jquery-vs-prototype-part-ii.html</feedburner:origLink></entry>
  
  <entry>
    <title>jQuery vs Prototype - part I</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/-ur5JTLSdvM/jquery-vs-prototype-part-i.html" />
    <updated>2007-11-11T00:00:00+01:00</updated>
    <id>http://solnic.eu/2007/11/11/jquery-vs-prototype-part-i</id>
    <content type="html">&lt;p&gt;Prototype 1.6.0 was released to the public 4 days ago, at first I decided to check its performance and new features in comparison to the previous version, but being interested in other JavaScript libraries, I&amp;#8217;ve changed my mind. Lets see how you can accomplish same tasks with the latest &lt;a href="http://www.prototypejs.org"&gt;Prototype&lt;/a&gt; and &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; libraries and simply see which one is faster. In this part I&amp;#8217;m going to show the results of running single operations, in next part(s) I will prepare a sample website and write more complex test cases and, again, check how fast jQuery and Prototype can be (or how slow&amp;#8230;).&lt;/p&gt;
&lt;h3&gt;Test environment setup&lt;/h3&gt;
&lt;p&gt;The following software was used:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Prototype 1.6.0&lt;/li&gt;
	&lt;li&gt;jQuery 1.2.1&lt;/li&gt;
	&lt;li&gt;Firefox 2.0.0.9&lt;/li&gt;
	&lt;li&gt;Firebug 1.05&lt;/li&gt;
	&lt;li&gt;Webdeveloper 1.1.4&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Test page contains only one table with 500 rows, it&amp;#8217;s generated using the following &lt;span class="caps"&gt;RHTML&lt;/span&gt; template:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.erb &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’erb’&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;  &amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;    &amp;lt;td class=&amp;quot;first&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;    &amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;    &amp;lt;td class=&amp;quot;second&amp;quot;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;      &amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;hello from &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;    &amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;  &amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="x"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;h3&gt;Running the tests&lt;/h3&gt;
&lt;p&gt;Each operation was executed using Firebug&amp;#8217;s console with Profiler turned on and repeated 3 times, &lt;br /&gt;
between each execution the page was reloaded. Cache in Firefox was disabled using Webdeveloper plugin. &lt;br /&gt;
Here are the results of 7 test operations showing average times and number of method calls in each operation:&lt;/p&gt;
&lt;p&gt;1. Adding &amp;#8216;marked&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; class to every cell having &amp;#8216;first&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; class:&lt;/p&gt;
&lt;table class="test_results" id="test_results"&gt;
&lt;tr&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Operation&lt;/th&gt;
    &lt;th&gt;Time (ms)&lt;/th&gt;
    &lt;th&gt;Method Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;jQuery&lt;/td&gt;
&lt;td class="code"&gt;
&lt;pre&gt;
$(&amp;#8216;td.first&amp;#8217;).addClass(&amp;#8216;marked&amp;#8217;)
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;102.495&lt;/td&gt;
    &lt;td&gt;3032&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #1&lt;/td&gt;
&lt;td class="code"&gt;
&lt;pre&gt;
$$(&amp;#8216;td.first&amp;#8217;).each(function(cell) { cell.addClassName(&amp;#8216;marked&amp;#8217;) })
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;117.162&lt;/td&gt;
    &lt;td&gt;7056&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #2&lt;/td&gt;
&lt;td class="code"&gt;
&lt;pre&gt;
$$(&amp;#8216;td.first&amp;#8217;).invoke(&amp;#8216;addClassName&amp;#8217;, &amp;#8216;marked&amp;#8217;)
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;129.972&lt;/td&gt;
    &lt;td&gt;8062&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;: no practical difference, although jQuery is a little faster.&lt;/p&gt;
&lt;p&gt;2. Removing &lt;span class="caps"&gt;CSS&lt;/span&gt; class from every table cell having &amp;#8220;second&amp;#8221; &lt;span class="caps"&gt;CSS&lt;/span&gt; class:&lt;/p&gt;
&lt;table class="test_results" id="test_results"&gt;
&lt;tr&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Operation&lt;/th&gt;
    &lt;th&gt;Time (ms)&lt;/th&gt;
    &lt;th&gt;Method Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;jQuery&lt;/td&gt;
&lt;td&gt;
&lt;pre&gt;
$(&amp;#8216;td.second&amp;#8217;).removeClass(&amp;#8216;second&amp;#8217;)
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;109.855&lt;/td&gt;
    &lt;td&gt;3032&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #1&lt;/td&gt;
&lt;td class="code"&gt;
&lt;pre&gt;
$$(&amp;#8216;td.second&amp;#8217;).each(function(cell) { cell.removeClassName(&amp;#8216;second&amp;#8217;) })
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;87.445&lt;/td&gt;
    &lt;td&gt;4551&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #2&lt;/td&gt;
&lt;td class="code"&gt;
&lt;pre&gt;
$$(&amp;#8216;td.second&amp;#8217;).invoke(&amp;#8216;removeClassName&amp;#8217;, &amp;#8216;second&amp;#8217;)
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;100.64&lt;/td&gt;
    &lt;td&gt;5557&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;: No big difference, especially when comparing Prototype #2 option with jQuery.&lt;/p&gt;
&lt;p&gt;3. Setting &amp;#8216;color&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; property in every div element which is inside a cell having &amp;#8216;second&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; class:&lt;/p&gt;
&lt;table class="test_results" id="test_results"&gt;
&lt;tr&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Operation&lt;/th&gt;
    &lt;th&gt;Time (ms)&lt;/th&gt;
    &lt;th&gt;Method Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;jQuery&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$(&amp;#8216;td.second div&amp;#8217;).css(&amp;#8216;color&amp;#8217;, &amp;#8216;red&amp;#8217;)&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;173.906&lt;/td&gt;
    &lt;td&gt;3536&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #1&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(function(el) { el.setStyle({ color : &amp;#8216;red&amp;#8217; }) });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;87.585&lt;/td&gt;
    &lt;td&gt;4563&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #2&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(function(el) { el.setStyle(&amp;#8216;color : red&amp;#8217;) });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;98.283&lt;/td&gt;
    &lt;td&gt;5064&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #3&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).invoke(&amp;#8216;setStyle&amp;#8217;, &amp;#8216;color : red&amp;#8217;);&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;107.81&lt;/td&gt;
    &lt;td&gt;6070&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;: Same here, Prototype 2 x faster&lt;/p&gt;
&lt;p&gt;4. Adding new elements before every div element which is inside a cell having &amp;#8216;second&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; class:&lt;/p&gt;
&lt;table class="test_results" id="test_results"&gt;
&lt;tr&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Operation&lt;/th&gt;
    &lt;th&gt;Time (ms)&lt;/th&gt;
    &lt;th&gt;Method Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;jQuery&lt;/td&gt;
&lt;td class="code"&gt;
&lt;pre&gt;
$(&amp;#8216;td.second div&amp;#8217;).before(&amp;#8216;&lt;h3&gt;text&lt;/h3&gt;&amp;#8217;)
&lt;/pre&gt;
&lt;/td&gt;
    &lt;td&gt;368.611&lt;/td&gt;
    &lt;td&gt;15066&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #1&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(function(el) { el.insert({ before: &amp;#8216;&amp;lt;h3&amp;gt;text&amp;lt;/h3&amp;gt;&amp;#8217; }) });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;1252.016&lt;/td&gt;
    &lt;td&gt;17088&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #2&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).invoke(&amp;#8216;insert&amp;#8217;, { before: &amp;#8216;&amp;lt;h3&amp;gt;text&amp;lt;/h3&amp;gt;&amp;#8217; });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;1316.969&lt;/td&gt;
    &lt;td&gt;19096&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;: Wow&amp;#8230;jQuery is almost 4 times faster, I should point out that &lt;a href="http://www.prototypejs.org/api/element/insert"&gt;Element#insert&lt;/a&gt; is a new method introduced in Prototype 1.6.0.&lt;/p&gt;
&lt;p&gt;5. Removing all div elements which are inside cells having &amp;#8216;second&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; class:&lt;/p&gt;
&lt;table class="test_results" id="test_results"&gt;
&lt;tr&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Operation&lt;/th&gt;
    &lt;th&gt;Time (ms)&lt;/th&gt;
    &lt;th&gt;Method Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;jQuery&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$(&amp;#8216;td.second div&amp;#8217;).remove()&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;151.955&lt;/td&gt;
    &lt;td&gt;2032&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #1&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(Element.remove);&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;65.785&lt;/td&gt;
    &lt;td&gt;3060&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #2&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).invoke(&amp;#8216;remove&amp;#8217;);&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;94,105&lt;/td&gt;
    &lt;td&gt;5068&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #3&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(function(el) { el.remove() });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;83.591&lt;/td&gt;
    &lt;td&gt;4062&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;: Prototype more then 2 times faster.&lt;/p&gt;
&lt;p&gt;6. Hiding and un-hiding all div elements which are inside cells having &amp;#8216;second&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; class:&lt;/p&gt;
&lt;table class="test_results" id="test_results"&gt;
&lt;tr&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Operation&lt;/th&gt;
    &lt;th&gt;Time (ms)&lt;/th&gt;
    &lt;th&gt;Method Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;jQuery&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$(&amp;#8216;td.second div&amp;#8217;).toggle();$(&amp;#8216;td.second div&amp;#8217;).toggle();&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;1948.825&lt;/td&gt;
    &lt;td&gt;47653&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #1&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(Element.toggle);$$(&amp;#8216;td.second div&amp;#8217;).each(Element.toggle);&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;158.987&lt;/td&gt;
    &lt;td&gt;14106&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #2&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(function(el) { el.toggle() }); $$(&amp;#8216;td.second div&amp;#8217;).each(function(el) { el.toggle() });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;191.096&lt;/td&gt;
    &lt;td&gt;16110&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;: jQuery tragedy, Prototype toggles visibility of 500 divs 10 times faster!&lt;/p&gt;
&lt;p&gt;7. Attaching event listeners to all div elements which are inside cells having &amp;#8216;second&amp;#8217; &lt;span class="caps"&gt;CSS&lt;/span&gt; class:&lt;/p&gt;
&lt;table class="test_results" id="test_results"&gt;
&lt;tr&gt;
    &lt;th&gt;Library&lt;/th&gt;
    &lt;th&gt;Operation&lt;/th&gt;
    &lt;th&gt;Time (ms)&lt;/th&gt;
    &lt;th&gt;Method Calls&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;jQuery&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$(&amp;#8216;td.second div&amp;#8217;).bind(&amp;#8216;click&amp;#8217;, function(){ alert(this.innerHTML) })&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;146.19&lt;/td&gt;
    &lt;td&gt;3535&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #1&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).invoke(&amp;#8216;observe&amp;#8217;, &amp;#8216;click&amp;#8217;, function(){ alert(this.innerHTML) });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;169,889&lt;/td&gt;
    &lt;td&gt;11581&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Prototype #2&lt;/td&gt;
    &lt;td class="code"&gt;&lt;pre&gt;$$(&amp;#8216;td.second div&amp;#8217;).each(function(el) { el.observe(&amp;#8216;click&amp;#8217;, function(){ alert(this.innerHTML) }) });&lt;/pre&gt;&lt;/td&gt;
    &lt;td&gt;164.456&lt;/td&gt;
    &lt;td&gt;10575&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Comment&lt;/em&gt;: no practical difference.&lt;/p&gt;
&lt;h3&gt;General conclusion and impression&lt;/h3&gt;
&lt;p&gt;Executed tests show that Prototype seems to be faster then jQuery, with the exception of the new insertion method, which performance should be improved. Although I like jQuery syntax more then Prototype, the performance is way more important then saving few lines of code. Of course tests that I made don&amp;#8217;t show how these libraries act in a real application, which is my task for the next part(s) of this article. Despite the results I must admit that I&amp;#8217;m very excited about jQuery, my general impression is that this library is more mature then Prototype.&lt;/p&gt;
&lt;p&gt;You may want to check out &lt;a href="http://blog.solnic.eu/2008/2/3/jquery-vs-prototype-part-ii"&gt;part ||&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/-ur5JTLSdvM" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2007/11/11/jquery-vs-prototype-part-i.html</feedburner:origLink></entry>
  
  <entry>
    <title>Why JavaScript helpers in rails are evil</title>
    <link href="http://feedproxy.google.com/~r/solnic-on-blog/~3/xckhG85nrYk/why-javascript-helpers-in-rails-are-evil.html" />
    <updated>2007-10-30T00:00:00+01:00</updated>
    <id>http://solnic.eu/2007/10/30/why-javascript-helpers-in-rails-are-evil</id>
    <content type="html">&lt;p&gt;Ruby on Rails gained so much attention and appreciation mostly because it simplifies the development process of &lt;span class="caps"&gt;AJAX&lt;/span&gt;-driven applications. When I started to learn Rails I was already very familiar with other &lt;span class="caps"&gt;MVC&lt;/span&gt;-based frameworks, and actually I&amp;#8217;ve created one myself (in PHP5) in my previous work. My framework also uses Prototype JavaScript library, so when l was learning Rails it was nothing new when I saw &amp;#8220;Ajax.Updater(&amp;#8230;)&amp;#8221;. I remember that when I added first &lt;span class="caps"&gt;AJAX&lt;/span&gt;-feature in the Depot (it&amp;#8217;s a tutorial application used in well known &amp;#8220;Agile Web Development in Ruby on Rails&amp;#8221; book)  &lt;strong&gt;I was shocked&lt;/strong&gt; about how simple it is, but then I looked into the &lt;span class="caps"&gt;HTML&lt;/span&gt; output and it shocked me once more&amp;#8230;&lt;/p&gt;
&lt;h3&gt;JavaScript Helpers&lt;/h3&gt;
&lt;p&gt;These nice methods generate for you &lt;span class="caps"&gt;HTML&lt;/span&gt; with some addition of JavaScript code, one can say &amp;#8220;You don&amp;#8217;t need to know JavaScript to create &lt;span class="caps"&gt;AJAX&lt;/span&gt; web apps! Just use Ruby on Rails!&amp;#8221;. It&amp;#8217;s a catchy slogan, and in some way it&amp;#8217;s true, you don&amp;#8217;t need to know how Ajax.Request works, you just write link_to_remote and you&amp;#8217;re done. In Rails &lt;span class="caps"&gt;API&lt;/span&gt; you can find 4 helper modules, all related to JavaScript code generation, and here they are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptHelper.html"&gt;General JavaScript Helpers&lt;/a&gt; &amp;#8211; actually there&amp;#8217;s nothing interesting there&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptMacrosHelper.html"&gt;JavaScript Macros Helpers&lt;/a&gt; &amp;#8211; whole thing is deprecated in the upcoming Rails 2.0&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper.html"&gt;Prototype Helpers&lt;/a&gt; &amp;#8211; probably the most popular methods, including link_to_remote and other &lt;span class="caps"&gt;AJAX&lt;/span&gt; goodies&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/ScriptaculousHelper.html"&gt;Scriptaculous Helpers&lt;/a&gt; &amp;#8211; you know, drag&amp;#8217;n&amp;#8217;drop and visual effects goodies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When I first saw what link_to_remote helper creates I was really surprised, back then I said to myself &amp;#8220;hey, that&amp;#8217;s&amp;#8230;just bad!&amp;#8221;. Unfortunately I had quickly forgotten about my negative thoughts on JavaScript helpers, because &amp;#8220;everybody&amp;#8221; use them, and that&amp;#8217;s a shame in my opinion. I don&amp;#8217;t know why JavaScript helpers are included in the Rails core, maybe it was just a pure marketing trick or something :) So, what&amp;#8217;s so evil about JavaScript helpers?&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;DRY&lt;/span&gt; &amp;#8211; ooooh reaaally?&lt;/h3&gt;
&lt;p&gt;We, the Ruby on Rails developers, use proudly our favorite &lt;span class="caps"&gt;MVC&lt;/span&gt; framework, we remember everyday about Don&amp;#8217;t Repeat Yourself principle and other good and well known practices. How come that people like us write scary pieces of code like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;users_list&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% @users.each do |user| -%&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_&amp;lt;%= user.id %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= user.login %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= link_to_remote(
&lt;/span&gt;&lt;span class=’line’&gt;             &amp;#39;Delete&amp;#39;,
&lt;/span&gt;&lt;span class=’line’&gt;             :url =&amp;gt; user_path(user),
&lt;/span&gt;&lt;span class=’line’&gt;             :method =&amp;gt; &amp;#39;delete&amp;#39;,
&lt;/span&gt;&lt;span class=’line’&gt;             :confirm =&amp;gt; &amp;#39;Are you sure?&amp;#39;,
&lt;/span&gt;&lt;span class=’line’&gt;             :complete =&amp;gt; &amp;quot;Effect.DropOut(&amp;#39;user_#{user.id}&amp;#39;)&amp;quot;,
&lt;/span&gt;&lt;span class=’line’&gt;             :failure =&amp;gt; &amp;#39;alert(&amp;quot;Could not delete user: #{user.login}&amp;quot;)&amp;#39;
&lt;/span&gt;&lt;span class=’line’&gt;          )
&lt;/span&gt;&lt;span class=’line’&gt;      %&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% end -%&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% end %&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Pretty common rhtml snippet, right?? (yes, I know, we use partials, but it&amp;#8217;s just an example) Let&amp;#8217;s have a look at the &lt;span class="caps"&gt;HTML&lt;/span&gt; output:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;span class=’line-number’&gt;20&lt;/span&gt;
&lt;span class=’line-number’&gt;21&lt;/span&gt;
&lt;span class=’line-number’&gt;22&lt;/span&gt;
&lt;span class=’line-number’&gt;23&lt;/span&gt;
&lt;span class=’line-number’&gt;24&lt;/span&gt;
&lt;span class=’line-number’&gt;25&lt;/span&gt;
&lt;span class=’line-number’&gt;26&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;users_list&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_2&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;jane&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;if (confirm(&amp;#39;Are you sure?&amp;#39;)) { new Ajax.Request(&amp;#39;/users/2&amp;#39;, {asynchronous:true, evalScripts:true, method: &amp;#39;delete&amp;#39;, onComplete:function(request){Effect.DropOut(&amp;#39;user_2&amp;#39;)}, onFailure:function(request){alert(&amp;#39;Could not delete user: jane&amp;#39;)}}); }; return false;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;john&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;if (confirm(&amp;#39;Are you sure?&amp;#39;)) { new Ajax.Request(&amp;#39;/users/1&amp;#39;, {asynchronous:true, evalScripts:true, method: &amp;#39;delete&amp;#39;, onComplete:function(request){Effect.DropOut(&amp;#39;user_1&amp;#39;)}, onFailure:function(request){alert(&amp;#39;Could not delete user: john&amp;#39;)}}); }; return false;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_4&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;paul&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;if (confirm(&amp;#39;Are you sure?&amp;#39;)) { new Ajax.Request(&amp;#39;/users/4&amp;#39;, {asynchronous:true, evalScripts:true, method: &amp;#39;delete&amp;#39;, onComplete:function(request){Effect.DropOut(&amp;#39;user_4&amp;#39;)}, onFailure:function(request){alert(&amp;#39;Could not delete user: paul&amp;#39;)}}); }; return false;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_3&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;peter&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;if (confirm(&amp;#39;Are you sure?&amp;#39;)) { new Ajax.Request(&amp;#39;/users/3&amp;#39;, {asynchronous:true, evalScripts:true, method: &amp;#39;delete&amp;#39;, onComplete:function(request){Effect.DropOut(&amp;#39;user_3&amp;#39;)}, onFailure:function(request){alert(&amp;#39;Could not delete user: peter&amp;#39;)}}); }; return false;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where did &lt;span class="caps"&gt;DRY&lt;/span&gt; go?&lt;/strong&gt; Hello? Why we don&amp;#8217;t apply our &lt;span class="caps"&gt;OOP&lt;/span&gt; practices also to JavaScript? &amp;#8220;Why bother!?&amp;#8221; you might ask, well, &lt;span class="caps"&gt;BECAUSE&lt;/span&gt; IT &lt;span class="caps"&gt;MATTERS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;JavaScript won&amp;#8217;t hurt you&lt;/h3&gt;
&lt;p&gt;Creating webapps without a good understanding of JavaScript is like working with ActiveRecord and having no idea what &lt;span class="caps"&gt;SQL&lt;/span&gt; is. I think you know what I mean. There are plenty of great JavaScript libraries, Ruby on Rails comes with &lt;a href="http://www.prototypejs.org"&gt;Prototype&lt;/a&gt; and it makes writing JavaScript as easy&amp;amp;cool as writing Ruby code. Okey, here&amp;#8217;s above example without redundancy, the quickest solution would be:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;users_list&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% @users.each do |user| -%&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_&amp;lt;%= user.id %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= user.login %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= link_to &amp;#39;Delete&amp;#39;, &amp;#39;#&amp;#39;, :onclick =&amp;gt; &amp;quot;deleteUser(#{user.id})&amp;quot; %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% end -%&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;And in application.js (or wherever else):&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;function deleteUser(userId) {
&lt;/span&gt;&lt;span class=’line’&gt;  if(confirm(&amp;#39;Are you sure?&amp;#39;) {
&lt;/span&gt;&lt;span class=’line’&gt;    new Ajax.Request(
&lt;/span&gt;&lt;span class=’line’&gt;       &amp;#39;/users/&amp;#39;+userId, {
&lt;/span&gt;&lt;span class=’line’&gt;         method : &amp;#39;delete&amp;#39;,
&lt;/span&gt;&lt;span class=’line’&gt;         on200 : function(){ Effect.DropOut(&amp;#39;user_&amp;#39;+userId) },
&lt;/span&gt;&lt;span class=’line’&gt;         on500 : function(xhr){ alert(xhr.responseText) }
&lt;/span&gt;&lt;span class=’line’&gt;    });
&lt;/span&gt;&lt;span class=’line’&gt;  }
&lt;/span&gt;&lt;span class=’line’&gt;  return false;
&lt;/span&gt;&lt;span class=’line’&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Now, our ouput looks like this:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;users_list&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_2&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;jane&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;deleteUser(2)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;john&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;deleteUser(1)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_4&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;paul&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;deleteUser(4)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_3&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;peter&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;deleteUser(3)&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;We don&amp;#8217;t have a redundant JavaScript code in the &lt;span class="caps"&gt;HTML&lt;/span&gt; output&lt;/li&gt;
	&lt;li&gt;We are not limited to what link_to_remote generates&lt;/li&gt;
	&lt;li&gt;We have a generic JavaScript function which deletes a user, we can make it even more generic and use successfully in other places&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Obtrusive JavaScript code in &lt;span class="caps"&gt;HTML&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Progressive enhancement and unobtrusive JavaScript&lt;/h3&gt;
&lt;p&gt;I found out about this approach about half a year ago, when I started to use Dan Webb&amp;#8217;s &lt;span class="caps"&gt;UJS&lt;/span&gt; rails plugin which makes an extensive use of LowPro library. I was very excited about its functionality, thanks to that plugin I&amp;#8217;ve stopped using JavaScript helpers. &lt;span class="caps"&gt;UJS&lt;/span&gt; is a dead project now, you can find out why &lt;a href="http://www.danwebb.net/2007/6/16/the-state-and-future-of-the-ujs-plugin"&gt;here&lt;/a&gt; but it doesn&amp;#8217;t matter, thanks to it I&amp;#8217;ve learned two important things:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;We can divide View layer into two sub-layers: the presentation (HTML+CSS) and the behaviour (JavaScript)&lt;/li&gt;
	&lt;li&gt;Presentation layer can be extended using JavaScript by adding various behaviours to the &lt;span class="caps"&gt;DOM&lt;/span&gt; elements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Currently I don&amp;#8217;t use &lt;span class="caps"&gt;UJS&lt;/span&gt; or pure Low Pro, instead I just code my JavaScript using Prototype and Scriptaculous. Let&amp;#8217;s see how this looks in practice. Here&amp;#8217;s how our users table example could be implemented using progressive enhancement and unobtrusive JavaScript code. First of all, we&amp;#8217;re going to create plain &lt;span class="caps"&gt;HTML&lt;/span&gt; links, without onclick event and without even href attribute (I assume we&amp;#8217;re writing an application which requires JavaScript to work):&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;users_list&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% @users.each do |user| -%&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_&amp;lt;%= user.id %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;%= user.login %&amp;gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;% end -%&amp;gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;Above rhtml template generates this &lt;span class="caps"&gt;HTML&lt;/span&gt; output:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.html &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’html’&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;users_list&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_3&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;peter&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_4&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;paul&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_1&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;john&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_2&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;jane&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;a&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;The very last thing to do is to add an actual functionality to our plain &lt;span class="caps"&gt;HTML&lt;/span&gt; code. Let&amp;#8217;s create a simple module called Users, which will include method for deleting users:&lt;/p&gt;
&lt;p&gt;&lt;div class=’bogus-wrapper’&gt;&lt;notextile&gt;&lt;figure class=’code’&gt;&lt;figcaption&gt;&lt;span&gt;sample.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class=’line-number’&gt;1&lt;/span&gt;
&lt;span class=’line-number’&gt;2&lt;/span&gt;
&lt;span class=’line-number’&gt;3&lt;/span&gt;
&lt;span class=’line-number’&gt;4&lt;/span&gt;
&lt;span class=’line-number’&gt;5&lt;/span&gt;
&lt;span class=’line-number’&gt;6&lt;/span&gt;
&lt;span class=’line-number’&gt;7&lt;/span&gt;
&lt;span class=’line-number’&gt;8&lt;/span&gt;
&lt;span class=’line-number’&gt;9&lt;/span&gt;
&lt;span class=’line-number’&gt;10&lt;/span&gt;
&lt;span class=’line-number’&gt;11&lt;/span&gt;
&lt;span class=’line-number’&gt;12&lt;/span&gt;
&lt;span class=’line-number’&gt;13&lt;/span&gt;
&lt;span class=’line-number’&gt;14&lt;/span&gt;
&lt;span class=’line-number’&gt;15&lt;/span&gt;
&lt;span class=’line-number’&gt;16&lt;/span&gt;
&lt;span class=’line-number’&gt;17&lt;/span&gt;
&lt;span class=’line-number’&gt;18&lt;/span&gt;
&lt;span class=’line-number’&gt;19&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=’code’&gt;&lt;pre&gt;&lt;code class=’js’&gt;&lt;span class=’line’&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nx"&gt;onWindowLoad&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;users_list&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;getElementsBySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userRow&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="nx"&gt;userRow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;down&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUserDelete&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="nx"&gt;onUserDelete&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Are you sure?&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tr&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;       &lt;span class="s1"&gt;&amp;#39;/users/&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;         &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;delete&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;         &lt;span class="nx"&gt;on200&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt; &lt;span class="nx"&gt;Effect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DropOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user_&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;         &lt;span class="nx"&gt;on500&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=’line’&gt;&lt;span class="nx"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;load&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onWindowLoad&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/notextile&gt;&lt;/p&gt;
&lt;p&gt;This way we:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Write reusable and object oriented code&lt;/li&gt;
	&lt;li&gt;Create clean and easy to maintain &lt;span class="caps"&gt;RHTML&lt;/span&gt; templates&lt;/li&gt;
	&lt;li&gt;Have a clean separation between visual and behavior layers in our applications&lt;/li&gt;
	&lt;li&gt;Decrease site loading time by writing less JavaScript (you can even &lt;a href="http://synthesis.sbecker.net/pages/asset_packager"&gt;compress it&lt;/a&gt; too)&lt;/li&gt;
	&lt;li&gt;Improve general performance of our application&amp;#8217;s UI&lt;/li&gt;
	&lt;li&gt;Learn JavaScript! :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;The final word&lt;/h3&gt;
&lt;p&gt;I didn&amp;#8217;t write anything about so called graceful degradation issue, leaving JavaScript helpers behind was the main reason for this article. If you totally disagree with me or/and you know an even better approach, leave a comment, I&amp;#8217;m always open to a discussion.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/solnic-on-blog/~4/xckhG85nrYk" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://solnic.eu/2007/10/30/why-javascript-helpers-in-rails-are-evil.html</feedburner:origLink></entry>
  
</feed>

