<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.dovetailsoftware.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Dynamic and Concise</title><subtitle type="html">This blog is for my thoughts and experience on riding with Rails. It could also contain other stuff though.</subtitle><id>http://blogs.dovetailsoftware.com/blogs/yi_wen/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.dovetailsoftware.com/blogs/yi_wen/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.dovetailsoftware.com/blogs/yi_wen/atom.aspx" /><generator uri="http://communityserver.org" version="2.1.61129.2">Community Server</generator><updated>2007-10-29T17:26:00Z</updated><entry><title>A Study in Array#Collect</title><link rel="alternate" type="text/html" href="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/12/04/collect-syntax-study.aspx" /><id>http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/12/04/collect-syntax-study.aspx</id><published>2007-12-04T17:14:00Z</published><updated>2007-12-04T17:14:00Z</updated><content type="html">&lt;p&gt;&lt;a href="http://www.stephenchu.com/"&gt;Stephen Chu&lt;/a&gt; talked about how to beautify statements like &lt;code&gt;customers.collect { |customer| customer.name }&lt;/code&gt; in &lt;a href="http://www.stephenchu.com/2007/03/enhance-arraycollect-to-become-magical.html"&gt;one of his posts&lt;/a&gt;. &lt;a href="http://drnicwilliams.com/"&gt;Dr. Nic&lt;/a&gt; also has a &lt;a href="http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/"&gt;post&lt;/a&gt; talking about the same thing. It's very interesting to see so many people want to get away the cumbersome collect syntax and I am one of these people.&lt;/p&gt;&lt;p&gt;To beautify the collect syntax when we need just one field such as &lt;code&gt;customer.name&lt;/code&gt;. There are several ways:to use &lt;a href="http://www.stephenchu.com/2007/03/enhance-arraycollect-to-become-magical.html"&gt;Stephen's&lt;/a&gt; syntax:&lt;br&gt;&lt;code&gt;customers.collect_name&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/"&gt;Dr. Nic's&lt;/a&gt;:&lt;br&gt;&lt;code&gt;customers.names&lt;/code&gt;&lt;/p&gt;&lt;p&gt;And guess what, if you are using Rails, it comes with a Symbol extension method called &lt;code&gt;to_proc&lt;/code&gt;. What the method does is to turn a symbol into a simple Proc object. so we can say:&lt;br&gt;&lt;br&gt;&lt;code&gt;customers.collect &amp;amp;:name&lt;/code&gt; which does the job.&lt;/p&gt;&lt;p&gt;In practice, I always just use this built-in to_proc because it's free as long as you are on a Rails project. And there is no reason for me to justify I should spend time to make it even more magical.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.stephenchu.com/"&gt;Stephen&lt;/a&gt; also came up with syntax like:&lt;br&gt;&lt;code&gt;customers.collect_name_and_id&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The method always returns an array of arrays (&lt;code&gt;[['Yi', 1], ['Du', 2]]&lt;/code&gt;). The syntax looks very nice, but I think it has limited value because I may not want an array of arrays, I may want an array of hashes (&lt;code&gt;[{1 =&amp;gt; 'Yi'}, {2 =&amp;gt; 'Du']&lt;/code&gt;), or an array of strings, then the method has no use or we have to do more magic. Most importantly, when we want multiple fields from a model object to form some kind of data structure, we probably should ask ourselves first: what's the business meaning for this action? If we can find one, we can just add one method, returning whatever we want, to the model class we are dealing with and use that method for collect.&lt;/p&gt;&lt;p&gt;For example, if I want to send an email to several people and their email address should look like: &lt;br&gt;&lt;code&gt;people.collect{|person| "person.name &amp;lt;person.email&amp;gt;"}&lt;/code&gt;, then I probably will just add a method to the Person class, such as &lt;code&gt;Person#full_email_address&lt;/code&gt; and return the string I need. the the syntax for collect can be simplified to &lt;code&gt;people.collect &amp;amp;:full_email_address&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;It's cool to see how powerful &lt;code&gt;method_missing&lt;/code&gt; can be with &lt;a href="http://www.stephenchu.com/2007/03/enhance-arraycollect-to-become-magical.html"&gt;Stephen's&lt;/a&gt; extension, and how lovely Ruby is. 	&lt;/p&gt;&lt;img src="http://blogs.dovetailsoftware.com/aggbug.aspx?PostID=10758" width="1" height="1"&gt;</content><author><name>ywen</name><uri>http://blogs.dovetailsoftware.com/members/ywen.aspx</uri></author><category term="Ruby on Rails" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/Ruby+on+Rails/default.aspx" /></entry><entry><title>Why I hate test coverage tools</title><link rel="alternate" type="text/html" href="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/11/19/why-i-hate-test-coverage-tools.aspx" /><id>http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/11/19/why-i-hate-test-coverage-tools.aspx</id><published>2007-11-19T21:42:00Z</published><updated>2007-11-19T21:42:00Z</updated><content type="html">&lt;p&gt;Because it could lie if we abuse it. I have been in one project where people count acceptance tests (written in FIT) so the test coverage always looks pretty high when the unit tests coverage are actually poor. But the figure gave people there false confidence that their code is in good shape.&lt;/p&gt;

