<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-28670731</id><updated>2012-01-28T07:22:44.920-08:00</updated><category term='fluent interfaces'/><category term='tdd'/><category term='metaprogramming'/><category term='has-one'/><category term='self-referential'/><category term='rails'/><category term='ActiveRecord'/><category term='symmetrical'/><title type='text'>Practical Ruby</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>John Hume</name><uri>http://www.blogger.com/profile/00164870439569642842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/1/buddyicons/50377630@N00.jpg?1096547663'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-28670731.post-4375357801047111220</id><published>2007-03-13T14:43:00.000-07:00</published><updated>2007-03-14T20:15:20.819-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='self-referential'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='symmetrical'/><category scheme='http://www.blogger.com/atom/ns#' term='has-one'/><title type='text'>Symmetric, self-referential has-one relationships in Rails</title><content type='html'>Suppose you have a Person model, and you want to represent that a Person can have a spouse. That's a self-referential relationship: the Spouse would be obviously be another Person. What makes this example a little more interesting than a standard self-referential has-one relationship is that the relationship is symmetric. You could, in theory, create the relationship from either perspective.&lt;br /&gt;&lt;br /&gt;If we have Alice and Bob:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       alice = Person.create!&lt;br /&gt;       bob = Person.create!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       alice.spouse = bob&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;should be just as valid as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       bob.spouse = alice&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The problem is that if you set the relationship up as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       class Person &lt; class_name =""&gt; 'Person'&lt;br /&gt;&lt;br /&gt;       end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then whoever you add the spouse to first "has" the spouse.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       alice.spouse = bob&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;would mean that&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       bob.spouse&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;returns nil&lt;br /&gt;&lt;br /&gt;That's clearly wrong. We want to be able to query Bob for his spouse and return Alice.&lt;br /&gt;&lt;br /&gt;We tried a number of solutions, including overriding the getter or setter, but the solution we found easiest was to build the relationship ourselves and not use any of the built-in Rails relationship functions.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       def spouse&lt;br /&gt;         if @spouse.nil? &amp;&amp;amp; !spouse_id.blank? || !@spouse.nil? &amp;&amp;amp; @spouse.id != spouse_id&lt;br /&gt;            @spouse = spouse_id.blank? ? nil : Person.find(spouse_id)&lt;br /&gt;         end&lt;br /&gt;         @spouse&lt;br /&gt;       end&lt;br /&gt;&lt;br /&gt;       def spouse=(new_spouse)&lt;br /&gt;         raise(ApplicationError, "Both persons must be saved records in order to connect.") if !new_spouse.nil? &amp;&amp;amp; (new_record? || new_spouse.new_record?)&lt;br /&gt; &lt;br /&gt;         unless new_spouse.nil?&lt;br /&gt;           new_spouse.get_a_divorce&lt;br /&gt;           new_spouse.set_spouse_and_id(self)&lt;br /&gt;           new_spouse.save!&lt;br /&gt;         end&lt;br /&gt;&lt;br /&gt;         get_a_divorce&lt;br /&gt;         set_spouse_and_id(new_spouse)&lt;br /&gt;         save!&lt;br /&gt;       end&lt;br /&gt;&lt;br /&gt;       def spouse_id=(new_spouse_id)&lt;br /&gt;         self.spouse = (new_spouse_id.blank? ? nil : Person.find(new_spouse_id))&lt;br /&gt;         save!&lt;br /&gt;       end&lt;br /&gt;&lt;br /&gt;   private&lt;br /&gt;&lt;br /&gt;       def set_spouse_and_id(new_spouse)&lt;br /&gt;         @spouse = new_spouse&lt;br /&gt;         self[:spouse_id] = new_spouse.nil? ? nil : new_spouse.id&lt;br /&gt;       end&lt;br /&gt;&lt;br /&gt;       def get_a_divorce&lt;br /&gt;         unless spouse.nil?&lt;br /&gt;           spouse.set_spouse_and_id(nil)&lt;br /&gt;           spouse.save!&lt;br /&gt;         end&lt;br /&gt;       end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The main points are:&lt;br /&gt;Your setter has to make sure that both sides of the relationship are disconnected before joining because you never know if the key is stored in the objects you're currently dealing with, or in their *former* partners.&lt;br /&gt;Your getter has to do a search for your ID if your object doesn't have a foreign-key reference because the key could be stored on either side.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-4375357801047111220?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/4375357801047111220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=4375357801047111220' title='179 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/4375357801047111220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/4375357801047111220'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2007/03/symmetric-self-referential-has-one.html' title='Symmetric, self-referential has-one relationships in Rails'/><author><name>sarnacke</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>179</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-130226316189554611</id><published>2007-03-09T06:18:00.000-08:00</published><updated>2007-03-09T10:02:54.918-08:00</updated><title type='text'>super accesses the inaccessible</title><content type='html'>Ali and I ran across something yesterday that surprised us.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;class Base; def foo; 'Base.foo'; end; end&lt;br /&gt;module Mod; def foo; 'Mod.foo'; end; end&lt;br /&gt;class Sub &lt; Base&lt;br /&gt;  include Mod&lt;br /&gt;  def foo; "Sub.foo calls super =&gt; #{super}"; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;Sub.superclass  # =&gt; Base&lt;br /&gt;Sub.new.foo     # =&gt; "Sub.foo calls super =&gt; Mod.foo"&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Chapter 22 of the &lt;a href="http://www.pragmaticprogrammer.com/titles/ruby/index.html"&gt;Pickaxe&lt;/a&gt; tells us (on page 335) that &lt;blockquote cite="http://www.pragmaticprogrammer.com/titles/ruby/index.html"&gt;Within the body of a method, a call to &lt;code&gt;super&lt;/code&gt; acts just like a call to that original method, except that the search for a method body starts in the superclass of the object that was found to contain the original method.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Then (on page 340) that &lt;blockquote cite="http://www.pragmaticprogrammer.com/titles/ruby/index.html"&gt;If a module is included within a class definition, the module’s constants, class variables, and instance methods are effectively bundled into an anonymous (and inaccessible) superclass for that class.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;It goes on to say that a module's &lt;code&gt;initialize&lt;/code&gt; will be called if an including class's &lt;code&gt;initialize&lt;/code&gt; calls &lt;code&gt;super&lt;/code&gt;, but doesn't mention that this is a consequence of how &lt;code&gt;super&lt;/code&gt; works everywhere, not special handling for &lt;code&gt;initialize&lt;/code&gt;.  (Why might one assume &lt;code&gt;initialize&lt;/code&gt; gets special handling? Because it gets &lt;a href="http://www.rubycentral.com/faq/rubyfaq-7.html#ss7.8"&gt;special handling with respect to visibility&lt;/a&gt;. Special cases create confusion.)&lt;br /&gt;&lt;br /&gt;So it turns out &lt;code&gt;super&lt;/code&gt; goes hunting up the chain as if the method using it hadn't been found. (I avoid using the word 'superclass' because it's ambiguous in Ruby due to the anonymous proxy classes responsible for putting mixins into the inheritance chain.) I like that Ruby works this way, but it further supports Pat Farley's case that the difference between multiple inheritance and Ruby's mixins has been grossly overstated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-130226316189554611?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/130226316189554611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=130226316189554611' title='163 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/130226316189554611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/130226316189554611'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2007/03/super-accesses-inaccessible.html' title='super accesses the inaccessible'/><author><name>John Hume</name><uri>http://www.blogger.com/profile/00164870439569642842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/1/buddyicons/50377630@N00.jpg?1096547663'/></author><thr:total>163</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-221333554049395216</id><published>2007-02-21T19:12:00.000-08:00</published><updated>2007-02-21T20:13:27.455-08:00</updated><title type='text'>Reopen with module_eval</title><content type='html'>&lt;p&gt;Ruby has open classes, and that's cool.  If you're partially defining a class and don't care whether other parts of the definition have already been loaded, then by all means take advantage of the fact that you can reopen using the same syntax you use to define in the first place.&lt;/p&gt;    &lt;pre&gt;class Sub &lt; Base # this may create Sub or reopen it.&lt;br /&gt;  def asdf ... end&lt;br /&gt;end&lt;/pre&gt;                &lt;p&gt;However, this is a pretty unusual case on a real project.  Typically a class from a third-party library is reopened to modify its original implementation.  Often a method is aliased or undefined.  If the original definition hasn't been loaded already, the reopening won't accomplish its intent.  Hopefully it will fail at some point during the reopening.  If you're unlucky (for example if you're trying to replace a method by simply re-&lt;code&gt;def&lt;/code&gt;'ing) you may get through your code without an error, leaving you with a very difficult to find bug.&lt;/p&gt;             &lt;p&gt;If you're reopening in this sort of situation, I recommend using &lt;code&gt;class_eval&lt;/code&gt;/&lt;code&gt;module_eval&lt;/code&gt; rather than a class-declaration-style reopening.&lt;/p&gt;     &lt;pre&gt;Sub.class_eval do&lt;br /&gt;  def asdf ... end&lt;br /&gt;end&lt;/pre&gt;                      &lt;p&gt;This way, if the original class definition hasn't already been loaded, your code will fail quickly and cleanly as soon as you try to touch the class (with a &lt;code&gt;NameError: uninitialized constant WhateverYouTriedToReopen&lt;/code&gt;) rather than more mysteriously some time later.  (Always prefer failing fast and clean when practical.)&lt;/p&gt;                                   &lt;p&gt;The benefit of this is even greater if you're working with Rails: If you try to call &lt;code&gt;class_eval&lt;/code&gt; on a class that hasn't been loaded yet, the &lt;code&gt;const_missing&lt;/code&gt; in &lt;code&gt;dependencies.rb&lt;/code&gt; will kick in and go looking for the class you're reopening, loading it just in time for you to bend it to your will.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-221333554049395216?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/221333554049395216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=221333554049395216' title='186 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/221333554049395216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/221333554049395216'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2007/02/reopen-with-moduleeval.html' title='Reopen with module_eval'/><author><name>John Hume</name><uri>http://www.blogger.com/profile/00164870439569642842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/1/buddyicons/50377630@N00.jpg?1096547663'/></author><thr:total>186</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-116803399908628649</id><published>2007-02-17T15:02:00.000-08:00</published><updated>2007-02-17T12:07:44.446-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='fluent interfaces'/><title type='text'>Unit Testing Delegation ... Handoff!</title><content type='html'>Delegation is easy to implement in Ruby, but if you're working test-first and trying to stick to strict unit tests, it can be a challenge to specify delegation succinctly.  (Some feel that delegation is so simple that it's a waste to have tests for it.  This depends on how you use your tests.  This isn't an article about that.  If your team isn't interested in unit testing delegation, don't do it.  If you find it valuable, read on.)&lt;br /&gt;&lt;br /&gt;I recently had a fairly long discussion with Jay during a developer lunch at our current project about unit testing delegation.  He and Z had implemented unit tests that mocked the &lt;code&gt;def_delegators&lt;/code&gt; method (of &lt;code&gt;&lt;a href="http://ruby-doc.org/stdlib/libdoc/forwardable/rdoc/classes/Forwardable.html" title="RDoc for Forwardable"&gt;Forwardable&lt;/a&gt;&lt;/code&gt;) in the class under test to reduce the size of some very wordy tests.&lt;br /&gt;&lt;br /&gt;The tests they discovered looked something like the below, mocking the method used to access the delegate and returning a mock delegate that expected the delegate method to be invoked.&lt;br /&gt;&lt;pre&gt;test 'delegates title to content_provider' do&lt;br /&gt;  o = ClassBeingTested.new&lt;br /&gt;  o.expects(:content_provider).returns(mock(:title =&gt; :some_title))&lt;br /&gt;  assert_same :some_title, o.title&lt;br /&gt;end&lt;br /&gt;test 'delegates sub_title to content_provider' do&lt;br /&gt;  o = ClassBeingTested.new&lt;br /&gt;  o.expects(:content_provider).returns(mock(:sub_title =&gt; :some_title))&lt;br /&gt;  assert_same :some_title, o.title&lt;br /&gt;end&lt;br /&gt;test 'delegates help_text to content_provider' do&lt;br /&gt;  o = ClassBeingTested.new&lt;br /&gt;  o.expects(:content_provider).returns(mock(:sub_title =&gt; :some_title))&lt;br /&gt;  assert_same :some_title, o.title&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;Or maybe it was more like this.  I don't remember which.&lt;br /&gt;&lt;pre&gt;test 'delegates to content_provider for title, sub_title, and help_text' do&lt;br /&gt;  o = ClassBeingTested.new&lt;br /&gt;  o.expects(:content_provider).at_least_once.returns(&lt;br /&gt;    mock(&lt;br /&gt;      :title =&gt;     :some_title, &lt;br /&gt;      :sub_title =&gt; :some_sub_title, &lt;br /&gt;      :help_text =&gt; :some_help_text))&lt;br /&gt;&lt;br /&gt;  assert_same :some_title, o.title&lt;br /&gt;  assert_same :some_sub_title, o.sub_title&lt;br /&gt;  assert_same :some_help_text, o.help_text&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;In any case, they needed to add some new delegating behavior to the class, and they thought what had been written was awfully wordy.  Maybe you think five lines to test three delegating methods is pretty good, but consider that the code under test is something like:&lt;br /&gt;&lt;pre&gt;class ClassUnderTest&lt;br /&gt;  extend Forwardable&lt;br /&gt;  def_delegators :content_provider, :title, :sub_title, :help_text&lt;br /&gt;  # ... plus stuff we're not talking about here, including the method&lt;br /&gt;  # 'content_provider' that gets the delegate.&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;The delegation of all three methods is just one line of code!  (That is, if you don't count the line where the class extends &lt;code&gt;Forwardable&lt;/code&gt;.)  Since implementing delegation is that easy, why should we have to write so much code to test the behavior?  &lt;br /&gt;&lt;br /&gt;They thought about it and tried another strategy: since the delegation plumbing is provided by &lt;code&gt;Forwardable&lt;/code&gt;, they would test that its class methods were called correctly by mocking them out.  Their new test did something like:&lt;br /&gt;&lt;pre&gt;test 'delegates price and has_rebate? to model' do&lt;br /&gt;  ClassBeingTested.expects(:def_delegators).with(:model, :price, :has_rebate?)&lt;br /&gt;  load 'class_being_tested'&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;The method &lt;code&gt;load&lt;/code&gt; is like &lt;code&gt;require&lt;/code&gt;, but without caching its results and turning no-op when the file has already been loaded.  It forces the class definition to run again, calling &lt;code&gt;def_delegators&lt;/code&gt; again.&lt;br /&gt;&lt;br /&gt;A clever solution, but it felt wrong to me.&lt;br /&gt;&lt;br /&gt;Mock-based testing requires us to dictate to some extent what our implementation will look like.  This is an evil we live with when it also provides a fairly readable description of a class's responsibilities.  But here, we seemed to have lost site of the responsibility.  The responsibility we want to show is that the object delegates.  How it accomplishes that delegation is a detail we'd rather leave to the class.  The more closely a test is tied to implementation,  the more likely it is that we'll need to change the test when we change the class, even if the class's responsibilities are not being changed.&lt;br /&gt;&lt;br /&gt;What made the test great was its brevity, but looking back at the original tests, I saw that we could have something just as brief, more readable, and which was not tied to the specific implementation.  I wanted a test that looked something like this:&lt;br /&gt;&lt;pre&gt;test 'delegates price and has_rebate? to model' do&lt;br /&gt;  assert(ClassUnderTest.new).delegates_to(:model).for_methods(:price, :has_rebate?)&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;but that actually exercised the delegating behavior similar to the long-hand tests we started with, so that whether delegation was declared with def_delegator, def_delegators, or implemented manually, the tests would be happy.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://www.martinfowler.com/bliki/FluentInterface.html" title="Martin Fowler's definitional Bliki entry FluentInterface"&gt;fluent interface&lt;/a&gt; for testing simple delegation is achievable because the responsibility we're testing is so straightforward: &lt;blockquote&gt;"When I send &lt;code&gt;price&lt;/code&gt; or &lt;code&gt;has_rebate?&lt;/code&gt; to the object, it should send the same messages to the object it gets from its &lt;code&gt;model&lt;/code&gt; method and return what that returns, without any knowledge of the thing returned."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The drawback to a fluent interface is that it can be difficult to debug failures, particularly those due to misuse of the interface itself.  It's easy to imagine a developer writing the following and expecting it to work.&lt;br /&gt;&lt;pre&gt;assert(ClassUnderTest.new).delegates_to(:model)&lt;/pre&gt;&lt;br /&gt;Although that reads nicely, it doesn't actually say enough to be able to test anything.  We have to be able to implement the interface in such a way that this sort of misuse won't result in tests silently doing nothing.&lt;br /&gt;&lt;br /&gt;This seemed like a solvable problem, so I set out to implement it.  The result is now available as &lt;a href="http://handoff.rubyforge.org/"&gt;Handoff&lt;/a&gt; (via &lt;code&gt;gem install handoff&lt;/code&gt;). &lt;br /&gt;&lt;br /&gt;As the interface worked out, assertions look like this:&lt;br /&gt;&lt;pre&gt;assert_handoff.from(ClassUnderTest.new).to(:content_provider).for(:title, :sub_title)&lt;/pre&gt;&lt;br /&gt;It supports method names that differ between the delegating object and the delegate, as well as specification of arguments that should be propagated, for example.&lt;br /&gt;&lt;pre&gt;assert_handoff.from(ClassUnderTest.new).to(:foo).for(:bar =&gt; :foo_bar, :baz =&gt; :foo_baz).with('arg1', :arg2, 3)&lt;/pre&gt;&lt;br /&gt;Give it a try.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-116803399908628649?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/116803399908628649/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=116803399908628649' title='166 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/116803399908628649'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/116803399908628649'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2007/01/unit-testing-delegation.html' title='Unit Testing Delegation ... Handoff!'/><author><name>John Hume</name><uri>http://www.blogger.com/profile/00164870439569642842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/1/buddyicons/50377630@N00.jpg?1096547663'/></author><thr:total>166</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-4373064896103943322</id><published>2007-02-10T11:01:00.000-08:00</published><updated>2007-02-17T10:00:29.383-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='metaprogramming'/><title type='text'>A Ruby Metaprogramming Introduction</title><content type='html'>&lt;p&gt;I was playing around with some unit tests to explore Ruby singleton classes on a recent flight when I decided they could be fleshed out into a pretty nice introduction to some basics of Ruby &lt;a href="http://en.wikipedia.org/wiki/Metaprogramming"&gt;metaprogramming&lt;/a&gt; for those who haven't done much with Ruby (which probably includes most people who've only written Rails applications). I particularly like the format because readers can &lt;ul&gt;&lt;li&gt;read it in their syntax-highlighting editor of choice, and&lt;/li&gt; &lt;li&gt;play with the code locally to explore further.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;  &lt;p&gt;If you want to get straight to mucking around, &lt;a href="http://subres.net/software/MetaprogrammingIntroduction_0.4.zip"&gt;download this zip file, which also contains &lt;code&gt;demo_test_unit_extensions.rb&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;If you're not that invested yet, here it is.&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;require '&lt;a href="http://subres.net/software/demo_test_unit_extensions.rb"&gt;demo_test_unit_extensions&lt;/a&gt;'&lt;br /&gt;&lt;br /&gt;class &lt;a href="http://subres.net/software/metaprogramming_introduction.rb"&gt;MetaprogrammingIntroduction&lt;/a&gt; &lt; Test::Unit::TestCase&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;  &lt;br /&gt;This is a demonstration of dynamic method definition using the private method&lt;br /&gt;Module#define_method and an introduction to singleton classes (also known as&lt;br /&gt;metaclasses). This is the basis of Ruby metaprogramming.&lt;br /&gt;&lt;br /&gt;Note that I'm going to avoid use or discussion of Ruby's very important eval&lt;br /&gt;methods in this article. This is only to reduce the scope of what's explained.&lt;br /&gt;In practice I'd prefer module_eval or class_eval to reopening of classes or&lt;br /&gt;modules or use of Object#send to invoke private methods.&lt;br /&gt;&lt;br /&gt;Chapter 24 in the Pickaxe is your reference for the nuts and bolts of Ruby&lt;br /&gt;classes. There's surprisingly little discussion of things you can do with&lt;br /&gt;metaprogramming, but all the information you need is there. _why the lucky&lt;br /&gt;stiff's Seeing Metaclasses Clearly is dense and opaque, but fun:&lt;br /&gt;  &lt;a href="http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html" &gt;http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&lt;/a&gt;&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Calling define_method on a class adds an instance method to both&lt;br /&gt;  existing and new instances.&lt;/span&gt;" do&lt;br /&gt;    GuineaPig = Class.new&lt;br /&gt;    pig = GuineaPig.new&lt;br /&gt;    class GuineaPig&lt;br /&gt;      define_method :next_integer do&lt;br /&gt;        @count = (@count || 0) + 1&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    assert_equal 1, pig.next_integer&lt;br /&gt;    assert_equal 2, pig.next_integer&lt;br /&gt;    assert_equal 1, GuineaPig.new.next_integer&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;This isn't all that cool, as we could have defined next_integer using the def&lt;br /&gt;keyword. But Module#define_method allows us to do a couple of things the def&lt;br /&gt;keyword doesn't. &lt;br /&gt;&lt;br /&gt;First, we can define our method name dynamically. Module#define_method takes a&lt;br /&gt;symbol or string as the method name, whereas the method name following the def&lt;br /&gt;keyword must be spelled out literally. You can satisfy this by evaluating a&lt;br /&gt;string of Ruby code that defines the method using def, but I usually find this&lt;br /&gt;less readable than using define_method. Try them both and see which reads better&lt;br /&gt;in your context.&lt;br /&gt;&lt;br /&gt;The second interesting aspect of using define_method is that you pass it a&lt;br /&gt;block, Ruby's closure.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Method bodies created with define_method can reference the context in&lt;br /&gt;  which they were created.&lt;/span&gt;" do&lt;br /&gt;    GuineaCounter = Class.new&lt;br /&gt;    shared_count = 0 # A new local variable.&lt;br /&gt;    GuineaCounter.send :define_method, :double_count do&lt;br /&gt;      shared_count += 1&lt;br /&gt;      @count ||= 0&lt;br /&gt;      @count += 1&lt;br /&gt;      [shared_count, @count]&lt;br /&gt;    end&lt;br /&gt;    first_counter = GuineaCounter.new&lt;br /&gt;    second_counter = GuineaCounter.new&lt;br /&gt;    &lt;br /&gt;    assert_equal [1, 1], first_counter.double_count&lt;br /&gt;    assert_equal [2, 2], first_counter.double_count&lt;br /&gt;    assert_equal [3, 1], second_counter.double_count&lt;br /&gt;    assert_equal [4, 2], second_counter.double_count&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;Even if the method that defined the local variable shared_count completed&lt;br /&gt;execution, the method in GuineaCounter will still be bound to the context of the&lt;br /&gt;method. (This binding isn't simple, as the block also assigns instance variables&lt;br /&gt;which obviously land in the right place. Look for a forthcoming write-up&lt;br /&gt;exploring this in depth.)&lt;br /&gt;&lt;br /&gt;Note the use of Object#send to invoke define_method, where we just reopened the&lt;br /&gt;class in earlier demonstrations. This is necessary if we want the block to bind&lt;br /&gt;to our local context. As mentioned earlier, I prefer module_eval or class_eval&lt;br /&gt;for this, but I'm leaving those out of this article.&lt;br /&gt;&lt;br /&gt;This next one may seem obvious, but it'll only take a moment.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Sending define_method to a module is consistent with sending it to a&lt;br /&gt;  class.&lt;/span&gt;" do&lt;br /&gt;    o = Object.new.extend(Enumerable)&lt;br /&gt;    # Object#extend mixes a module into an instance without affecting other &lt;br /&gt;    # instances of the same class.&lt;br /&gt;    &lt;br /&gt;    assert(o.is_a?(Enumerable) &amp;&amp; {}.is_a?(Enumerable))&lt;br /&gt;    &lt;br /&gt;    hash = {}&lt;br /&gt;    Enumerable.send :define_method, :next_integer_for_enumerables do&lt;br /&gt;      @count_for_enumerables = (@count_for_enumerables || 0) + 1&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    assert_equal 1, o.next_integer_for_enumerables&lt;br /&gt;    assert_equal 1, hash.next_integer_for_enumerables&lt;br /&gt;    assert_equal 2, hash.next_integer_for_enumerables&lt;br /&gt;    assert_equal 1, Array.new.next_integer_for_enumerables&lt;br /&gt;    # But since we only extended that one instance of Object up above ...&lt;br /&gt;    assert_raises(NoMethodError) { Object.new.next_integer_for_enumerables }&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;This next point is something of a tangent, but it's important to keep in mind,&lt;br /&gt;as it could bite you at some point.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Remember that adding methods to Object puts them all over the place, so&lt;br /&gt;  be careful!&lt;/span&gt;" do&lt;br /&gt;    o = Object.new&lt;br /&gt;    Object.send :define_method, :next_integer_for_all do&lt;br /&gt;      @count_for_all = (@count_for_all || 0) + 1&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    # So obviously, ...&lt;br /&gt;    assert_equal 1, o.next_integer_for_all&lt;br /&gt;    assert_equal 2, o.next_integer_for_all&lt;br /&gt;    &lt;br /&gt;    # But we also now have the method in this Test::Unit::TestCase.&lt;br /&gt;    assert_nil @count_for_all&lt;br /&gt;    assert_equal 1, next_integer_for_all&lt;br /&gt;    assert_equal 1, @count_for_all&lt;br /&gt;    &lt;br /&gt;    # Classes are Objects too, so they've all gained a class method, which&lt;br /&gt;    # maintains a count independent from its instances.&lt;br /&gt;    assert_equal 1, String.next_integer_for_all&lt;br /&gt;    assert_equal 2, String.next_integer_for_all&lt;br /&gt;    assert_equal 1, "".next_integer_for_all&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;This isn't mind-blowing, but it can be easy to accidentally call the method with&lt;br /&gt;the wrong receiver if you lose track of your current context.&lt;br /&gt;&lt;br /&gt;The takeaways from that are: &lt;br /&gt; * don't add methods to Object unless you've got a damn good reason, and&lt;br /&gt; * prove that you're getting the desired behavior with tests.&lt;br /&gt;&lt;br /&gt;Now here's where the cool stuff starts! Let's talk about singleton methods and&lt;br /&gt;classes.&lt;br /&gt;&lt;br /&gt;Above, we used Object#extend to mix a module into one instance of Object without&lt;br /&gt;affecting other instances or the Object class itself. You've probably also seen&lt;br /&gt;that Ruby allows you to define methods on just single instances. When done the&lt;br /&gt;simple way, this looks like the following:&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Methods can be defined on single instances using the def keyword.&lt;br /&gt;  These are referred to as 'singleton methods.'&lt;/span&gt;" do&lt;br /&gt;    o, p = Object.new, Object.new&lt;br /&gt;    &lt;br /&gt;    def o.say_hi&lt;br /&gt;      'hello there'&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    assert_equal 'hello there', o.say_hi&lt;br /&gt;    assert_raises(NoMethodError) { p.say_hi }&lt;br /&gt;    assert_equal ['say_hi'], o.singleton_methods&lt;br /&gt;    assert_true p.singleton_methods.empty?&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;So that's neat, but what if we want some of the power of Module#define_method&lt;br /&gt;discussed earlier? What module or class should define_method to add a method to&lt;br /&gt;just one object? The singleton class!&lt;br /&gt;&lt;br /&gt;Classes and Modules are special objects that can hold methods for other objects&lt;br /&gt;to respond to. It would have been a shame for Matz to have had to implement&lt;br /&gt;another sort of method owning facility to handle singleton methods, so Ruby does&lt;br /&gt;some hidden trickery when we define a method on an instance: it creates a&lt;br /&gt;virtual class to hold methods specific to that object, inserting it into the&lt;br /&gt;chain of classes that will be checked for methods when it's looking to handle a&lt;br /&gt;message sent to the object. The object's class method will still return the&lt;br /&gt;original class, but the singleton class actually gets "first dibs" at responding&lt;br /&gt;to a call. These classes are hidden from ObjectSpace and created without calling&lt;br /&gt;Class.new, making them hard to get a hold of.&lt;br /&gt;&lt;br /&gt;What do we call these things? The term 'singleton class' makes some sense, as&lt;br /&gt;there's only one per object. This name can be confusing though, because of the&lt;br /&gt;Singleton design pattern (easily implemented in Ruby by including the stdlib&lt;br /&gt;module Singleton). The term 'metaclass' is used frequently, but it comes from&lt;br /&gt;other languages and really applies only to the class of a class. Matz is&lt;br /&gt;considering calling singleton classes 'eigenclasses' in future versions of Ruby&lt;br /&gt;to reduce confusion with other concepts. (Chances are you don't have a&lt;br /&gt;preconceived notion of what 'eigenclass' ought to mean, so there's nothing to&lt;br /&gt;get mixed up with these funny classes in Ruby.) I'll continue to refer to these&lt;br /&gt;as 'singleton classes' for now.&lt;br /&gt;&lt;br /&gt;How unusual is it for singleton classes to come into play? It happens far more&lt;br /&gt;frequently than we think about them, because all class methods are actually&lt;br /&gt;singleton methods of instances of Class. Here's a simple class with a couple&lt;br /&gt;class methods.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  class Greeter&lt;br /&gt;    def greet; 'hello!'; end&lt;br /&gt;    &lt;br /&gt;    def self.describe_greeting&lt;br /&gt;      'Mostly it''s just saying hello to people.'&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def Greeter.say_more&lt;br /&gt;    'Actually, saying hello pretty much covers it.'&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;Notice how similar the second and third method definitions look to our singleton&lt;br /&gt;method definition above. That's not a coincidence: describe_greeting and&lt;br /&gt;say_more are both singleton methods of the object Greeter, an instance of the&lt;br /&gt;class Class. These methods are both held in Greeter's singleton class, the first&lt;br /&gt;place Ruby looks for methods when Greeter receives a message.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;So-called 'class methods' are really just singleton methods of&lt;br /&gt;  instances of Class.&lt;/span&gt;" do&lt;br /&gt;    assert_equal ['describe_greeting', 'say_more'].sort, Greeter.singleton_methods.sort&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;Once you digest it, this hidden consistency makes it much easier to keep track&lt;br /&gt;of what's going on in Ruby.&lt;br /&gt;&lt;br /&gt;Now, we said above that singleton classes are hidden. How do we get at them?&lt;br /&gt;Ruby gives us just one way in: the "class double-ell." Let's use this to add a&lt;br /&gt;singleton method to a Greeter.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;The 'class double-ell' gets us into the definition of an object's&lt;br /&gt;  singleton class.&lt;/span&gt;" do&lt;br /&gt;    jim, jane = Greeter.new, Greeter.new&lt;br /&gt;    class &lt;&lt; jim&lt;br /&gt;      def greet_enthusiastically&lt;br /&gt;        self.greet.upcase&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    assert_equal 'HELLO!', jim.greet_enthusiastically&lt;br /&gt;    assert_raises(NoMethodError) { jane.greet_enthusiastically }&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;This is also a third way (besides the two we saw above) to create class methods.&lt;br /&gt;It's the only one that allows Ruby's visibility modifiers to work the way&lt;br /&gt;they're normally used for instance methods (where they look like keywords even&lt;br /&gt;though they're really method calls).&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;The 'class double-ell' can be used to create non-public class methods.&lt;/span&gt;" do&lt;br /&gt;    class Greeter&lt;br /&gt;      class &lt;&lt; self&lt;br /&gt;        private&lt;br /&gt;        def secret_truth&lt;br /&gt;          'Greeting gets old fast!'&lt;br /&gt;        end&lt;br /&gt;        public&lt;br /&gt;        def truth&lt;br /&gt;          secret_truth.gsub /old fast/, 'better with every passing year'&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;    assert_raises(NoMethodError) { Greeter.secret_truth } # because it's private&lt;br /&gt;    assert_equal 'Greeting gets better with every passing year!', Greeter.truth&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;Now let's make these singleton classes easier to get to. We create an instance&lt;br /&gt;method on Object that returns the receiver's singleton class. I use the&lt;br /&gt;convention of calling this method 'metaclass,' even though it's a poor name for&lt;br /&gt;reasons already discussed.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  class ::Object &lt;br /&gt;    def metaclass&lt;br /&gt;      class &lt;&lt; self&lt;br /&gt;        self&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;The singleton class is a class, but not the same one returned by the&lt;br /&gt;  Object#class method.&lt;/span&gt;" do&lt;br /&gt;    hash = Hash.new&lt;br /&gt;    &lt;br /&gt;    assert_true hash.metaclass.is_a?(Class)&lt;br /&gt;    assert_false hash.class == hash.metaclass&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Our method returns the same object on repeated calls to the same&lt;br /&gt;  receiver.&lt;/span&gt;" do&lt;br /&gt;    hash = {}&lt;br /&gt;    &lt;br /&gt;    assert_same hash.metaclass, hash.metaclass&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Instances do not share the same singleton class instance.&lt;/span&gt;" do&lt;br /&gt;    assert_not_same({}.metaclass, {}.metaclass)&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;I'd also like to demonstrate here that an object doesn't have a singleton class&lt;br /&gt;until it's actually needed, but I can't think of a way to do that given the&lt;br /&gt;hiding discussed earlier.&lt;br /&gt;&lt;br /&gt;Get ready for a mouthful.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;The singleton class instance of a class is the superclass of the&lt;br /&gt;  singleton class instances of instances of that class.  Phew!&lt;/span&gt;" do&lt;br /&gt;    assert_same( {}.metaclass.superclass, Hash.metaclass)&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;I can't think of any reason that's useful, but there it is.  The same goes for&lt;br /&gt;singleton classes of classes (true metaclasses).&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Same diff when the instance in question is a class.&lt;/span&gt;" do&lt;br /&gt;    assert_same Hash.metaclass.superclass, Class.metaclass&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Bizarrely, same diff even when the instance in question is Class &lt;br /&gt;  itself!&lt;/span&gt;" do&lt;br /&gt;    assert_same Class.metaclass.superclass, Class.metaclass&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;Right this moment, it appears the inheritance chain of singleton classes may&lt;br /&gt;change in the next version of Ruby. See this relatively awesome distillation of&lt;br /&gt;changes in play for Ruby 1.9:&lt;br /&gt;  &lt;a href="http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9" &gt;http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Anyway, back to what we were trying to do: use Module#define_method to create a&lt;br /&gt;singleton method.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Calling define method on a singleton class creates a singleton &lt;br /&gt;  method.&lt;/span&gt;" do&lt;br /&gt;    o = Object.new&lt;br /&gt;    &lt;br /&gt;    assert_equal 0, o.singleton_methods.size&lt;br /&gt;    &lt;br /&gt;    o.metaclass.send :define_method, :countdown do&lt;br /&gt;      (@numbers ||= (1..3).to_a.reverse.push('POW!')).shift&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    assert_equal ['countdown'], o.singleton_methods&lt;br /&gt;    assert_raises(NoMethodError) { Object.new.countdown }&lt;br /&gt;    assert_equal 3, o.countdown&lt;br /&gt;    assert_equal 2, o.countdown&lt;br /&gt;    assert_equal 1, o.countdown&lt;br /&gt;    assert_equal 'POW!', o.countdown&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;I'm surprised that Matz didn't put a method on Object called&lt;br /&gt;define_singleton_method, allowing us to do the same thing we did above without&lt;br /&gt;exposing singleton classes. To me they feel like an implementation detail we&lt;br /&gt;shouldn't have needed to see.&lt;br /&gt;&lt;br /&gt;Let's create that method now.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  class ::Object&lt;br /&gt;    def define_singleton_method name, &amp;body&lt;br /&gt;      singleton_class = class &lt;&lt; self; self; end&lt;br /&gt;      singleton_class.send(:define_method, name, &amp;body)&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;This is functionally equivalent to _why's meta_def method, but that name bugs&lt;br /&gt;me a lot, so I'm not using it.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;  show "&lt;span style="font-weight:bolder"&gt;Use of our newly created Object#define_singleton_method to create a&lt;br /&gt;  singleton method without ever seeing the singleton class.&lt;/span&gt;" do&lt;br /&gt;    o = Object.new&lt;br /&gt;    o.define_singleton_method :get_excited do&lt;br /&gt;      @excitation_rant = (@excitation_rant || "I'm getting excited.").gsub(/excited/, "really excited")&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    assert_equal "I'm getting really excited.", o.get_excited&lt;br /&gt;    assert_equal "I'm getting really really excited.", o.get_excited&lt;br /&gt;    assert_equal "I'm getting really really really excited.", o.get_excited&lt;br /&gt;  end&lt;br /&gt;&lt;span style="color:#333"&gt;=begin&lt;/span&gt;&lt;br /&gt;With the ability to dynamically define methods on classes and instances at&lt;br /&gt;runtime, you have the tools needed for some pretty interesting metaprogramming.&lt;br /&gt;Have fun with it, just keep an eye on the developers around you to see if you're&lt;br /&gt;going too meta on them.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;If you have any comments, questions, suggestions, corrections, or additions for&lt;br /&gt;this write-up, please leave comments on Practical Ruby&lt;br /&gt;(http://practicalruby.blogspot.com/).&lt;br /&gt;&lt;br /&gt;Thanks to a whole bunch of people for useful feedback, particularly: Jay Fields,&lt;br /&gt;Z, Chris George, Ali Aghereza, and Omar Ghaffar.&lt;br /&gt;&lt;span style="color:#333"&gt;=end&lt;/span&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-4373064896103943322?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/4373064896103943322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=4373064896103943322' title='441 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/4373064896103943322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/4373064896103943322'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2007/02/ruby-metaprogramming-introduction.html' title='A Ruby Metaprogramming Introduction'/><author><name>John Hume</name><uri>http://www.blogger.com/profile/00164870439569642842</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://static.flickr.com/1/buddyicons/50377630@N00.jpg?1096547663'/></author><thr:total>441</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-116042112400983585</id><published>2006-10-09T12:11:00.000-07:00</published><updated>2006-10-09T12:13:10.226-07:00</updated><title type='text'>yaml | for here strings</title><content type='html'>From &lt;a href="http://yaml4r.sourceforge.net/doc/"&gt;http://yaml4r.sourceforge.net/doc/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Multi-line types&lt;br /&gt;&lt;br /&gt;Strings which span several lines can be represented in YAML as blocks. Blocks begin with either a literal '|' character or a folded '&gt;' character. The block is then dumped into a new level of indentation:&lt;br /&gt;&lt;pre&gt;- literal: |&lt;br /&gt;    A literal block keeps all&lt;br /&gt;    new lines when it is brought&lt;br /&gt;    into Ruby.&lt;br /&gt;- folded: &gt;&lt;br /&gt;    A folded block will get rid&lt;br /&gt;    of its newlines, trading them&lt;br /&gt;    for spaces when it is brought&lt;br /&gt;    into Ruby.&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-116042112400983585?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/116042112400983585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=116042112400983585' title='64 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/116042112400983585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/116042112400983585'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/10/yaml-for-here-strings_09.html' title='yaml | for here strings'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>64</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-116042081044612083</id><published>2006-10-09T12:06:00.000-07:00</published><updated>2006-10-09T12:06:53.793-07:00</updated><title type='text'>acts_as_state_machine initial state</title><content type='html'>When using acts_as_state_machine calling new does not set initial state; however, calling create does.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;gt;&amp;gt; Offer.new&lt;br /&gt;=&amp;gt; #&amp;lt;Offer:0x2554604 @new_record=true, @attributes={&amp;quot;name&amp;quot;=&amp;gt;nil, &amp;quot;updated_at&amp;quot;=&amp;gt;nil, &amp;quot;reference_name&amp;quot;=&amp;gt;nil, &amp;quot;updated_by&amp;quot;=&amp;gt;nil, &amp;quot;display_name&amp;quot;=&amp;gt;nil, &amp;quot;offer_display&amp;quot;=&amp;gt;nil, &amp;quot;state&amp;quot;=&amp;gt;nil, &amp;quot;created_at&amp;quot;=&amp;gt;nil}&amp;gt;&lt;br /&gt;&amp;gt;&amp;gt; Offer.create&lt;br /&gt;=&amp;gt; #&amp;lt;Offer:0x254c2c4 @errors=#&amp;lt;ActiveRecord::Errors:0x254b66c @errors={}, @base=#&amp;lt;Offer:0x254c2c4 ...&amp;gt;&amp;gt;, @new_record_before_save=true, @new_record=false, @attributes={&amp;quot;name&amp;quot;=&amp;gt;nil, &amp;quot;updated_at&amp;quot;=&amp;gt;Mon Oct 09 13:46:21 CDT 2006, &amp;quot;refeence_name&amp;quot;=&amp;gt;nil, &amp;quot;id&amp;quot;=&amp;gt;66, &amp;quot;updated_by&amp;quot;=&amp;gt;nil, &amp;quot;display_name&amp;quot;=&amp;gt;nil, &amp;quot;offer_display&amp;quot;=&amp;gt;nil, &amp;quot;state&amp;quot;=&amp;gt;&amp;quot;draft&amp;quot;, &amp;quot;created_at&amp;quot;=&amp;gt;Mon Oct 09 13:46:21 CDT 2006}&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;class def....&lt;pre&gt;class Offer &amp;lt; ActiveRecord::Base&lt;br /&gt;  acts_as_state_machine :initial =&amp;gt; :draft&lt;br /&gt;&lt;br /&gt;  state :draft"&lt;br /&gt;  ...&lt;br /&gt;end&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-116042081044612083?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/116042081044612083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=116042081044612083' title='82 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/116042081044612083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/116042081044612083'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/10/actsasstatemachine-initial-state.html' title='acts_as_state_machine initial state'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>82</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-115931934208767612</id><published>2006-09-26T18:08:00.000-07:00</published><updated>2006-09-26T18:09:37.706-07:00</updated><title type='text'>Invalid chars in method names, allowed?</title><content type='html'>Interesting, especially in terms of creating a DSL.&lt;pre&gt;irb(main):026:0&gt; class Strange&lt;br /&gt;irb(main):027:1&gt;   define_method :'10%, eh?' do&lt;br /&gt;irb(main):028:2*     'yep'&lt;br /&gt;irb(main):029:2&gt;   end&lt;br /&gt;irb(main):030:1&gt; end&lt;br /&gt;=&gt; #&lt;Proc:0x0003833c@(irb):27&gt;&lt;br /&gt;irb(main):031:0&gt; Strange.instance_methods.sort&lt;br /&gt;=&gt; ["10%, eh?", "==", "==="...]&lt;br /&gt;irb(main):032:0&gt; Strange.new.send :'10%, eh?'&lt;br /&gt;=&gt; "yep"&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-115931934208767612?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/115931934208767612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=115931934208767612' title='47 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115931934208767612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115931934208767612'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/09/invalid-chars-in-method-names-allowed.html' title='Invalid chars in method names, allowed?'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>47</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-115636589942022266</id><published>2006-08-23T13:44:00.000-07:00</published><updated>2006-08-25T20:34:13.036-07:00</updated><title type='text'>rename_table and postgresql sequences</title><content type='html'>rename_table in migrations will rename the table in a postgresql database; however, it does not rename the sequence.&lt;br /&gt;&lt;br /&gt;For example, assume you have a table &lt;code&gt;foo&lt;/code&gt; and a sequence &lt;code&gt;foo_id_seq&lt;/code&gt;. You can rename the table by executing:&lt;code&gt;rename_table :foo, :bar&lt;/code&gt;&lt;br /&gt;However, after changing the name of the table to &lt;code&gt;bar&lt;/code&gt; the sequence will still be &lt;code&gt;foo_id_seq&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-115636589942022266?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/115636589942022266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=115636589942022266' title='25 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115636589942022266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115636589942022266'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/08/renametable-and-postgresql-sequences.html' title='rename_table and postgresql sequences'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>25</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-115426526876377095</id><published>2006-07-30T06:12:00.000-07:00</published><updated>2006-07-30T06:14:29.550-07:00</updated><title type='text'>include Reloadable</title><content type='html'>When working with Rails you can make your non-ActiveRecord classes auto-reload if you add &lt;code&gt;include Reloadable&lt;/code&gt; to the class.  This is quite helpful when you want the behavior of your non-ActiveRecord classes to change without restarting your web server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-115426526876377095?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/115426526876377095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=115426526876377095' title='73 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115426526876377095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115426526876377095'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/07/include-reloadable.html' title='include Reloadable'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>73</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-115273764494402419</id><published>2006-07-12T13:53:00.000-07:00</published><updated>2006-07-12T13:54:05.370-07:00</updated><title type='text'>Fixture columns of Oracle LOBs type do not get loaded</title><content type='html'>Discovered in Rails version: revision 4606&lt;br /&gt;&lt;br /&gt;When you are using functional tests fixtures with Rails, if you are using Oracle 10g with oci8 adapter, and if your fixture's column type in the database is of type CLOB or BLOB, chances are your fixtures for that column will NOT get loaded.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;pre&gt;$ cat customers.yml&lt;br /&gt;simple_customer:&lt;br /&gt;  id: 1&lt;br /&gt;  some_text: A whole bunch of text.&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then your &lt;span style="font-style:italic;"&gt;customers(:simple_customer).some_text&lt;/span&gt; is &lt;span style="font-style:italic;"&gt;nil&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Workaround:&lt;br /&gt;&lt;br /&gt;In your functional test setup method, &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style:italic;"&gt;customers(:simple_customer).some_text = 'A whole bunch of text."&lt;br /&gt;customers(:simple_customer).save&lt;/span&gt;&lt;/pre&gt;before each of your test methods start using simple_customer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-115273764494402419?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/115273764494402419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=115273764494402419' title='62 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115273764494402419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115273764494402419'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/07/fixture-columns-of-oracle-lobs-type-do.html' title='Fixture columns of Oracle LOBs type do not get loaded'/><author><name>Stephen Chu</name><uri>http://www.blogger.com/profile/07181510921622947661</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>62</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-115151942474816267</id><published>2006-06-28T11:28:00.000-07:00</published><updated>2006-06-28T11:30:25.126-07:00</updated><title type='text'>Block-commenting in TextMate</title><content type='html'>Interesting article on TextMate keyboard shortcuts (including how to comment out a block of selected code)  can be found &lt;a href="http://www.garrettdimon.com/archives/trick-your-textmate-the-series"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-115151942474816267?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/115151942474816267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=115151942474816267' title='68 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115151942474816267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/115151942474816267'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/06/block-commenting-in-textmate.html' title='Block-commenting in TextMate'/><author><name>Ryan Kinderman</name><uri>http://www.blogger.com/profile/13746201487930532875</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>68</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114969650342884410</id><published>2006-06-07T09:06:00.000-07:00</published><updated>2006-06-07T09:36:51.056-07:00</updated><title type='text'>A fix for breakpointer</title><content type='html'>If you encounter this error with breakpointer:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;.../drb.rb:837:in `getaddrinfo': getaddrinfo: No address associated with nodename (SocketError)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The solution (after some searching around is simply to adjust the server URI:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;./script/breakpointer -c druby://localhost:0&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114969650342884410?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114969650342884410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114969650342884410' title='63 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114969650342884410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114969650342884410'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/06/fix-for-breakpointer.html' title='A fix for breakpointer'/><author><name>Michael Schubert</name><uri>http://www.blogger.com/profile/09423559965542413047</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>63</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114919860876939229</id><published>2006-06-01T14:47:00.000-07:00</published><updated>2006-06-01T14:50:41.343-07:00</updated><title type='text'>oberve_field inconsist with observe_form</title><content type='html'>So a funny thing was happening on the way to POSTing from an observe_field on a text area... whenever an ampersand (&amp;) was in the text, the params passed in would break... a clear sign that the value on that field was not being properly escaped.&lt;br /&gt;&lt;br /&gt;The simple solution is to change your :with =&gt; 'field' in observe_field to :with =&gt; "'field=' + escape(value)"&lt;br /&gt;&lt;br /&gt;Oddly, observe_form does not have this problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114919860876939229?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114919860876939229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114919860876939229' title='74 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114919860876939229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114919860876939229'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/06/obervefield-inconsist-with-observeform.html' title='oberve_field inconsist with observe_form'/><author><name>Michael Schubert</name><uri>http://www.blogger.com/profile/09423559965542413047</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>74</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114902161887406536</id><published>2006-05-30T13:38:00.000-07:00</published><updated>2006-05-30T13:40:18.883-07:00</updated><title type='text'>display DSL syntax</title><content type='html'>When developing a DSL system place large posters around the room with the DSL syntax samples.&lt;br /&gt;&lt;br /&gt;As features are added to the language, update the posters so the entire team is on the same page concerning the syntax.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114902161887406536?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114902161887406536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114902161887406536' title='32 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114902161887406536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114902161887406536'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/05/display-dsl-syntax.html' title='display DSL syntax'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>32</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114858331707641082</id><published>2006-05-25T11:37:00.000-07:00</published><updated>2006-05-25T11:55:35.470-07:00</updated><title type='text'>leading zero</title><content type='html'>A leading zero on an integer is an octal.  IRB returns a relevant error for 09 "Illegal octal digit" but 019 returns a less relevant message "unexpected tINTEGER"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114858331707641082?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114858331707641082/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114858331707641082' title='33 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114858331707641082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114858331707641082'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/05/leading-zero.html' title='leading zero'/><author><name>Ron Campbell</name><uri>http://www.blogger.com/profile/17626556404882102091</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>33</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114858023812870399</id><published>2006-05-25T10:59:00.000-07:00</published><updated>2006-05-25T11:03:58.170-07:00</updated><title type='text'>ReceiveAny</title><content type='html'>I recently needed an object that would handle any method call and support method chaining such as:&lt;pre&gt;f = RevieveAny.this.is.random.text&lt;/pre&gt;The solution was fairly simple:&lt;pre&gt;class ReceiveAny&lt;br /&gt;  instance_methods.each { |m| undef_method m unless m =~ /^__/ }&lt;br /&gt;&lt;br /&gt;  def method_missing(sym, *args)&lt;br /&gt;    self&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;require File.expand_path(File.dirname(__FILE__) + "/../test_helper")&lt;br /&gt;&lt;br /&gt;class ReceiveAnyTest &lt; Test::Unit::TestCase&lt;br /&gt;  def test_any_method_call_returns_self&lt;br /&gt;    r = ReceiveAny.new&lt;br /&gt;    assert_equal r, r.any_method_call&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def test_any_method_can_be_chained&lt;br /&gt;    r = ReceiveAny.new&lt;br /&gt;    assert_equal r, r.any_method_call.can.be.executed.in.a.chain&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;instance_methods undef logic borrowed from &lt;a href="http://onestepback.org/index.cgi/Tech/Ruby/BlankSlate.rdoc"&gt;BlankSlate&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114858023812870399?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114858023812870399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114858023812870399' title='26 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114858023812870399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114858023812870399'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/05/receiveany.html' title='ReceiveAny'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>26</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114857462297045571</id><published>2006-05-25T09:28:00.000-07:00</published><updated>2006-05-25T09:30:57.493-07:00</updated><title type='text'>Trace Log</title><content type='html'>You'll find this little guy tucked away somewhere in PickAxe but I use it when I really need more clues to a weird show-stopping bug:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;   set_trace_func proc {|*x| p [x[1],x[2],x[3].to_s] if (x[0]=="call" and !x[1].include?("/ruby/1.8/irb"))}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Just be prepared for a flood of trace messages.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114857462297045571?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114857462297045571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114857462297045571' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114857462297045571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114857462297045571'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/05/trace-log.html' title='Trace Log'/><author><name>Michael Schubert</name><uri>http://www.blogger.com/profile/09423559965542413047</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114857407334777632</id><published>2006-05-25T09:13:00.001-07:00</published><updated>2006-05-25T09:24:04.010-07:00</updated><title type='text'>call sort with a block</title><content type='html'>I needed to sort a list of partners today so I added:&lt;pre&gt;class Partner&lt;br /&gt;  def &lt;=&gt;(other)&lt;br /&gt;     self.name &lt;=&gt; other.name&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;However, I could have just done:&lt;pre&gt;Partner.find(:all).sort { |one, other| one.name &lt;=&gt; other.name }&lt;/pre&gt;Doc for sort &lt;a href="http://ruby-doc.org/core/classes/Array.html#M000424"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114857407334777632?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114857407334777632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114857407334777632' title='34 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114857407334777632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114857407334777632'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/05/call-sort-with-block.html' title='call sort with a block'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>34</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114857377816753158</id><published>2006-05-25T09:13:00.000-07:00</published><updated>2006-05-25T09:16:18.166-07:00</updated><title type='text'>Restart your terminal/command window after you install a new gem</title><content type='html'>At least on windows, after installing a new gem, you have to restart your cmd window. Otherwise your gem cannot be used in irb or script/console.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114857377816753158?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114857377816753158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114857377816753158' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114857377816753158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114857377816753158'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/05/restart-your-terminalcommand-window.html' title='Restart your terminal/command window after you install a new gem'/><author><name>Stephen Chu</name><uri>http://www.blogger.com/profile/07181510921622947661</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-28670731.post-114848519181175628</id><published>2006-05-24T08:27:00.000-07:00</published><updated>2006-05-24T09:06:27.863-07:00</updated><title type='text'>DSL word gotchas</title><content type='html'>When developing a DSL, certain keywords can leave you with strange error messages.  For example, &lt;code&gt;open&lt;/code&gt; doesn't invoke method_missing, but fails with the message: &lt;code&gt;ArgumentError: wrong number of arguments (0 for 1)&lt;/code&gt;.  &lt;code&gt;open&lt;/code&gt; is not a ruby keyword; however, if you open an irb session and simply type &lt;code&gt;open&lt;/code&gt; it will fail with the above message.  It appears as though &lt;code&gt;open&lt;/code&gt; delegates to IO.open.&lt;br /&gt;&lt;br /&gt;The important thing to note is that a bizarre error when executing a DSL can be the result of a method being defined in an unexpected way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/28670731-114848519181175628?l=practicalruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://practicalruby.blogspot.com/feeds/114848519181175628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=28670731&amp;postID=114848519181175628' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114848519181175628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/28670731/posts/default/114848519181175628'/><link rel='alternate' type='text/html' href='http://practicalruby.blogspot.com/2006/05/dsl-word-gotchas.html' title='DSL word gotchas'/><author><name>Jay Fields</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>21</thr:total></entry></feed>
