<?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:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7638404154269297868</id><updated>2010-05-22T18:43:29.713-05:00</updated><title type='text'>collect {thoughts}</title><subtitle type='html'>programming, ruby, technology</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.drewolson.org/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default?orderby=updated'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-6497082030803408516</id><published>2009-11-14T17:40:00.009-06:00</published><updated>2009-11-14T17:58:50.882-06:00</updated><title type='text'>Make your cucumber steps definitions time aware</title><content type='html'>If you're like me, you've found yourself with a cucumber step definition like this:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/234862.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;And you want to write a step definition like this:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/234863.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Instead of doing all that extra work, I threw together a cucumber step that lets you add times to any existing step definition:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/233978.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;To make things even easier I created a gem called &lt;a href="http://github.com/drewolson/timebomb"&gt;Timebomb&lt;/a&gt;. It lets you append time constraints to your cucumber step defintions by mixing and matching:&lt;br /&gt;&lt;br /&gt;  - seconds, minutes, hours, days, weeks, months, years&lt;br /&gt;  - ago, from now&lt;br /&gt;&lt;br /&gt;So with the following step definition:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/234862.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I can write any of the following:&lt;br /&gt;&lt;br /&gt;  - Given I received an invitation 1 day from now&lt;br /&gt;  - Given I received an invitation 2 weeks ago&lt;br /&gt;  - Given I received an invitation 3 months from now&lt;br /&gt;  - Given I received an invitation 15 years ago&lt;br /&gt;&lt;br /&gt;Timebomb to the rescue, BOOM!&lt;br /&gt;&lt;br /&gt;== Installing ==&lt;br /&gt;&lt;br /&gt;First install Timebomb&lt;br /&gt;&lt;br /&gt;  - sudo gem install timebomb --source http://gemcutter.org&lt;br /&gt;&lt;br /&gt;Now, just require it in your cucumber env.rb file. BOOM goes the dynamite.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-6497082030803408516?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/6497082030803408516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=6497082030803408516' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/6497082030803408516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/6497082030803408516'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2009/11/make-your-cucumber-steps-definitions.html' title='Make your cucumber steps definitions time aware'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-4992748031653929056</id><published>2009-07-07T10:36:00.016-05:00</published><updated>2009-07-07T10:59:08.973-05:00</updated><title type='text'>Vim Plugin for Ruby Testing</title><content type='html'>If you're using ruby and you're using vim, you've probably noticed some awesome tools out there (mostly created by Tim Pope). You've got rails.vim, ruby.vim, etc. However, I noticed that there was a lack of support for some features that Textmate users have been taking for granted for a long time. I'm talking about the support Textmate provides around running your tests.&lt;br /&gt;&lt;br /&gt;The key features I was missing from Textmate were having text output in a new buffer, the ability to run a focused test (the test my cursor was currently on) and the ability to run all tests in a given context. With the help of some ThoughtWorks colleagues on a previous project, I've put together a vim plugin that I think meets these needs.&lt;br /&gt;&lt;br /&gt;The plugin is &lt;a href="http://github.com/drewolson/ruby_focused_unit_test_vim/"&gt;ruby_focused_unit_test_vim&lt;/a&gt;. The plugin currently supports the following ruby testing tools:&lt;br /&gt;&lt;br /&gt;- test/unit&lt;br /&gt;- rspec&lt;br /&gt;- shoulda&lt;br /&gt;- dust&lt;br /&gt;&lt;br /&gt;The current features the plugin supports are:&lt;br /&gt;&lt;br /&gt;- run focused test&lt;br /&gt;- run focused context&lt;br /&gt;- run entire test file&lt;br /&gt;- all commands stream output to a new buffer&lt;br /&gt;&lt;br /&gt;The streaming feature is very cool (thanks to &lt;a href="http://github.com/qxjit"&gt;David Vollbracht&lt;/a&gt;). It gives you instant feedback as your tests pass/fail in a new buffer. It feels very similar to the test output in Textmate.&lt;br /&gt;&lt;br /&gt;The installation process is simple. Just clone the git repo and copy the ruby_focused_unit_test.vim file into your .vim/plugin directory.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/142173.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Once you've installed the plugin, three commands become available to you:&lt;br /&gt;&lt;br /&gt;- RunRubyFocusedUnitTest&lt;br /&gt;- RunRubyFocusedContext&lt;br /&gt;- RunAllRubyTests&lt;br /&gt;&lt;br /&gt;To make things simple, I map these commands in my .vimrc:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/142175.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I hope you find the plugin useful. In the future I'll write about my overall vim setup for ruby/rails development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-4992748031653929056?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/4992748031653929056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=4992748031653929056' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/4992748031653929056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/4992748031653929056'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2009/07/vim-plugin-for-ruby-testing.html' title='Vim Plugin for Ruby Testing'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-1458707335781553930</id><published>2008-12-29T15:55:00.012-06:00</published><updated>2009-01-09T13:26:11.908-06:00</updated><title type='text'>Sinatra Dances on Passenger's Stage</title><content type='html'>I wrote briefly in my last post about how I've been working with &lt;a href="http://github.com/bmizerany/sinatra/tree/master"&gt;sinatra&lt;/a&gt; quite a bit lately. After some great experiences at work, I decided to move my &lt;a href="http://drewolson.org"&gt;homepage&lt;/a&gt; over to sinatra from rails. It was totally inane to have the site written in rails in the first place, but I'd been learning the framework at the time and when you have a hammer...well, you know.&lt;br /&gt;&lt;br /&gt;Anyway, I learned quite a bit about deploying a sinatra app on &lt;a href="http://www.modrails.com/"&gt;passenger&lt;/a&gt; as well as using passenger for development of sinatra apps and I figured I'd talk a bit about that. One great thing about passenger is its ability to serve any rack application. Rack is a tiny little framework that acts as a sort of standard for dealing with http requests and sinatra supports rack. This means deploying a sinatra app on passenger is pretty simple, but I had to poke around a bit to get the wheels running smoothly. Let's first look at my application layout.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/44123.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;We'll look at each of these files a bit closer. First and foremost, we've got the drewolson.rb file. This is my sinatra app, which we won't go into now, but remember that your sinatra app should sit at the root of your directory structure. You can also see that I have 3 subdirectories. The first is public, where you throw any static files (like images, stylesheets or favicons). The next is the views directory, which is pretty self-explanatory. Throw your view files in here.&lt;br /&gt;&lt;br /&gt;Last but not least is the test subdirectory. This is where the tests for my sinatra app reside. Sinatra actually provides you with some pretty nice testing tools, and I'll just show you my test_helper.rb which all my tests require.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/44132.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Ok, now onto the deployment fun stuff. There are two files that are key to deploying sinatra apps on passenger: config.ru and Capfile. Capfile is my capistrano deployment script and config.ru is my rackup file. Let's look at config.ru first.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/44134.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I tried several variants of this file, but this is the only one that works for me. Notice that you have to explicitly state where you app_file is located as well as where your views directory sits.&lt;br /&gt;&lt;br /&gt;Next up, let's look at my Capfile.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/44135.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Again, this is super simple when compared to a standard rails Capfile. Notice that we overwrite deploy:restart. All we have to do with passenger is touch a file. Note that this also assumes you have ssh access to your server and that you're using git as your version control system. &lt;br /&gt;&lt;br /&gt;The last piece of the puzzle is setting up a virtual host for apache. Now, you've probably already done this before but just to be complete I'll show you my virtual host for this application.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/44137.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Yes, that's it. Seriously. Assuming you've enabled the site in apache, all you have to do on your first deploy is run:&lt;br /&gt;&lt;br /&gt;cap deploy:setup&lt;br /&gt;cap deploy&lt;br /&gt;&lt;br /&gt;Bam, you're up and running with a sinatra app on passenger. But that's not all. One thing that I struggled with when getting this all working was constantly deploying, checking the app, fixing the config.ru, deploying, checking the app ... All this could have been avoided if I'd simply been developing on passenger locally and using it to run my rack based sinatra app locally before deploying. Well it turns out this is super simple. You can use the awesome &lt;a href="http://www.fngtps.com/2008/09/passenger-preference-pane-v1-1"&gt;passenger prefpane&lt;/a&gt; if you're on OS X. Simply install it, point it at your directory, and you now have a local copy of your sinatra app running on passenger + rack. How sweet is that?&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;&lt;br /&gt;It seems that newer versions of sinatra and rack break these instructions. They are verified working for rack 0.4.0 and sinatra 0.3.2. Updated code snippets to reflect this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-1458707335781553930?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/1458707335781553930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=1458707335781553930' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1458707335781553930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1458707335781553930'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/12/sinatra-dances-on-passengers-stage.html' title='Sinatra Dances on Passenger&apos;s Stage'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-1010272255974714323</id><published>2008-12-23T13:23:00.005-06:00</published><updated>2008-12-23T13:48:22.149-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby rss sinatra'/><title type='text'>Mashup your RSS Feeds with ruby + sinatra + pipe</title><content type='html'>I've been doing some build work lately and I stumbled upon a situation last week where I needed to take a bunch of RSS feeds, aggregate them and filter only the specific items I wanted. This actually manifested itself with continuous integration boxes. We have a lot of CI boxes running a lot of builds but each team is only interested in several of these builds. &lt;br /&gt;&lt;br /&gt;One option is using something like CCMenu, but I actually needed a consumable RSS feed for use by another service that displayed build status is a very big, readable way (for a monitor in the team area). This aggregation and filtering of RSS feeds is, in fact, exactly what &lt;a href="http://pipes.yahoo.com/pipes/"&gt;Yahoo Pipes&lt;/a&gt; does. However, these are all internal feeds, so Yahoo Pipes wouldn't work for me here.&lt;br /&gt;&lt;br /&gt;Lately, I have been toying with &lt;a href="http://github.com/bmizerany/sinatra/tree/master"&gt;sinatra&lt;/a&gt;, a great little web framework in ruby. I decided to write a tool that could be used in conjunction with sinatra to get me my RSS feed aggregation and filtering. That tool is called (not surprisingly) &lt;a href="http://github.com/drewolson/pipe/tree/master"&gt;pipe&lt;/a&gt;. Below is the code for creating a simple feed containing all the ruby related articles on ycombinator and the clojure related articles on the programming subreddit:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/39432.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;You can install pipes like so:&lt;br /&gt;- gem sources -a http://gems.github.com&lt;br /&gt;- sudo gem install drewolson-pipe&lt;br /&gt;&lt;br /&gt;The documentation is &lt;a href="http://drewolson.github.com/pipe"&gt;here&lt;/a&gt;. Enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-1010272255974714323?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/1010272255974714323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=1010272255974714323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1010272255974714323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1010272255974714323'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/12/mashup-your-rss-feeds-with-ruby-sinatra.html' title='Mashup your RSS Feeds with ruby + sinatra + pipe'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-4484757395695623784</id><published>2008-05-13T22:52:00.023-05:00</published><updated>2008-12-03T20:01:02.341-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='DSL'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Micro DSLs</title><content type='html'>Three things you need to know about me: I spend a lot of time on planes, I like DSLs and I'm lazy. With these powers combined, I've created my new hobby: creating micro DSLs. What is a micro DSL? Basically, during my (seemingly) never ending flights from San Fran to Chicago I try to recreate DSLs I like in as few lines as possible. Oh, and one more thing: I give the resulting DSLs self-degrading names to show the respect to the people who first created them.&lt;br /&gt;&lt;br /&gt;A couple more rules: I decide how much of the original DSL I want to recreate and I can cut any corners that I'd like. In some cases, I try to improve the original DSL or tweak the syntax a bit.&lt;br /&gt;&lt;br /&gt;The first DSL I've micro-ized is Jay Fields &lt;a href="http://blog.jayfields.com/2007/12/ruby-expectation-gem.html"&gt;expectations&lt;/a&gt;. I find its syntax very nice and it had some unique challenges. The general approach I took to keep the code short was to use test/unit behind the scenes. This stopped me from having to recreate all the goodness that test/unit gives me for free: a test suite runner, error/failure tracking and assertions.&lt;br /&gt;&lt;br /&gt;Anyway, the code is below. It's about 48 lines long and implements most of the features from the original DSL.&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;&lt;span class="meta meta_require meta_require_ruby"&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;require&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;test/unit&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&gt;&lt;br /&gt;&lt;span class="meta meta_require meta_require_ruby"&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;require&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;rubygems&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&gt;&lt;br /&gt;&lt;span class="meta meta_require meta_require_ruby"&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;require&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;mocha&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&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="meta meta_class meta_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby"&gt;Mocha::Expectation&lt;/span&gt;&lt;/span&gt;&lt;br /&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;and&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;mock&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby"&gt;alias_method&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;go&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&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;and&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="meta meta_class meta_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby"&gt;LoweredExpectations&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;include&lt;/span&gt; &lt;span class="support support_class support_class_ruby"&gt;Mocha&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby"&gt;::&lt;/span&gt;&lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Standalone&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;COMPARATORS&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby"&gt;{&lt;/span&gt;&lt;span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Class&lt;/span&gt; &lt;span class="punctuation punctuation_separator punctuation_separator_key-value"&gt;=&amp;gt;&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;kind_of?&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Range&lt;/span&gt; &lt;span class="punctuation punctuation_separator punctuation_separator_key-value"&gt;=&amp;gt;&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;include?&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Regexp&lt;/span&gt; &lt;span class="punctuation punctuation_separator punctuation_separator_key-value"&gt;=&amp;gt;&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;=~&lt;/span&gt;&lt;br /&gt;  &lt;span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby"&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;br /&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;initialize&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;test_case&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="support support_class support_class_ruby"&gt;Class&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/span&gt;&lt;span class="support support_class support_class_ruby"&gt;Test&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby"&gt;::&lt;/span&gt;&lt;span class="support support_class support_class_ruby"&gt;Unit&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby"&gt;::&lt;/span&gt;&lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;TestCase&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;test_num&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;0&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&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;expect&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;value&lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt;&lt;span class="constant constant_language constant_language_ruby"&gt;true&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;&amp;amp;&lt;/span&gt;block&lt;/span&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    test_name &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_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;test_&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;&lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;test_num&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"&gt;+=&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;1&lt;/span&gt;&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;br /&gt;    &lt;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;if&lt;/span&gt; value&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;kind_of? &lt;span class="support support_class support_class_ruby"&gt;Mocha&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby"&gt;::&lt;/span&gt;&lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Mock&lt;/span&gt;&lt;br /&gt;      &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;test_case&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;send&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;define_method&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;test_name&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;        block&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;call&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/span&gt;value&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt;&lt;br /&gt;        value&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="support support_function support_function_actionpack support_function_actionpack_rails"&gt;verify&lt;/span&gt;&lt;br /&gt;      &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;else&lt;/span&gt;&lt;br /&gt;      comparator &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="support support_class support_class_ruby"&gt;COMPARATORS&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;[&lt;/span&gt;value&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;class&lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;]&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby"&gt;||&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;==&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;      &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;test_case&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;send&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;define_method&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;test_name&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;        assert&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/span&gt;block&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;call&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;send&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/span&gt;comparator&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;value&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;))&lt;/span&gt;&lt;br /&gt;      &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&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;LoweredExpectations&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;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;&amp;amp;&lt;/span&gt;block&lt;/span&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="support support_class support_class_ruby"&gt;LoweredExpectations&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;instance_eval&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_arithmetic keyword_operator_arithmetic_ruby"&gt;&amp;amp;&lt;/span&gt;block&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Below is an expectations file using the above code. Note there's a small different in the way mocks are used. The method &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; links expectations and &lt;span style="font-style: italic;"&gt;go&lt;/span&gt; is used to send the mock to the block.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;&lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;LoweredExpectations&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;  expect &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;    &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;1&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;1&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  expect &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;2&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;    &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;1&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;+&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;1&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  expect &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;foo&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="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&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;fo&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="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_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;o&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;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  expect &lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;/&lt;/span&gt;bar\d&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;/&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&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;bar2&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;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  expect &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Fixnum&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&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;4&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_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;to_i&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  expect mock&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;expects&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;bar&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_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby"&gt;and&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;expects&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;baz&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_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;go &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;foo&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;    foo&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;bar&lt;br /&gt;    foo&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;baz&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Of course, the error reporting is much worse in my version than Jay's, but I'd say not too bad for ~50 lines of code. Let me know what you think.&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;&lt;br /&gt;Source is available on &lt;a href="http://github.com/drewolson/lowered_expectations/tree/master"&gt;github&lt;/a&gt;. You can see my other projects on the right side of this blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-4484757395695623784?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/4484757395695623784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=4484757395695623784' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/4484757395695623784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/4484757395695623784'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/05/micro-dsls-part-1.html' title='Micro DSLs'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-1371153138896173750</id><published>2008-09-08T14:18:00.006-05:00</published><updated>2008-12-03T19:59:36.304-06:00</updated><title type='text'>Diggr released</title><content type='html'>I finally got around to a small side project I have wanted to work on: a new ruby wrapper for the Digg API. There's one existing library out there that I know of, but I didn't like the syntax all that much. So, like any good developer, I've reinvented the wheel! My library is called diggr and it strives to be simple and consistent with the Digg API endpoints listed &lt;a href="http://apidoc.digg.com/CompleteList"&gt;here&lt;/a&gt;. Rather than boring you with a detailed description, I'll just show some code snippets below. For more information on diggr check out:&lt;br /&gt;&lt;br /&gt;- &lt;a href="http://diggr.rubyforge.org"&gt;Docs&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://github.com/drewolson/diggr/tree/master"&gt;Source&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here are a few simple examples:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby"&gt;&lt;span class="meta meta_require meta_require_ruby"&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;require&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;rubygems&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&gt;&lt;br /&gt;&lt;span class="meta meta_require meta_require_ruby"&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;require&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;diggr&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&gt;&lt;br /&gt;&lt;br /&gt;diggr &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="support support_class support_class_ruby"&gt;Diggr&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby"&gt;::&lt;/span&gt;&lt;span class="support support_class support_class_ruby"&gt;API&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; retrieve a single user by user name and print the number of profile views&lt;br /&gt;&lt;/span&gt;user &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; diggr&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;user&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;johndoe&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_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;fetch&lt;br /&gt;puts user&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;profileviews&lt;br /&gt;&lt;br /&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; iterator over the most recent 10 stories (default return size) and print their titles&lt;br /&gt;&lt;/span&gt;diggr&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;stories&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;each &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;story&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;  puts story&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;title&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; print the title of the 3 most recent hot stories&lt;br /&gt;&lt;/span&gt;diggr&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;stories&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;hot&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;options&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;count&lt;/span&gt; &lt;span class="punctuation punctuation_separator punctuation_separator_key-value"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;3&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_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;each &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;story&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;  puts story&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;title&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; build an array of stories whos title contains "foo"&lt;br /&gt;&lt;/span&gt;diggr&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;stories&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;inject&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_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;array&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;,&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;story&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;  array &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"&gt;&amp;lt;&amp;lt;&lt;/span&gt; story &lt;span class="keyword keyword_control keyword_control_ruby"&gt;if&lt;/span&gt; story&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;title &lt;span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_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;foo&lt;span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  array&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; print the title of the 2nd and 3rd most recent stories&lt;br /&gt;&lt;/span&gt;diggr&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;stories&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;options&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;count&lt;/span&gt; &lt;span class="punctuation punctuation_separator punctuation_separator_key-value"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;2&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&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;offset&lt;/span&gt; &lt;span class="punctuation punctuation_separator punctuation_separator_key-value"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;2&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_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;each &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;story&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;  puts story&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;title&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-1371153138896173750?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/1371153138896173750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=1371153138896173750' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1371153138896173750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1371153138896173750'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/09/diggr-released.html' title='Diggr released'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-1823704853211124735</id><published>2008-06-11T22:28:00.016-05:00</published><updated>2008-12-03T19:58:35.987-06:00</updated><title type='text'>Ruby and Macros: An Experiment</title><content type='html'>Lately I've been doing a lot of reading about Lisp. This got me thinking about how I could implement something similar to Lisp macros in ruby. DISCLAIMER: I am not a Lisp guru. I'm sure I'm missing the finer points of Lisp macros. I'm sure I'm an idiot.&lt;br /&gt;&lt;br /&gt;That said, what I wanted to come up with was a way to define methods such that you received both the arguments to the method and the block given to the method completely unevaluated. That is, you'll be given an array of strings representing the arguments and one large string representing the block passed to the marco. You are then be free to do whatever you'd like with the arguments and the body. This, to me, captures at least the essence of macros (yes, I'm probably wrong). To do so, I've whipped up a gem called def_macro.&lt;br /&gt;&lt;br /&gt;Below I'll show you some samples using the gem to define two classic Lisp macros: with and loop. The with macro basically gives a block access to some local variables while executing. The loop macro just loops over some code n times (the loop macro I'm describing here is WAY simplified from the true Lisp loop macro). Anyway, I'll show the examples in two stages: defining the macro using def_macro and using the defined macro.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;&lt;span class="meta meta_require meta_require_ruby"&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;require&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;rubygems&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&gt;&lt;br /&gt;&lt;span class="meta meta_require meta_require_ruby"&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;require&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;def_macro&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&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;&lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;The&lt;/span&gt; with macro&lt;span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;def_macro &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;with&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;args&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;,&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;body&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;  eval args&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;first&lt;br /&gt;  eval body&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;with proc &lt;span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby"&gt;{&lt;/span&gt;&lt;span class="meta meta_syntax meta_syntax_ruby meta_syntax_ruby_start-block"&gt; &lt;/span&gt;a &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;1&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_statement punctuation_separator_statement_ruby"&gt;;&lt;/span&gt; b &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;2&lt;/span&gt; &lt;span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby"&gt;}&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;  puts a &lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;+&lt;/span&gt; b&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;                             &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; =&amp;gt; 3&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Notice in this case I'm only evaluating the first argument (there's only one). By doing so, I've set my local variables. I'm then free to evaluate the body string. Everything works as expected and we see 3 printed out. Notice that if I'm passing code as arguments, they must be inside of a proc or lambda. Ruby forces us to do this if we don't want the code evaluated immediately.&lt;br /&gt;&lt;br /&gt;The simplified loop macro is even easier to implement. Take a look:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;&lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;The&lt;/span&gt; &lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;loop&lt;/span&gt; macro&lt;span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;def_macro &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;loop&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;args&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;,&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;body&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;  &lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&lt;/span&gt;eval args&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;first&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;times &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;    eval body&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;loop&lt;/span&gt; &lt;span class="constant constant_numeric constant_numeric_ruby"&gt;2&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;  puts &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;hi&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;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;                 &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; =&amp;gt; "hi" "hi"&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Notice this time that it's not necessary to wrap the argument in a proc as it doesn't matter when the number 2 is evaluated.&lt;br /&gt;&lt;br /&gt;You can download the gem in two ways:&lt;br /&gt;- rubyforge: sudo gem install defmacro&lt;br /&gt;- github: sudo gem install drewolson-defmacro --source=http://gems.github.com&lt;br /&gt;&lt;br /&gt;The source is on github at http://github.com/drewolson/def_macro/tree/master&lt;br /&gt;&lt;br /&gt;Update: Fixed spelling of macro (thanks to Nwallins on reddit)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-1823704853211124735?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/1823704853211124735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=1823704853211124735' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1823704853211124735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1823704853211124735'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/06/ruby-and-macros-experiment.html' title='Ruby and Macros: An Experiment'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-5672017290942325320</id><published>2008-05-29T18:59:00.018-05:00</published><updated>2008-05-30T15:52:39.505-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Remote Git Repos on Ubuntu: The Right Way</title><content type='html'>&lt;h3&gt;Overview&lt;/h3&gt;&lt;br /&gt;&lt;div&gt;Over the past week or so I've been setting up remote git repositories on my &lt;a href="http://slicehost.com"&gt;slice&lt;/a&gt;. I figured it would be helpful to put together a post regarding what I've found to be the right way to set up remote git repos. The info in this post is basically collected from several blogs and articles, but I've yet to see all of it in a single post.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Before we get started, I'm going to make a couple of assumptions:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;You're running ubuntu&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;You have ssh access to your box&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;You have access to a user on the sudoer list&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;You have git installed on your server and your client machine&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;You've generated a public/private key and it's in the standard location&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;/div&gt;&lt;br /&gt;Ok, enough with the chitchat, let's just get started.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Adding the git user&lt;/h3&gt;&lt;br /&gt;1. Create a git user on your server&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="text text_plain"&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;On your server:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;sudo adduser git&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;2. Create your .ssh folder and authorized_keys file for the git user&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="text text_plain"&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;On your server:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;su git                          # switch to the git user&lt;br /&gt;cd ~                            # change to git's home dir&lt;br /&gt;mkdir .ssh                      # make the .ssh dir&lt;br /&gt;touch .ssh/authorized_keys      # create an empty authorized_keys file&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;3. Next, we need to copy the public key from our client system and add it to the authorized_keys for the git user on the server.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="text text_plain"&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;On your client:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;ssh copy-id git@yourserver.com&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;4. Because we're going to be giving anyone access to the git user who needs access to the git repos, we want to restrict the actions the git user can take. To do so, we'll set the git users shell to git-shell. First, log back into your server on a user with sudo access (not the git user) and do the following:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="text text_plain"&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;On your server:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;which git-shell             # remember this location for the next step. mine is /usr/bin/git-shell&lt;br /&gt;sudo vim /etc/passwd        # find the line related to the git user, change the section that says&lt;br /&gt;&lt;/span&gt;                            &lt;span class="meta meta_paragraph meta_paragraph_text"&gt;# /bin/sh to /usr/bin/git-shell (or whatever you got from the first step)&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Creating a new git repo&lt;/h3&gt;&lt;br /&gt;So we've created our git user and now we'd like to create a new repository that we can use from the clients. It's actually really simple. We basically create a folder on the server in our git user's home directory named whatever we'd like the repo to be named and them we initialize it as a bare git repo. One thing to keep in is that all these commands will be performed from a user that has sudo access and is NOT the git user. Because we've set the git user's shell to git-shell, we can no longer switch to that user or ssh in as them.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="text text_plain"&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;On your server:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;sudo mkdir /home/git/foo                # create foo directory&lt;br /&gt;cd /home/git/foo                        # change to that directory&lt;br /&gt;sudo git --bare init                    # initialize a bare git repo&lt;br /&gt;sudo chown -R git:git /home/git/foo     # make the git user the owner of the repo&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;First Commit to the Repo&lt;/h3&gt;&lt;br /&gt;After initializing the repo, we're going to do a first commit from our client machine. The first commit is slightly complicated, but after you'll be all set to go.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="text text_plain"&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;On our client:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;mkdir foo                                           # make a new folder&lt;br /&gt;cd foo&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;git init                                            # initialize the git repo and add a file&lt;br /&gt;touch README&lt;br /&gt;git add .&lt;br /&gt;git commit -m "added README"&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;git remote add origin git@yourserver.com:foo        # add the remote git repo&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;git push origin master                              # push your commit to it&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Cloning your Repo&lt;/h3&gt;&lt;br /&gt;Our repo is now all set to clone! On our client, we could futz around with the .git/config to make our master branch track the origin, but if we clone the repo it does it for us! So, we'll just delete the directory we've just created and reclone the repo. That way, we don't have to remember how to set up the .git/config file (and I'm lazy).&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="text text_plain"&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;On our client:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="meta meta_paragraph meta_paragraph_text"&gt;rm -r foo/&lt;br /&gt;git clone git@yourserver.com:foo&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;And that's really all there is to it. If you'd like to give someone else access to your git repo, simply add their public key to authorized_keys. Keep in mind that with this setup, all users will have access to all git repos you create in the git user's home directory. I'll talk more about giving different access in a later post. Hope this helps you all getting git remote repos up for all your projects.&lt;br /&gt;&lt;br /&gt;Update: Now uses ssh copy-id to copy public key to the remote server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-5672017290942325320?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/5672017290942325320/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=5672017290942325320' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/5672017290942325320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/5672017290942325320'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/05/remote-git-repos-on-ubuntu-right-way.html' title='Remote Git Repos on Ubuntu: The Right Way'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-1707714869305845082</id><published>2008-05-22T19:59:00.004-05:00</published><updated>2008-05-22T20:56:12.700-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='DSL'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Don't Cry Over Spilled Context</title><content type='html'>Let's talk a bit about a DSL pattern called spill-over context. In keeping with the whole "picture worth a thousand words" thing, let's take a look at a snippet of code from a rakefile to get an idea of what spill-over context actually is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;desc &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;I describe the task below me!&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;br /&gt;task &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;stuff&lt;/span&gt;&lt;br /&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;  &lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; do stuff here&lt;br /&gt;&lt;/span&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; &lt;br /&gt;What's cool about the code above is that the &lt;span style="font-style:italic;"&gt;desc&lt;/span&gt; method seems to magically know how to attach itself to the next task defined. When I run "rake -T", I will see the description associated with my :stuff task. Very slick.&lt;br /&gt;&lt;br /&gt;Like most things involved in DSLs, this seems magical at first. How the heck would the description know to attach itself to the next task? It's cool and very easy to see the intent of the code, but how the heck does it work? In truth, implementing the spill-over context pattern is pretty darn simple. Let's look at an example DSL I created:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;make_a_sandwich &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="support support_class support_class_ruby"&gt;Task&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&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;make a sandwich&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="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;  description &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;open up the fridge&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;br /&gt;  step &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;open_fridge&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;    &lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; do fridge opening stuff&lt;br /&gt;&lt;/span&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  description &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;get some bread&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;br /&gt;  step &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;get_bread&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;    &lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; bread stuff here&lt;br /&gt;&lt;/span&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  description &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;get peanut butter and jelly&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;br /&gt;  step &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;ingredients&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do&lt;br /&gt;&lt;/span&gt;&lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;    &lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; get the good stuff&lt;br /&gt;&lt;/span&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;make_a_sandwich&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;show_task&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This DSL (which looks strikingly similiar to rake) lets us create tasks out of steps. We can describe each of the steps in plain english and then use the &lt;span style="font-style:italic;"&gt;show_task&lt;/span&gt; method to print out a nice explanation of our task. &lt;br /&gt;&lt;br /&gt;The code to implement this DSL is pretty easy to understand. At a high level, here's what happens. I've defined two instance methods on Task called &lt;span style="font-style:italic;"&gt;describe&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;step&lt;/span&gt;. The &lt;span style="font-style:italic;"&gt;describe&lt;/span&gt; method stores whatever sting is passed to it in an instance variable called @last_description. The &lt;span style="font-style:italic;"&gt;step&lt;/span&gt; method does two things. First, it stores the block passed to it in a hash along with the step name as a key. Second, and most importantly, it checks to see if there is a description sitting in the instance variable @last_description. If so, it associates that description with the step it is creating, and then clears out the instance variable. That's all there is to spill-over context! The "magic" of the description attaching to a step is accomplished by storing the description in an instance variable and using it later. Very simple, but also a very powerful concept for creating interesting and usable DSLs.&lt;br /&gt;&lt;br /&gt;Finally, the &lt;span style="font-style:italic;"&gt;show_task&lt;/span&gt; method just iterates over the tasks and descriptions and prints them out nicely. So, without further ado, here's the implementation code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;&lt;span class="meta meta_class meta_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby"&gt;Task&lt;/span&gt;&lt;/span&gt;&lt;br /&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;initialize&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;name&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;&amp;amp;&lt;/span&gt;block&lt;/span&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;name&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; name&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;steps&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby"&gt;{}&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;descriptions&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;[]&lt;/span&gt;&lt;br /&gt;    instance_eval&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_arithmetic keyword_operator_arithmetic_ruby"&gt;&amp;amp;&lt;/span&gt;block&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_ruby"&gt;if&lt;/span&gt; &lt;span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby"&gt;block_given?&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&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;show_task&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    puts &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;Task: &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;&lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;name&lt;/span&gt;&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;br /&gt;    puts &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;Steps:&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;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;descriptions&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;each_with_index &lt;span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby"&gt;do &lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;(&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;step&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;,&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;desc&lt;/span&gt;)&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;,&lt;/span&gt;&lt;span class="variable variable_other variable_other_block variable_other_block_ruby"&gt;i&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby"&gt;|&lt;/span&gt;&lt;br /&gt;      puts &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;i&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;+&lt;/span&gt;&lt;span class="constant constant_numeric constant_numeric_ruby"&gt;1&lt;/span&gt;&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;step&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;desc&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;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&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;step&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;name&lt;span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby"&gt;,&lt;/span&gt;&lt;span class="keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby"&gt;&amp;amp;&lt;/span&gt;block&lt;/span&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;steps&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;[&lt;/span&gt;name&lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;]&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; block&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;descriptions&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;[&lt;/span&gt;name&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_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;last_description&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;last_description&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; &lt;span class="constant constant_language constant_language_ruby"&gt;nil&lt;/span&gt; &lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&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;description&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;text&lt;/span&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby"&gt;@&lt;/span&gt;last_description&lt;/span&gt; &lt;span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby"&gt;=&lt;/span&gt; text&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-1707714869305845082?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/1707714869305845082/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=1707714869305845082' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1707714869305845082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/1707714869305845082'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/05/dont-cry-over-spilled-context.html' title='Don&apos;t Cry Over Spilled Context'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-6908969933107757450</id><published>2008-05-14T21:37:00.003-05:00</published><updated>2008-05-14T21:43:44.634-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='modules'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Conditional includes</title><content type='html'>This little problem came up at work a few days ago: what if you want to include a module but, based on the including class, get some different behavior? Enter conditional includes.&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&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;Foo&lt;/span&gt;&lt;/span&gt;&lt;br /&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;Bar&lt;/span&gt;&lt;/span&gt;&lt;br /&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;hello&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      puts &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;hi from bar&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;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&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;Baz&lt;/span&gt;&lt;/span&gt;&lt;br /&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;hello&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      puts &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;hi from baz&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;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&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;self.included&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;klass&lt;/span&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;if&lt;/span&gt; klass&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;to_s &lt;span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_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;Blah&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;br /&gt;      klass&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;send&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;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;Bar&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;else&lt;/span&gt;&lt;br /&gt;      klass&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;send&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;(&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;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;Baz&lt;/span&gt;&lt;span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, we can change the conditional logic to fit our needs. Now we'll include this module into two classes:&lt;br /&gt;&lt;br /&gt;&lt;pre class="textmate-source vibrant_ink"&gt;&lt;span class="source source_ruby source_ruby_rails"&gt;&lt;span class="meta meta_class meta_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby"&gt;Blah&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;include&lt;/span&gt; &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="meta meta_class meta_class_ruby"&gt;&lt;span class="keyword keyword_control keyword_control_class keyword_control_class_ruby"&gt;class&lt;/span&gt; &lt;span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby"&gt;Barf&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;include&lt;/span&gt; &lt;span class="variable variable_other variable_other_constant variable_other_constant_ruby"&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword keyword_control keyword_control_ruby"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="support support_class support_class_ruby"&gt;Blah&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;hello  &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; =&amp;gt; 'hi from bar'&lt;br /&gt;&lt;/span&gt;&lt;span class="support support_class support_class_ruby"&gt;Barf&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;&lt;span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby"&gt;new&lt;/span&gt;&lt;span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby"&gt;.&lt;/span&gt;hello  &lt;span class="comment comment_line comment_line_number-sign comment_line_number-sign_ruby"&gt;&lt;span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby"&gt;#&lt;/span&gt; =&amp;gt; 'hi from baz'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Yahoo! We get different behavior from each class without exposing the complexity to the end user.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-6908969933107757450?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/6908969933107757450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=6908969933107757450' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/6908969933107757450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/6908969933107757450'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/05/conditional-includes.html' title='Conditional includes'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7638404154269297868.post-7642057455774808553</id><published>2008-04-24T02:18:00.005-05:00</published><updated>2008-05-13T23:47:02.674-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='rubinius'/><category scheme='http://www.blogger.com/atom/ns#' term='oss'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>The rubinius community rocks</title><content type='html'>The &lt;a href="http://rubini.us/"&gt;rubinius&lt;/a&gt; community is impressive. Really impressive. After watching Evan Phoenix's talk at &lt;a href="http://mtnwestrubyconf2008.confreaks.com/"&gt;MountainWest RubyConf&lt;/a&gt;, I decided to see what all the fuss was about. Sure enough, it was just as easy to get involved as he claimed.&lt;br /&gt;&lt;br /&gt;How easy? I went from downloading source code to having a patch committed in less than 24 hours. And this is the first open source project I've contributed to other than my own tiny gems on rubyforge. If I can do it, you definitely can.&lt;br /&gt;&lt;br /&gt;Oh, and did I mention that having a single patch committed (no matter how small) gives you commit rights? Ingenious.&lt;br /&gt;&lt;br /&gt;Why is this important? Because I am now very jazzed about rubinius. People on the irc channel are super helpful. The documentation on the &lt;a href="http://rubinius.lighthouseapp.com/projects/5089-rubinius/overview"&gt;lighthouse&lt;/a&gt; page is awesome. They're even on git. I don't want to sleep. I want to submit patches.&lt;br /&gt;&lt;br /&gt;On top of being totally accessible for a first time OSS'er, the project is just cool. After toying around with lisp and io, self-implementing languages seem really neat to me. Coding ruby to create ruby is a gratifying experience.&lt;br /&gt;&lt;br /&gt;If you've been waiting for a project to get involved in, you should definitely check it out. They have all the tools that make it easy and fun to get going fast. And best of all, they are nice people.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7638404154269297868-7642057455774808553?l=blog.drewolson.org' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.drewolson.org/feeds/7642057455774808553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=7638404154269297868&amp;postID=7642057455774808553' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/7642057455774808553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7638404154269297868/posts/default/7642057455774808553'/><link rel='alternate' type='text/html' href='http://blog.drewolson.org/2008/04/rubinius-community-rocks.html' title='The rubinius community rocks'/><author><name>drew olson</name><uri>http://www.blogger.com/profile/05841768484212409868</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15613864122579486026'/></author><thr:total>1</thr:total></entry></feed>