&lt;p&gt;In another project, a test had only two lines of code, but it actually ran about 5 seconds and touched a lot of code underneath. So by this test alone, it improved the test coverage a lot, looks pretty good eh? Then wait until it failed sometimes. People had absolutely no clue on why it failed and where it caused the failure. and then we could spent one hour to just pinpoint where the problem is. For me, this test is simply just not a test and should be replaced by a bunch of more fine-grained unit tests.&lt;/p&gt;

&lt;p&gt;The test coverage number is just a number. It helps when the number is low so that you know you have serious problems in your project. But when the number is high, it doesn't mean anything. We could still do something with it, such as browsing through the nice colored reports to see where we failed to test and if we should fix that. But we should never trust we are in good shape just because the number is high.&lt;/p&gt;

&lt;p&gt;To make our test coverage more meaningful, we should remember that TDD is a tool to help us designing our code, to improve the code quality. If we feel awkward in writing a test, then we know there is something wrong in our code and we should refactor that piece, instead of just writing a bad test or just be off.&lt;/p&gt;&lt;img src="http://blogs.dovetailsoftware.com/aggbug.aspx?PostID=10622" width="1" height="1"&gt;</content><author><name>ywen</name><uri>http://blogs.dovetailsoftware.com/members/ywen.aspx</uri></author><category term="unit test" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/unit+test/default.aspx" /><category term="test driven development" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/test+driven+development/default.aspx" /></entry><entry><title>When RSpec meets Validatable</title><link rel="alternate" type="text/html" href="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/11/12/when-rspec-meets-validatable.aspx" /><id>http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/11/12/when-rspec-meets-validatable.aspx</id><published>2007-11-12T16:36:00Z</published><updated>2007-11-12T16:36:00Z</updated><content type="html">&lt;A href="http://blog.jayfields.com/"&gt;Jay Fields&lt;/A&gt; writes an excellent module called &lt;A href="http://blog.jayfields.com/2007/11/validatable-166-released.html"&gt;Validatable&lt;/A&gt; to provide a class who include the module the ActiveRecord like behavior. For example, you can say &lt;I&gt;validates_presence_of :attribute&lt;/I&gt; etc. &lt;A href="http://validatable.rubyforge.org/"&gt;This page&lt;/A&gt; has the RDoc of the module. When I write RSpec for a Validatable class, I ended up writing a stattement like this: &lt;PRE&gt;   &lt;BR&gt;   @email.validate_only("presence_of/body") &lt;BR&gt;   @email.errors.on(:body).should_not be_nil&lt;BR&gt;&lt;/PRE&gt;Which is basically testing &lt;I&gt;body&lt;/I&gt; is a required field. It works, but it looks complicated and hard to understand. The RSpec on Rails plugin provides a method &lt;I&gt;error_on&lt;/I&gt; so that I can say something like this: &lt;PRE&gt; model.should have(2).errors_on(:attribute)&lt;BR&gt;&lt;/PRE&gt;This is much more readable than the previous one. I came up with a small extension on Validatable so that I can have a better syntax for testing Validatable. Here's the spec: &lt;PRE&gt;require File.dirname(__FILE__) + '/../../../spec_helper'&lt;BR&gt;&lt;BR&gt;module RspecValidatableSpec&lt;BR&gt;  class Thing&lt;BR&gt;    include Validatable&lt;BR&gt;    attr_accessor :age&lt;BR&gt;    attr_accessor :name&lt;BR&gt;    validates_presence_of :age&lt;BR&gt;    validates_numericality_of :age&lt;BR&gt;  end&lt;BR&gt;end&lt;BR&gt;&lt;BR&gt;describe RSpecValidatable, 'a validatable object' do&lt;BR&gt;  before :each do&lt;BR&gt;    @thing = RspecValidatableSpec::Thing.new&lt;BR&gt;  end&lt;BR&gt;  &lt;BR&gt;  it "should tell you it has at least one error on a field" do&lt;BR&gt;    @thing.should have_at_least(1).error_on(:age)&lt;BR&gt;  end&lt;BR&gt;&lt;BR&gt;  it "should tell you it has one error on a required field" do&lt;BR&gt;    @thing.should have(1).error_on_presence_of(:age)&lt;BR&gt;  end&lt;BR&gt;&lt;BR&gt;  it "should tell you it has one error on a numerical field" do&lt;BR&gt;    @thing.should have(1).error_on_numericality_of(:age)&lt;BR&gt;  end&lt;BR&gt;end&lt;BR&gt;&lt;BR&gt;describe RSpecValidatable, 'a validatable object' do&lt;BR&gt;  before :each do&lt;BR&gt;    @thing = RspecValidatableSpec::Thing.new&lt;BR&gt;  end&lt;BR&gt;&lt;BR&gt;  it "should tell you it has no error on a field" do&lt;BR&gt;    @thing.should have(:no).errors_on(:name)&lt;BR&gt;  end&lt;BR&gt;end&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;/PRE&gt;You may need a different path to your spec_helper.rb to make it work. I got the "traditional" &lt;I&gt;errors_on&lt;/I&gt; just like how RSpec works on ActiveRecords. What's more, Validatable has a &lt;I&gt;validates_only&lt;/I&gt; method which allows us validating only one type of error on one attribute. so I can have even better control than RSpec on Rails giving me over ActiveRecords. For example, I can specify what type of errors I expect to have. The only problem is that &lt;I&gt;validates_only&lt;/I&gt; raises an error if you check an attribute on a validation that is not specified. So a nice spec like &lt;PRE&gt;email.should have(:no).errors_on_presence_of(:attachment)&lt;BR&gt;&lt;/PRE&gt;is not quite possible. For those of you who are interested in this, here is the actual code: &lt;PRE class=textmate-source&gt;&lt;SPAN class="source source_ruby source_ruby_rails"&gt;&lt;SPAN class="meta meta_module meta_module_ruby"&gt;&lt;SPAN class="keyword keyword_control keyword_control_module keyword_control_module_ruby"&gt;module&lt;/SPAN&gt; &lt;SPAN class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby"&gt;RSpecValidatable&lt;/SPAN&gt;&lt;/SPAN&gt;
  &lt;SPAN class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"&gt;&lt;SPAN class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/SPAN&gt; &lt;SPAN class="entity entity_name entity_name_function entity_name_function_ruby"&gt;errors_on&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;(&lt;/SPAN&gt;&lt;SPAN class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby"&gt;attribute&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/SPAN&gt;&lt;/SPAN&gt;
    &lt;SPAN class="variable variable_language variable_language_ruby"&gt;self&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;valid?
    &lt;SPAN class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;[&lt;/SPAN&gt;&lt;SPAN class="variable variable_language variable_language_ruby"&gt;self&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;errors&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;on&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/SPAN&gt;attribute&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;]&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;flatten&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;compact
  &lt;SPAN class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/SPAN&gt;

  &lt;SPAN class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"&gt;&lt;SPAN class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/SPAN&gt; &lt;SPAN class="entity entity_name entity_name_function entity_name_function_ruby"&gt;respond_to?&lt;/SPAN&gt;&lt;/SPAN&gt; method_name
    &lt;SPAN class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby"&gt;super&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/SPAN&gt;method_name&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/SPAN&gt; &lt;SPAN class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby"&gt;||&lt;/SPAN&gt; method_name&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;to_s&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;index&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/SPAN&gt;&lt;SPAN class="string string_quoted string_quoted_single string_quoted_single_ruby"&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby"&gt;'&lt;/SPAN&gt;error_on&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby"&gt;'&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/SPAN&gt; &lt;SPAN class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby"&gt;==&lt;/SPAN&gt; &lt;SPAN class="constant constant_numeric constant_numeric_ruby"&gt;0&lt;/SPAN&gt;  
  &lt;SPAN class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/SPAN&gt;
  
  &lt;SPAN class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"&gt;&lt;SPAN class="keyword keyword_control keyword_control_def keyword_control_def_ruby"&gt;def&lt;/SPAN&gt; &lt;SPAN class="entity entity_name entity_name_function entity_name_function_ruby"&gt;method_missing&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;(&lt;/SPAN&gt;&lt;SPAN class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby"&gt;error_on_method&lt;SPAN class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/SPAN&gt; attribute&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/SPAN&gt;&lt;/SPAN&gt;
    reason &lt;SPAN class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/SPAN&gt; error_on_method&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;to_s&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;sub&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/SPAN&gt;&lt;SPAN class="string string_regexp string_regexp_classic string_regexp_classic_ruby"&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby"&gt;/&lt;/SPAN&gt;error_on_&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby"&gt;/&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/SPAN&gt; &lt;SPAN class="string string_quoted string_quoted_single string_quoted_single_ruby"&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby"&gt;'&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby"&gt;'&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/SPAN&gt; 
    &lt;SPAN class="variable variable_language variable_language_ruby"&gt;self&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;validate_only&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/SPAN&gt;&lt;SPAN class="string string_quoted string_quoted_double string_quoted_double_ruby"&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby"&gt;"&lt;/SPAN&gt;&lt;SPAN class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby"&gt;#{&lt;/SPAN&gt;reason&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;to_s&lt;SPAN class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby"&gt;}&lt;/SPAN&gt;&lt;/SPAN&gt;/&lt;SPAN class="source source_ruby source_ruby_embedded source_ruby_embedded_source"&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby"&gt;#{&lt;/SPAN&gt;attribute&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;to_s&lt;SPAN class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby"&gt;}&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby"&gt;"&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/SPAN&gt;
    &lt;SPAN class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;[&lt;/SPAN&gt;&lt;SPAN class="variable variable_language variable_language_ruby"&gt;self&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;errors&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;on&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/SPAN&gt;attribute&lt;SPAN class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;]&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;flatten&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;compact
  &lt;SPAN class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/SPAN&gt;
  
  &lt;SPAN class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby"&gt;alias&lt;/SPAN&gt; &lt;SPAN class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby"&gt;:&lt;/SPAN&gt;error_on&lt;/SPAN&gt; &lt;SPAN class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby"&gt;:&lt;/SPAN&gt;errors_on&lt;/SPAN&gt;
  
&lt;SPAN class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/SPAN&gt;

&lt;SPAN class="support support_class support_class_ruby"&gt;Validatable&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/SPAN&gt;send &lt;SPAN class="constant constant_other constant_other_symbol constant_other_symbol_ruby"&gt;&lt;SPAN class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby"&gt;:&lt;/SPAN&gt;include&lt;/SPAN&gt;&lt;SPAN class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/SPAN&gt; &lt;SPAN class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;RSpecValidatable&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;/PRE&gt;&lt;img src="http://blogs.dovetailsoftware.com/aggbug.aspx?PostID=10028" width="1" height="1"&gt;</content><author><name>ywen</name><uri>http://blogs.dovetailsoftware.com/members/ywen.aspx</uri></author><category term="RSpec" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/RSpec/default.aspx" /><category term="Validatable" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/Validatable/default.aspx" /><category term="Ruby on Rails" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/Ruby+on+Rails/default.aspx" /></entry><entry><title>Law of Demeter and Forwardable</title><link rel="alternate" type="text/html" href="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/11/02/law-of-demeter-and-forwardable.aspx" /><id>http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/11/02/law-of-demeter-and-forwardable.aspx</id><published>2007-11-02T18:26:00Z</published><updated>2007-11-02T18:26:00Z</updated><content type="html">&lt;p&gt;Dan Manges has an excellent &lt;a href="http://www.dcmanges.com/blog/37" title="Law of Demeter" target="_blank"&gt;post&lt;/a&gt; explaining Law of Demeter and when it makes sense to use Forwardable to comply the principle, or I should say when it doesn't make sense to use the module. &lt;/p&gt;&lt;p&gt;The point is, use it when it makes sense. Take his example, customer_name is just not a sensible method for an order. Asking an order for its customer name is a wrong question because all the order should care is who is its customer. The name is irrelevant to the order.&amp;nbsp;  &lt;/p&gt;&lt;p&gt;In fact, I think by putting cusomer_name method in an order. the encapsulation is actually broken because now an order knows the inside details of a customer, thus tightly coupled these two classes.&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.dovetailsoftware.com/aggbug.aspx?PostID=9513" width="1" height="1"&gt;</content><author><name>ywen</name><uri>http://blogs.dovetailsoftware.com/members/ywen.aspx</uri></author><category term="ruby forwardable law of demeter" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/ruby+forwardable+law+of+demeter/default.aspx" /></entry><entry><title>Fluent interface for Ruby delegation</title><link rel="alternate" type="text/html" href="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/10/29/fluent-interface-for-ruby-delegation.aspx" /><id>http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/2007/10/29/fluent-interface-for-ruby-delegation.aspx</id><published>2007-10-29T22:26:00Z</published><updated>2007-10-29T22:26:00Z</updated><content type="html">This is a &lt;a href="http://www.brynary.com/2007/4/8/fluent-interface-for-ruby-delegation" title="Bryan's blog"&gt;link&lt;/a&gt; to Bryan's blog for Fluent interface for Ruby delegation. We used it in our codebase for&amp;nbsp; better (read: more readable) syntax. You might be interested in.&lt;br&gt;&lt;img src="http://blogs.dovetailsoftware.com/aggbug.aspx?PostID=9360" width="1" height="1"&gt;</content><author><name>ywen</name><uri>http://blogs.dovetailsoftware.com/members/ywen.aspx</uri></author><category term="ruby delegation forwardable" scheme="http://blogs.dovetailsoftware.com/blogs/yi_wen/archive/tags/ruby+delegation+forwardable/default.aspx" /></entry></feed>