<?xml version="1.0"?>
<rdf:RDF
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns="http://purl.org/rss/1.0/"
>
<channel rdf:about="http://planetruby.0x42.net/">
	<title>Planet Ruby</title>
	<link>http://planetruby.0x42.net/</link>
	<description>Planet Ruby - http://planetruby.0x42.net/</description>

	<items>
		<rdf:Seq>
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-19626531.post-9011603051424770549" />
			<rdf:li rdf:resource="http://pragdave.blogs.pragprog.com/pragdave/2008/05/our-take-on-pre.html" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-19626531.post-7424517142851686866" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-19626531.post-5778383724683099288" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-19626531.post-5993386436344845991" />
			<rdf:li rdf:resource="http://onestepback.org/index.cgi/Tech/Conferences/TestingInRails/TddStudioJune2008.red" />
			<rdf:li rdf:resource="http://pragdave.blogs.pragprog.com/pragdave/2008/05/silly-shoulda-t.html" />
			<rdf:li rdf:resource="tag:errtheblog.com,2008:Post/90" />
			<rdf:li rdf:resource="tag:weblog.jamisbuck.org,2008-02-16:4194" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-20975090.post-4683995300507623856" />
			<rdf:li rdf:resource="http://tomcopeland.blogs.com/juniordeveloper/2008/05/mod_rails-and-c.html" />
			<rdf:li rdf:resource="http://pragdave.blogs.pragprog.com/pragdave/2008/05/test-driven-rai.html" />
			<rdf:li rdf:resource="http://tomcopeland.blogs.com/juniordeveloper/2008/05/mod_rails-for-y.html" />
			<rdf:li rdf:resource="tag:weblog.jamisbuck.org,2008-04-11:4355" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-20975090.post-5678536949833072644" />
			<rdf:li rdf:resource="tag:technomancy.us,2007:in%20which%20light%20is%20shed%20upon%20some%20previously%20unexplored%20frontiers" />
			<rdf:li rdf:resource="tag:chneukirchen@yahoo.de,2004-06:chris-blogs-x-20080513-170804" />
			<rdf:li rdf:resource="http://onestepback.org/index.cgi/General/PresentingCodeUpdate.red" />
			<rdf:li rdf:resource="http://onestepback.org/index.cgi/General/PresentingCode.red" />
			<rdf:li rdf:resource="http://onestepback.org/index.cgi/Tech/Ruby/LispInRuby.red" />
		</rdf:Seq>
	</items>
</channel>

<item rdf:about="tag:blogger.com,1999:blog-19626531.post-9011603051424770549">
	<title>Ola Bini: ThoughtWorks comes to Sweden</title>
	<link>http://ola-bini.blogspot.com/2008/05/thoughtworks-comes-to-sweden.html</link>
	<content:encoded>I few months back I blogged about the possibility that ThoughtWorks would come to Sweden. Well, this is now reality. I have the extreme honor to be a part of this initiative together with Marcus Ahnve (who blogged about it &lt;a href=&quot;http://marcus.ahnve.net/2008/05/16/joining-thoughtworks-starting-office-in-stockholm/&quot;&gt;here&lt;/a&gt;). If you read that blog you will know that Marcus will  head the Swedish operation. I am immensely happy about having him as my new colleague and also boss. =)&lt;br /&gt;&lt;br /&gt;People might ask what my role in this new office will be. That's a valid question. My main goal is to stay out of trouble - and trying my very best to not scare potential customers away. Marcus is extremely capable and will handle all challenges, which means that I'll do my best to bask in the glory of opening an new office. I might also have a hand in any billable work we do, and help out with recruitment and possibly even (shudder) marketing.&lt;br /&gt;&lt;br /&gt;Not sure if you catched the meaning in that last sentence, but let me spell two points out. We will be selling work in Sweden from day one. I will be one of the consultants sold and that means that if you have an Ruby or JRuby work you want to start up, this might be an excellent time to call your local ThoughtWorks office... =)&lt;br /&gt;&lt;br /&gt;The recruitment point is simply this. We plan on accumulating the best people we can find - as we aim to do in every country we enter. If you feel like you could fit this bill, mail me and we can talk.&lt;br /&gt;&lt;br /&gt;It's important to note that this operation will initially be very low profile. Don't expect center folds in DN's Economy pages. We will work mostly with word-of-mouth. So if you hear of someone that might need our help, don't hesitate to mention our name. And even though we are low profile, we will still have the resources of the whole company to draw on. A 1000  ThoughtWorkers. That feels rather good, and it should feel even better for any prospective clients.&lt;br /&gt;&lt;br /&gt;One thing I have been a bit worried about is my commitment to JRuby, and other open source projects. I assure everyone I'll do my best to live up to these commitments. Sleep be damned!&lt;br /&gt;&lt;br /&gt;These are exciting times. I for one is looking forward to it very much. Me and Marcus will officially start on this from June this year. Get in touch if you have any questions. It's my name separated with dots at gmail, or obini at the official thoughtworks domain.&lt;span id=&quot;formatbar_Buttons&quot;&gt;&lt;/span&gt;</content:encoded>
	<dc:date>2008-05-16T23:00:35+00:00</dc:date>
	<dc:creator>Ola Bini</dc:creator>
</item>
<item rdf:about="http://pragdave.blogs.pragprog.com/pragdave/2008/05/our-take-on-pre.html">
	<title>Dave Thomas: Our take on presenting code</title>
	<link>http://pragdave.blogs.pragprog.com/pragdave/2008/05/our-take-on-pre.html</link>
	<content:encoded>&lt;p&gt;Back in March, Jim Weirich posted some notes on a clever technique for &lt;a href=&quot;http://onestepback.org/index.cgi/General/PresentingCode.red&quot;&gt;getting code into Keynote presentations&lt;/a&gt;. It struck a chord with me, because I've been suffering the same problem for a long time now. Eventually, the pain of putting together the Studio content with Mike Clark and Chad Fowler drove me to find a solution. (The pain wasn't working with Mike and Chad—it was creating and keeping up to date many hundreds of slides, most of which contained code.)&lt;/p&gt;

&lt;p&gt;The solution we went with was based on the way we do code in the Bookshelf books. Rather than embedding the code in the slides, we write regular old programs. Then, in the slide material, we reference the source file (and optionally say which section of that source file), and the appropriate code gets dragged into the slide, syntax highlighted, and hyperlinked back to our editor. Here's how it works.&lt;/p&gt;

&lt;h2&gt;Create Your Material&lt;/h2&gt;

&lt;p&gt;We've given up using Keynote and Powerpoint. They're a pain with version control, and they make it easy to fall into the eye-candy trap, favoring glitz over content. Instead, we create our material is plain text files using Textile markup. Typically we use one file per major topic, and the use an index file to bring all these individual files together into a single overall presentation/&lt;/p&gt;

&lt;p&gt;Within the material, we can include material from external files using the &lt;code&gt;:code&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;Here's the source for an individual slide:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;h1. const_missing
Correctly handles nested modules
:code code/meta/const_missing.rb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and here's what appears on the screen:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s1.jpg&quot;&gt;&lt;img class=&quot;image-full&quot; alt=&quot;S1&quot; title=&quot;S1&quot; src=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s1.jpg&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code gets inserted onto the slide and is syntax highlighted. The blue text below the box shows the file name (so attendees can find it in their collateral material). It's also a txmt: hyperlink—click it and the file opens in Textmate, so we can edit and run it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/const_missingrb.jpg&quot;&gt;&lt;img class=&quot;image-full&quot; alt=&quot;Const_missingrb&quot; title=&quot;Const_missingrb&quot; src=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/const_missingrb.jpg&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Using Parts of a Source File&lt;/h2&gt;

&lt;p&gt;You often just want to show part of a larger source file. We do that by including &lt;code&gt;START:tag&lt;/code&gt; and &lt;code&gt;END:tag&lt;/code&gt; comments in the original source. (This works in any language, and not just Ruby source). In the slide markup, you indicate the part(s) you want to include in square brackets after the file name:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;pre&gt;h1. method_missing&lt;br /&gt;
:code code/meta/my_ostruct.rb[impl class=code-small]&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This says to look at the source file &lt;code&gt;code/meta/my_ostruct.rb&lt;/code&gt; and only include on the slide the stuff between &lt;code&gt;START:impl&lt;/code&gt; and  comments. We'll also display it using the CSS class &lt;code&gt;code-small&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The ability to include parts of code is invaluable when you're doing a sequence of slides that builds a solution: you can show each part of a source file in turn.&lt;/p&gt;

&lt;h2&gt;Building the Presentation&lt;/h2&gt;

&lt;p&gt;The toolchain that takes all this is remarkably simple, because most of the work is done for us. We use a simple Ruby script that takes our original slides, embeds the source code from external files, and then runs Textile to produce an HTML version. We then add a header to that HTML that drags in two incredibly useful Javascript libraries.&lt;/p&gt;

&lt;p&gt;For the presentation itself, we use Eric Meyer's &lt;a href=&quot;http://meyerweb.com/eric/tools/s5/&quot;&gt;S5&lt;/a&gt; system. It gives us nice looking slides, simple to use navigation, and lets us present in our own browsers or (potentially) on our students'. &lt;/p&gt;

&lt;p&gt;For the syntax highlighting of code, we use &lt;a href=&quot;http://code.google.com/p/syntaxhighlighter/&quot;&gt;SyntaxHighlighter&lt;/a&gt;. This clever piece of code doesn;t require you to mark up the code elements inthe HTML. Instead you just flag your &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; blocks with an appropriate class and it does the parsing and highlighting in the browser. It means that really large decks can be a little slow to load (but the still beat Keynote on elaspsed time), but it also means your HTML is really clean.&lt;/p&gt;

&lt;p&gt;Finally, we have a Rake task that lets us built the whole presentation or just individual chapters.&lt;/p&gt;

&lt;p&gt;The whole thing took about 4 hours to get working, and probably another 4 hours on and off to tweak it based on experience. The code's not really in a state that can be released (so please don't ask), but it wouldn't take much to produce something you could do the same with.&lt;/p&gt;

&lt;h2&gt;It Actually Works in Practice!&lt;/h2&gt;

&lt;p&gt;So far, we've done two studios using this stuff (Advanced Ruby and Erlang), and I've used it in a number of conference presentations. I wouldn't switch back to regular presentation software for any code-based talk. (I'll still use Keynote for non-code slides, though.)&lt;/p&gt;

&lt;h2&gt;A Few More Slides&lt;/h2&gt;

&lt;p&gt;Here's the source:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;pre&gt;h1. initialize_copy&lt;br /&gt;
Container wrappers such a OStruct have a potential problem&lt;br /&gt;
:code code/meta/my_ostruct_problem.rb[class=code-small]&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;h1. initialize_copy&lt;br /&gt;
:code code/meta/my_ostruct_ic.rb[impl class=code-small]&lt;/p&gt;

&lt;p&gt;h1. const_missing&lt;br /&gt;
* Module method whenever undefined constant references in that module&lt;br /&gt;
** (Module is a module, and acts as a global place for @const_missing@)&lt;br /&gt;
* Mostly used to autoload classes&lt;br /&gt;
* Not as easy as it looks (Rails' @dependencies.rb@ is 500 lines long)&lt;/p&gt;

&lt;p&gt;h1. const_missing&lt;br /&gt;
:code code/meta/const_missing_autoload.rb[class=code-small]&lt;/p&gt;

&lt;p&gt;And here are the resulting slides:&lt;/p&gt;

&lt;p&gt;                                                                                 &lt;br /&gt;
&lt;a href=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s2.jpg&quot;&gt;&lt;img class=&quot;image-full&quot; alt=&quot;S2&quot; title=&quot;S2&quot; src=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s2.jpg&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;a href=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s3.jpg&quot;&gt;&lt;img class=&quot;image-full&quot; alt=&quot;S3&quot; title=&quot;S3&quot; src=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s3.jpg&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;a href=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s4.jpg&quot;&gt;&lt;img class=&quot;image-full&quot; alt=&quot;S4&quot; title=&quot;S4&quot; src=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s4.jpg&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;a href=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s5.jpg&quot;&gt;&lt;img class=&quot;image-full&quot; alt=&quot;S5&quot; title=&quot;S5&quot; src=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/16/s5.jpg&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-16T22:58:21+00:00</dc:date>
</item>
<item rdf:about="tag:blogger.com,1999:blog-19626531.post-7424517142851686866">
	<title>Ola Bini: Dynamically created methods in Ruby</title>
	<link>http://ola-bini.blogspot.com/2008/05/dynamically-created-methods-in-ruby.html</link>
	<content:encoded>There seems to be some confusion with regards to dynamically defining methods in Ruby. I thought I'd take a look at the three available methods for doing this and just quickly note why you'd use one method in favor of another.&lt;br /&gt;&lt;br /&gt;Let's begin by a quick enumeration of the available ways of defining a method after the fact:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Using a def&lt;/li&gt;&lt;li&gt;Using define_method&lt;/li&gt;&lt;li&gt;Using def inside of an eval&lt;/li&gt;&lt;/ul&gt;There are several things to consider when you dynamically define a method in Ruby. Most importantly you need to consider performance, memory leaks and lexical closure. So, the first, and simplest way of defining a method after the fact is def. You can do a def basically anywhere, but it needs to be qualified if you're not immediately in the context of a module-like object. So say that you want to create a method that returns a lazily initialized value, you can do it like this:&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;class&lt;/span&gt; &lt;span&gt;Obj&lt;/span&gt;&lt;br /&gt;&lt;span&gt;  def&lt;/span&gt; &lt;span&gt;something&lt;/span&gt;&lt;br /&gt;   puts &lt;span&gt;&quot;calling simple&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    @abc&lt;/span&gt; = 3*42&lt;br /&gt;&lt;span&gt;    def&lt;/span&gt; &lt;span&gt;something&lt;/span&gt;&lt;br /&gt;     puts &lt;span&gt;&quot;calling memoized&quot;&lt;/span&gt;&lt;br /&gt; &lt;span&gt;    @abc&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    end&lt;/span&gt;&lt;br /&gt;   something&lt;br /&gt;&lt;span&gt;  end&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;o = &lt;span&gt;Obj&lt;/span&gt;.new&lt;br /&gt;o.something&lt;br /&gt;o.something&lt;br /&gt;o.something&lt;/pre&gt;&lt;br /&gt;As you can see, we can use the def keyword inside of any context. Something that bites most Ruby programmers at least once - and more than once if they used to be Scheme programmers -  is that the second def of &quot;something&quot; will not do a lexically scoped definition inside the scope of the first &quot;something&quot; method. Instead it will define a &quot;something&quot; method on the metaclass of the currently executing self. This means that in the example of the local variable &quot;o&quot;, the first call to &quot;something&quot; will first calculate the value and then define a new &quot;something&quot; method on the metaclass of the &quot;o&quot; local variable. This pattern can be highly useful.&lt;br /&gt;&lt;br /&gt;Another variation is quite common. In this case you define a new method on a specific object, without that object being the self. The syntax is simple:&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;o.something&lt;/span&gt;&lt;br /&gt; puts &lt;span&gt;&quot;singleton method&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;/pre&gt;This is deceptively simple, but also powerful. It will define a new method on the metaclass of the &quot;o&quot; local variable, constant, or result of method call. You can use the same syntax for defining class methods:&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;String.something&lt;/span&gt;&lt;br /&gt; puts &lt;span&gt;&quot;also singleton method&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;/pre&gt;And in fact, this does exactly the same thing, since String is an instance of the Class class, this will define a method &quot;something&quot; on the metaclass of the String object. There are two other idioms you will see. The first one:&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;class&lt;/span&gt; &amp;lt;&amp;lt; o&lt;br /&gt;&lt;span&gt;  def&lt;/span&gt; &lt;span&gt;something&lt;/span&gt;&lt;br /&gt;   puts &lt;span&gt;&quot;another singleton method&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;  end&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;/pre&gt;does exactly the same thing as&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;o.something&lt;/span&gt;&lt;br /&gt; puts &lt;span&gt;&quot;another singleton method&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;This idiom is generally preferred in two cases - first, when defining on the metaclass of self. In this case, using this syntax makes what is happening much more explicit. The other common usage of this idiom is when you're defining more than one singleton method. In that case this syntax provide a nice grouping.&lt;br /&gt;&lt;br /&gt;The final way of defining methods with def is using module_eval. The main difference here is that module_eval allows you to define new instance methods for a module like object:&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;String&lt;/span&gt;.module_eval &lt;span&gt;do&lt;/span&gt;&lt;br /&gt;&lt;span&gt;  def&lt;/span&gt; &lt;span&gt;something&lt;/span&gt;&lt;br /&gt;   puts &lt;span&gt;&quot;instance method something&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;  end&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&quot;foo&quot;&lt;/span&gt;.something&lt;/pre&gt;This syntax is more or less equivalent to using the module or class keyword, but the difference is that you can send in a block which gives you some more flexibility. For example, say that you want to define the same method on three different classes. The idiomatic way of doing it would be to define a new module and include that in all the classes. But another alternative would be doing it like this:&lt;pre class=&quot;codeBox&quot;&gt;block = proc &lt;span&gt;do&lt;/span&gt;&lt;br /&gt;&lt;span&gt;  def&lt;/span&gt; &lt;span&gt;something&lt;/span&gt;&lt;br /&gt;   puts &lt;span&gt;&quot;Shared something definition&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;  end&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;String&lt;/span&gt;.module_eval &amp;amp;block&lt;br /&gt;&lt;span&gt;Hash&lt;/span&gt;.module_eval &amp;amp;block&lt;br /&gt;&lt;span&gt;Binding&lt;/span&gt;.module_eval &amp;amp;block&lt;/pre&gt;The method class_eval is an alias for module_eval - it does exactly the same thing.&lt;br /&gt;&lt;br /&gt;OK, so now you know when the def method can be used. Some important notes about it to remember is this: def does _not_ use any enclosing scope. The method defined by def will not be a lexical closure, which means that you can only use instance variables from the enclosing running environment, and even those will be the instance variables of the object executing the method, not the object defining the method. My main rule is this: use def whenever you can. If you don't need lexical closures or a dynamically defined name, def should be your default option. The reason: performance. All the other versions are much harder - and in some cases impossible - for the runtimes to improve. In JRuby, using def instead of define_method will give you a large performance boost. The difference isn't that large with MRI, but that is because MRI doesn't really optimize the performance of general def either, so you get bad performance for both.&lt;br /&gt;&lt;br /&gt;Use def unless you can't.&lt;br /&gt;&lt;br /&gt;The next version is define_method. It's just a regular method that takes a block that defines that implementation of the method. There are some drawbacks to using define_method - the largest is probably that the defined method can't use blocks, although this is fixed in 1.9. Define_method gives you two important benefits, though. You can use a name that you only know at runtime, and since the method definition is a block this means that it's a closure. That means you can do something like this:&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;class&lt;/span&gt; &lt;span&gt;Obj&lt;/span&gt;&lt;br /&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;something&lt;/span&gt;&lt;br /&gt;  puts &lt;span&gt;&quot;calling simple&quot;&lt;/span&gt;&lt;br /&gt;  abc = 3*42&lt;br /&gt;  (&lt;span&gt;class&lt;/span&gt; &amp;lt;&amp;lt;&lt;span&gt;self&lt;/span&gt;; &lt;span&gt;self&lt;/span&gt;; &lt;span&gt;end&lt;/span&gt;).send &lt;span&gt;:define_method&lt;/span&gt;, &lt;span&gt;:something&lt;/span&gt; &lt;span&gt;do&lt;/span&gt;&lt;br /&gt;    puts &lt;span&gt;&quot;calling memoized&quot;&lt;/span&gt;&lt;br /&gt;    abc&lt;br /&gt;  &lt;span&gt;end&lt;/span&gt;&lt;br /&gt;  something&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;o = &lt;span&gt;Obj&lt;/span&gt;.new&lt;br /&gt;o.something&lt;br /&gt;o.something&lt;br /&gt;o.something&lt;/pre&gt;OK, let this code sample sink in for a while. It's actually several things rolled into one. They are all necessary though. First, note that abc is no longer an instance variable. It's instead a local variable to the first &quot;something&quot; method. Secondly, the funky looking thing (class &lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;class&lt;/span&gt; &lt;span&gt;Obj&lt;/span&gt;&lt;br /&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;something&lt;/span&gt;&lt;br /&gt;  puts &lt;span&gt;&quot;calling simple&quot;&lt;/span&gt;&lt;br /&gt;  abc = 3*42&lt;br /&gt;  &lt;span&gt;class&lt;/span&gt; &amp;lt;&amp;lt; &lt;span&gt;self&lt;/span&gt;&lt;br /&gt;    define_method &lt;span&gt;:something&lt;/span&gt; &lt;span&gt;do&lt;/span&gt;&lt;br /&gt;      puts &lt;span&gt;&quot;calling memoized&quot;&lt;/span&gt;&lt;br /&gt;      abc&lt;br /&gt;    &lt;span&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span&gt;end&lt;/span&gt;&lt;br /&gt;  something&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;o = &lt;span&gt;Obj&lt;/span&gt;.new&lt;br /&gt;o.something&lt;br /&gt;o.something&lt;br /&gt;o.something&lt;/pre&gt;&lt;br /&gt;Well, it's a good thought. The problem is that it won't work. See, there are a few keywords in Ruby that kills lexical closure. The class, module and def keywords are the most obvious ones. So, the reference to abc inside of the define_method block will actually not be a lexical closure to the abc defined outside, but instead actually cause a runtime error since there is no such local variable in scope. This means that using define_method in this way is a bit cumbersome in places, but there are situations where you really need it.&lt;br /&gt;&lt;br /&gt;The second feature of define_method is less interesting - it allows you to have any name for the method you define, including something random you come up with at runtime. This can be useful too, of course.&lt;br /&gt;&lt;br /&gt;Let's summarize. The method define_method is a private method so it's a bit problematic to call, but it allows you to define methods that are real closures, thus providing some needed functionality. You can use whatever name you want for the method, but this shouldn't be the deciding reason to use it.&lt;br /&gt;&lt;br /&gt;There are two problems with define_method. The first one is performance. It's extremely hard to generally optimize the performance of invocation of a define_method method. Specifically, define_method invocations will usually be a bit slower than activating a block, since define_method also needs to change the self for the block in question. Since it's a closure it is harder to optimize for other reasons too, namely we can never be exactly sure about what local variables are referred to inside of the block. We can of course guess and hope and do optimistic improvements based on that, but you can never get define_method invocations are fast as invoking a regular Ruby method.&lt;br /&gt;&lt;br /&gt;Since the block sent to define_method is a closure, it means it might be a potential memory leak, as I documented in an older blog post. It's important to note that most Ruby implementations keep around the original self of the block definition, as well as the lexical context, even though the original self is never accessible inside the block, and thus shouldn't be part of the closed environment. Basically, this means that methods defined with define_method could potentially leak much more than you'd expect.&lt;br /&gt;&lt;br /&gt;The final way of defining a method dynamically in Ruby is using def or define_method inside of an eval. There are actually interesting reasons for doing both. In the first case, doing a def inside of an eval allows you to dynamically determine the name of the method, it allows you to insert any code before or after the actual functioning code, and most importantly, defining a method with def inside of eval will usually have all the same performance characteristics as a regular def method. This applies for invocation of the method, not definition of it. Obviously eval is slower than just using def directly. The reason that def inside of an eval can be made fast is that at runtime it will be represented in exactly the same way as a regular def-method. There is no real difference as far as the Ruby runtime sees it. In fact, if you want to, you can model the whole Ruby file as running inside of an eval. Not much difference there. In particular, JRuby will JIT compile the method if it's defined like that. And actually, this is exactly how Rails handles potentially slow code that needs to be dynamically defined. Take a look at the rendering of compiled views in ActionPack, or the route recognition. Both of these places uses this trick, for good reasons.&lt;br /&gt;&lt;br /&gt;The other one I haven't actually seen, and to be fair I just made it up. =) That's using define_method inside of an eval. The one thing you would gain from doing such a thing is that you have perfect control over the closure inside of the method defined. That means you could do something like this:&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;class&lt;/span&gt; &lt;span&gt;BinderCreator&lt;/span&gt;&lt;br /&gt; &lt;span&gt;def&lt;/span&gt; &lt;span&gt;get&lt;/span&gt;&lt;br /&gt;   abc = 123&lt;br /&gt;   binding&lt;br /&gt; &lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;eval(&amp;lt;&amp;lt;&lt;span&gt;EV&lt;/span&gt;, &lt;span&gt;BinderCreator&lt;/span&gt;.new.get)&lt;br /&gt;&lt;span&gt;  Object.send :define_method, :something do&lt;br /&gt;   abc&lt;br /&gt; end&lt;br /&gt;EV&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;In this code we create a new method &quot;something&quot; on Object. This method is actually a closure, but it's an extremely controller closure since we create a specific binding where we want it, and then use that binding as the context in which the define_method runs. That means we can return the value of abc from inside of the block. This solution will have the same performance problems as regular define_method methods, but it will let you control how much you close over at least.&lt;br /&gt;&lt;br /&gt;So what's the lesson? Defining methods can be complicated in Ruby, and you absolutely need to know when to use which one of these variations. Try to avoid define_method unless you absolutely have to, and remember that def is available in more places than you might think.</content:encoded>
	<dc:date>2008-05-15T15:45:00+00:00</dc:date>
	<dc:creator>Ola Bini</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-19626531.post-5778383724683099288">
	<title>Ola Bini: A New Hope: Polyglotism</title>
	<link>http://ola-bini.blogspot.com/2008/05/new-hope-polyglotism.html</link>
	<content:encoded>OK, so this isn't necessarily anything new, but I had to go with the running joke of the two blog posts this post is more or less a follow up to. If you haven't already read them, go read Yegge's &lt;a href=&quot;http://steve-yegge.blogspot.com/2008/05/dynamic-languages-strike-back.html&quot;&gt;Dynamic Languages Strikes Back&lt;/a&gt;, and Beust's &lt;a href=&quot;http://beust.com/weblog/archives/000483.html&quot;&gt;Return Of The Statically Typed Languages&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So let's see. Distilled, Steve thinks that static languages have reached the ceiling for what's possible to do, and that dynamic languages offer more flexibility and power without actually sacrificing performance and maintainability. He backs this up with several research papers that point to very interesting runtime performance improvement techniques that really can help dynamic languages perform exceptionally well.&lt;br /&gt;&lt;br /&gt;On the other hand Cedric believes that Scala is bad because of implicits and pattern matching, that it's common sense to not allow people to use the languages they like, that tools for dynamic languages will never be as good as the ones for static ones, that Java generics isn't really a problem, that dynamic language performance will improve but that this doesn't matter, that static languages really hasn't failed at all and that Java is still the best language of choice, and will continue to be for a long time.&lt;br /&gt;&lt;br /&gt;Now, these two bloggers obviously have different opinions, and it's really hard to actually see which parts are facts and which are opinions. So let me try to sort out some facts first:&lt;br /&gt;&lt;br /&gt;Dynamic language have been around for a long time. As long as statically typed languages in fact. Lisp was the first one.&lt;br /&gt;&lt;br /&gt;There have been extremely efficient dynamic language implementations. Some of the Common Lisp implementations are on par with C performance, and Strongtalk also achieved incredible numbers. As several commenters have noted, Strongtalks performance did not come from the optional type tags.&lt;br /&gt;&lt;br /&gt;All dynamic languages in large use today are not even on the same map with regards to performance. There are several approaches to fixing these, but we can't know how well they will work out in practice.&lt;br /&gt;&lt;br /&gt;Java's type system is not very strong, and not very static, as these definitions go. From a type theoretic stand point Java does not offer neither static type safety nor any complete guarantees.&lt;br /&gt;&lt;br /&gt;There is a good reason for these holes in Java. In particular, Java was created to give lots of hints to the compiler so the compiler can catch errors where the programmer is insoncistent. This is one of the reasons that you very often find yourself writing the same type name twice, including the type name arguments (generics). If the programmer makes a mistake at one side, the compiler will be able to catch this error very easily. It is a redundancy in the syntax that makes Java programs very verbose, but helps against certain kinds of mistakes.&lt;br /&gt;&lt;br /&gt;Really strong type systems like those Haskell and OCaML use provide extremely strong compile time guarantees. This means that if the compiler accepts your program, you will never see any runtime errors from the type system. This allows these compilers to generate very efficient code, because they know more about the state of the application at most points in time, compared to the compiler for Java, which knows some things, but not nearly as much as Haskell or OCaML.&lt;br /&gt;&lt;br /&gt;The downside of really strong type systems is that they disallow some extremely common expressions - these are things you intuitively can imagine, but it can't be expressed within the constraints of such a type system. One solution to these problems is to add higher kinds, but these have a tendency to create more complexity and also suffer from some of the same problems.&lt;br /&gt;&lt;br /&gt;So, we have three categories of languages here. The strongly statically checked ones, like Haskell. The weakly statically checked ones, like Java. And the dynamically checked ones, like Ruby. The way I look at these, they are good at very different things. They don't even compete in the same leagues. And comparing them is not really a valid point of reasoning. The one thing that I am totally sure if is that we need better tools. And the most important tool in my book is the language. It's interesting, many Java programmers talk so much about tools, but they never seem to think about their language as a tool. For me, the language is what shapes my thinking, and thus it's definitely much more important than which editor I'm using.&lt;br /&gt;&lt;br /&gt;I think Cedric have a point in that dynamic language tool support will never be as good as those for statically typed languages - at least not when you're defining &quot;good&quot; to be the things that current Java tools are good at. Steve thinks that the tools will be just as good, but different. I'm not sure. To a degree I know that no tool can ever be completely safe and complete, as long as the language include things like external configuration, reflection and so on. There is no way to include all dynamic aspects of Java, but using the common mainstream parts of the language will give you most of these. As always this is a tradeoff. You might get better IDE support for Java right now, but you will be able to express things in Ruby that you just can't express in Java because the abstractions will become too large.&lt;br /&gt;&lt;br /&gt;This is the point where I'm going to do a copout. These discussions are good, to the degree that we are working on improving our languages (our tools). But there is a fuzzy line in these discussions, where you end up comparing apples and oranges. These languages are all useful, for different things. A good programmer uses his common sense to provide the best value possible. That includes choosing the best language for the job. If Ruby allows you to provide functionality 5 times faster than the equivalent functionality with Java, you need to think about whether this is acceptable or not. On the one hand, Java has IDEs that make maintainability easier, but with the Ruby codebase you will end up maintaining a fifth of the size of the Java code base. Is that trade off acceptable? In some cases yes, in some cases no.&lt;br /&gt;&lt;br /&gt;In many cases the best solution is a hybrid one. There is a reason that Google allows more than one language (C++, Java, Python and JavaScript). This is because the languages are good at different things. They have different characteristics, and you can get a synergistic effect by combining them. A polyglot system can be greater than the sum of it's parts.&lt;br /&gt;&lt;br /&gt;I guess that's the message of this post. Compare languages, understand your most important tools. Have several different tools for different tasks, and understand the failings of your current tools. Reason about these failings in comparison to the tasks they should do well, instead of just comparing languages to languages.&lt;br /&gt;&lt;br /&gt;Be good polyglot programmers. The world will not have a new big language again, and you need to rewire your head to work in this environment.</content:encoded>
	<dc:date>2008-05-15T15:33:56+00:00</dc:date>
	<dc:creator>Ola Bini</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-19626531.post-5993386436344845991">
	<title>Ola Bini: Would Type Inference help Java</title>
	<link>http://ola-bini.blogspot.com/2008/05/would-type-inference-help-java.html</link>
	<content:encoded>My former colleague Lars Westergren recently posted a blog (&lt;a href=&quot;http://larswestergren.blogspot.com/2008/05/type-inference-thoughts.html&quot;&gt;here&lt;/a&gt;) about type inferencing, posing the question whether type inference would actually be good for Java, and if it would provide any benefits outside of just &quot;less typing&quot;.&lt;br /&gt;&lt;br /&gt;In short: no. Type inferencing would probably not do much more than save you some typing. But how much typing it would save you could definitely vary depending on the type of type inference you added. The one version I would probably prefer is just a very simple hack to avoid writing out the generic type arguments. One simple way of doing that would be to allow an equals sign inside of the angle brackets. In that case you could do this:&lt;br /&gt;&lt;pre class=&quot;codeBox&quot;&gt;List&amp;lt;=&amp;gt;      l  = &lt;span&gt;new&lt;/span&gt; &lt;span&gt;ArrayList&lt;/span&gt;&amp;lt;String&amp;gt;();&lt;br /&gt;List&amp;lt;String&amp;gt; l2 = &lt;span&gt;new&lt;/span&gt; &lt;span&gt;ArrayList&lt;/span&gt;&amp;lt;=&amp;gt;();&lt;/pre&gt;Of course, you can do it on more complicated expressions:&lt;pre class=&quot;codeBox&quot;&gt;List&amp;lt;Set&amp;lt;Map&amp;lt;Class&amp;lt;?&amp;gt;, List&amp;lt;String&amp;gt;&amp;gt;&amp;gt;&amp;gt; l = &lt;span&gt;new&lt;/span&gt; &lt;span&gt;ArrayList&lt;/span&gt;&amp;lt;=&amp;gt;();&lt;/pre&gt;This would save us some real pain in the definition of genericized types, and it wouldn't strip away much stuff you need for readability. In the above examples it would just strip away one duplication, and you don't need that duplication to read it correctly. The one case where it might be a little bit harder to read would be if you defined a variable and assigned it somewhere else. In that case the definition would need to carry the type information, so the instantiation would use the =&gt; syntax. I think that would be an acceptable price to reduce the verbosity of Java generics.&lt;br /&gt;&lt;br /&gt;Another kind of generics that would be somewhat useful is the kind added to C#, which is only local to a scope. That means there will be no type inferencing of member variables, method parameters or return values. Of course, that's the crux of Lars question, since this kind of type inference potentially removes ALL type information in the current text, since you can do:&lt;br /&gt;&lt;pre class=&quot;codeBox&quot;&gt;&lt;span&gt;var&lt;/span&gt; &lt;span&gt;x&lt;/span&gt; = &lt;span&gt;someValue&lt;/span&gt;.DoSomething();&lt;/pre&gt;At this point there is no easy way for you to know what the type of x actually is. Reading it like this, it looks a bit frightening if you're used to Java type tags, but in fact this is not what you would see. In most cases you have a small method - maybe 5-15 lines of code, where x is being used in some way or another. In many cases you will see methods called on x, or x used as argument to method calls. Both of these usages gives you clues about what it might be, but in fact you don't always need to know what type it is. You just need to know what you can do with it. And that's exactly what Java interfaces represent. So for example, do you know what class you get back from Collections.synchronizedMap()? No, and you shouldn't need to know. What you do know is that it's something that implements Map, and the documentation says that it is synchronized, but that is it. The only thing you know about it is that you can use it as a map.&lt;br /&gt;&lt;br /&gt;So in practice, the kind of type inference C# adds is actually quite useful, clean, and doesn't cause too much trouble - especially if you have one of those fancy ideas that do method completion... =)&lt;br /&gt;&lt;br /&gt;From another angle, there are some things that type inference could possible do, but that you will never see in Java. For example, say that you assign a variable to something, and later you assign that variable to some other value. If these two values are distinct types that doesn't overlap in the inheritence chain, you will usually get an error. But if you have an advanced type system, it will do unification for you. The basic versions will just find the most common supertype (the disjunction), but you can also imagine the compiler injecting a new type into your program that is the union of the two types in use. This will provide something similar to duck typing while still retaining some static type safety. If your type system allows multiple inheritence, the synthetic union type might even be a subclass of both the types in question.&lt;br /&gt;&lt;br /&gt;So yeah. The long answer is that you can actually do some funky stuff with type inference that doesn't immediately translate to less typing. Although less typing and better abstractions is what programming languages are all about, right? Otherwise assembler provides everything we want.</content:encoded>
	<dc:date>2008-05-15T15:32:34+00:00</dc:date>
	<dc:creator>Ola Bini</dc:creator>
</item>
<item rdf:about="http://onestepback.org/index.cgi/Tech/Conferences/TestingInRails/TddStudioJune2008.red">
	<title>Jim Weirich: Test Driven Studio in June 2008</title>
	<link>http://onestepback.org/index.cgi/Tech/Conferences/TestingInRails/TddStudioJune2008.red</link>
	<content:encoded>&lt;p&gt;&lt;em&gt;Joe O&amp;#8217;Brien and I will be leading another Test Driven
Studio in Denver, June 9-11.&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;&lt;a href=&quot;http://pragmaticstudio.com/images/studio/tdd-with-rails-icon.jpg&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://onestepback.org/images/pragstudio/studio-medium.gif&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

	&lt;h2&gt;Testing, Colorado, June &amp;#8230; What&amp;#8217;s not to like?&lt;/h2&gt;


	&lt;p&gt;About 8 years ago I come upon a technique that radically changed the
way I developed code.  I was reading Martin Fowler&amp;#8217;s &amp;#8220;Refactoring&amp;#8221; 
book and came across this paragraph:&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&amp;#8220;Whenever I do refactoring, the first step is always the
same.  I need to build a solid set of tests for that section of code.
The test are essential because even though I follow refactorings
structured to avoid most of the opportunities for introducing bugs,
I&amp;#8217;m still human and still make mistakes.  Thus I need solid
tests.&amp;#8221; &lt;/em&gt;&amp;#8212;Martin Fowler&lt;/p&gt;


	&lt;p&gt;Chapter 4 of &amp;#8220;Refactoring&amp;#8221; was my first introduction to JUnit and got
me interested in &amp;#8220;Test First Design&amp;#8221; (what we now tend to call &amp;#8220;Test
Driven Development&amp;#8221;).  Although I wrote &lt;em&gt;good&lt;/em&gt; code before, the
onfidence I had in my code took a dramatic leap forward after I
started adopting &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; practices.&lt;/p&gt;


	&lt;p&gt;On June 9 through 11, &lt;a href=&quot;http://objo.com&quot;&gt;Joe O&amp;#8217;Brien&lt;/a&gt; and I will have
the pleasure of leading the next Pragmatic Programmer&amp;#8217;s &lt;a href=&quot;http://pragmaticstudio.com/testing-rails&quot;&gt;Test-Driven
Development with Rails
Studio.&lt;/a&gt; in Denver.  We will
have an opportunity to share with you some of our experiences in using
&lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt; with Ruby and Rails.&lt;/p&gt;


	&lt;p&gt;There are still seats available, so its not too late to sign up.  More
information is available
&lt;a href=&quot;http://pragmaticstudio.com/testing-rails&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-15T13:30:58+00:00</dc:date>
</item>
<item rdf:about="http://pragdave.blogs.pragprog.com/pragdave/2008/05/silly-shoulda-t.html">
	<title>Dave Thomas: &lt;strike&gt;Silly&lt;/strike&gt; Useful shoulda trick</title>
	<link>http://pragdave.blogs.pragprog.com/pragdave/2008/05/silly-shoulda-t.html</link>
	<content:encoded>&lt;img alt=&quot;_mg_3035&quot; title=&quot;_mg_3035&quot; src=&quot;http://pragdave.blogs.pragprog.com/photos/uncategorized/2008/05/14/_mg_3035.jpg&quot; border=&quot;0&quot; /&gt;

&lt;p&gt;
Playing with the &lt;a href=&quot;http://thoughtbot.com/projects/shoulda&quot;&gt;shoulda&lt;/a&gt; testing framework, I came across a small but useful trick. Because the tests are written inside closures, local class variables are available inside &lt;code&gt;should&lt;/code&gt; blocks. They're only evaluated once, so they don't take the place of &lt;code&gt;setup&lt;/code&gt; blocks, but they are a nice way of storing test-wide values. Somehow, I like the look of this better than using instance variables or constants—the tests seem to be more uniform and balanced.
&lt;/p&gt;

	
/* Stylesheet generated from TextMate theme
 *
 * Slush &amp;amp; Poppies
 * 
 *
 */


pre.textmate-source {
	margin: 0;
	padding: 0 0 0 2px;
	font-family: Monaco, monospace;
	font-size: 11px;
	line-height: 1.3em;
	word-wrap: break-word;
	white-space: pre;
	white-space: pre-wrap;
	white-space: -moz-pre-wrap;
	white-space: -o-pre-wrap;
}

pre.textmate-source.slush_poppies {
	color: #000000;
	background-color: #F1F1F1;
}

pre.textmate-source .linenum {
	width: 75px;
	padding: 0.1em 1em 0.2em 0;
	color: #888;
	background-color: #eee;
}
pre.textmate-source.slush_poppies span {
   padding-top: 0.2em;
   padding-bottom: 0.1em;
}
pre.textmate-source.slush_poppies ::selection {
	background-color: #B0B0FF;
}
/* Comment */
pre.textmate-source.slush_poppies .comment {
	color: #406040;
}

/* String */
pre.textmate-source.slush_poppies .string {
	color: #C03030;
}

/* Number */
pre.textmate-source.slush_poppies .constant_numeric {
	color: #0080A0;
}

/* OCaml floating-point constants */
pre.textmate-source.slush_poppies .source_ocaml .constant_numeric_floating-point {
	text-decoration: underline;
}

/* Character constants */
pre.textmate-source.slush_poppies .constant_character {
	color: #800000;
}

/* Built-in constant */
pre.textmate-source.slush_poppies .constant_language {
}

/* User-defined constant */
pre.textmate-source.slush_poppies .constant_character, pre.textmate-source.slush_poppies .constant_other {
}

/* Variable */
pre.textmate-source.slush_poppies .variable_parameter, pre.textmate-source.slush_poppies .variable_other {
}

/* Keyword */
pre.textmate-source.slush_poppies .keyword {
	color: #2060A0;
}

/* Operators */
pre.textmate-source.slush_poppies .keyword_operator {
	color: #2060A0;
}

/* OCaml prefix f-p operators */
pre.textmate-source.slush_poppies .source_ocaml .keyword_operator_symbol_prefix_floating-point {
	text-decoration: underline;
}

/* OCaml infix f-p operators */
pre.textmate-source.slush_poppies .source_ocaml .keyword_operator_symbol_infix_floating-point {
	text-decoration: underline;
}

/* Module Keyword */
pre.textmate-source.slush_poppies .entity_name_module, pre.textmate-source.slush_poppies . .support_other_module {
	color: #0080FF;
}

/* Storage types */
pre.textmate-source.slush_poppies .storage_type {
	color: #A08000;
}

/* Storage */
pre.textmate-source.slush_poppies .storage {
	color: #008080;
}

/* Variant types */
pre.textmate-source.slush_poppies .entity_name_class_variant {
	color: #C08060;
}

/* Directives */
pre.textmate-source.slush_poppies .keyword_other_directive {
	font-weight: bold;
}

/* Line-number directives */
pre.textmate-source.slush_poppies .source_ocaml .keyword_other_directive_line-number {
}

/* Inherited class */
pre.textmate-source.slush_poppies .entity_other_inherited-class {
}

/* Function name */
pre.textmate-source.slush_poppies .entity_name_function {
	color: #800000;
}

/* Type name */
pre.textmate-source.slush_poppies .storage_type_user-defined {
	color: #800080;
}

/* Class type name */
pre.textmate-source.slush_poppies .entity_name_type_class_type {
	color: #8000C0;
}

/* Function argument */
pre.textmate-source.slush_poppies .variable_parameter {
}

/* Tag name */
pre.textmate-source.slush_poppies .entity_name_tag {
}

/* Tag attribute */
pre.textmate-source.slush_poppies .entity_other_attribute-name {
}

/* Library function */
pre.textmate-source.slush_poppies .support_function {
}

/* Library constant */
pre.textmate-source.slush_poppies .support_constant {
}

/* Library class/type */
pre.textmate-source.slush_poppies .support_type, pre.textmate-source.slush_poppies .support_class {
}

/* Library variable */
pre.textmate-source.slush_poppies .support_variable {
}

/* Invalid */
pre.textmate-source.slush_poppies .invalid {
}



	


&lt;pre class=&quot;textmate-source slush_poppies&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails source_ruby_rails_shoulda&quot;&gt;&lt;span class=&quot;meta meta_require meta_require_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;test/unit&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;meta meta_require meta_require_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;shoulda&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;meta meta_require meta_require_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;date&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;

&lt;span class=&quot;meta meta_require meta_require_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;csv_to_html/age_calculator&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;AgeCalculatorTest&lt;span class=&quot;entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby&quot;&gt; &lt;span class=&quot;punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby&quot;&gt;&amp;lt;&lt;/span&gt; Test::Unit::TestCase&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
                                  
  birth &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;parse&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;2003-05-02&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;meta meta_should meta_should_ruby meta_should_ruby_shoulda&quot;&gt;  &lt;span class=&quot;keyword keyword_other keyword_other_should keyword_other_should_ruby keyword_other_should_ruby_shoulda&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;be year difference if now later in year than birth&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby keyword_control_start-block_ruby_shoulda&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
    now &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;parse&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;2008-06-15&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;support support_function&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;AgeCalculator&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;age_given_dates&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;now&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; birth&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_should meta_should_ruby meta_should_ruby_shoulda&quot;&gt;  &lt;span class=&quot;keyword keyword_other keyword_other_should keyword_other_should_ruby keyword_other_should_ruby_shoulda&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;be year difference if now later in month than birth&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby keyword_control_start-block_ruby_shoulda&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
    now &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;parse&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;2008-06-15&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;support support_function&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;AgeCalculator&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;age_given_dates&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;now&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; birth&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
         
&lt;span class=&quot;meta meta_should meta_should_ruby meta_should_ruby_shoulda&quot;&gt;  &lt;span class=&quot;keyword keyword_other keyword_other_should keyword_other_should_ruby keyword_other_should_ruby_shoulda&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;be year difference minus 1 if now earlier in year than birth&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby keyword_control_start-block_ruby_shoulda&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
    now &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;parse&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;2008-04-15&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;support support_function&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;AgeCalculator&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;age_given_dates&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;now&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; birth&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_should meta_should_ruby meta_should_ruby_shoulda&quot;&gt;  &lt;span class=&quot;keyword keyword_other keyword_other_should keyword_other_should_ruby keyword_other_should_ruby_shoulda&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;be year difference minus 1 if now earlier in month than birth&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby keyword_control_start-block_ruby_shoulda&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
    now &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;parse&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;2008-05-01&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;support support_function&quot;&gt;assert_equal&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;AgeCalculator&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;age_given_dates&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;now&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; birth&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;</content:encoded>
	<dc:date>2008-05-15T04:52:39+00:00</dc:date>
</item>
<item rdf:about="tag:errtheblog.com,2008:Post/90">
	<title>err.the_blog: Who Needs an API?</title>
	<link>http://errtheblog.com/posts/90-who-needs-an-api</link>
	<content:encoded>&lt;p&gt;&lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt; is a pretty fun site to work on, I&amp;#8217;m not gonna lie. On more than one occasion, we thought it would be pretty cool to setup a service allowing public projects to receive donations.&lt;/p&gt;


	&lt;h3&gt;Sounds like an Itch&lt;/h3&gt;


	&lt;p&gt;&lt;a href=&quot;http://pledgie.org&quot;&gt;Pledgie&lt;/a&gt; being the venerable service it is, I decided one night it couldn&amp;#8217;t possibly be that hard to integrate it with GitHub. It&amp;#8217;s a pretty standard Rails site with some simple forms to make the magic happen (eg. setup a donation page).&lt;/p&gt;


	&lt;p&gt;They don&amp;#8217;t have an &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; (yet), but in this day and age, you really don&amp;#8217;t need one if you procure the proper tools.&lt;/p&gt;


	&lt;p&gt;Enter &lt;a href=&quot;http://mechanize.rubyforge.org/mechanize/&quot;&gt;Mechanize&lt;/a&gt;. You can do all I&amp;#8217;m about to describe with just &lt;span class=&quot;code&quot;&gt;Net::HTTP&lt;/span&gt;, but seriously, who wants to do that?&lt;/p&gt;


	&lt;h3&gt;Start Scratching&lt;/h3&gt;


	&lt;p&gt;&lt;strong&gt;Step 0:&lt;/strong&gt; Drive girlfriend to airport, buy a case of Anchor Steam, and turn off  the Xbox.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Sign up for a Pledgie account, cause GitHub&amp;#8217;s a regular user after all.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Write the interface on GitHub to accept the user&amp;#8217;s Paypal address.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Figure out the form fields I should be filling out to login and create a new pledge on Pledgie.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Write the Mechanize code:&lt;/p&gt;


&lt;pre class=&quot;ruby&quot;&gt;
&lt;span class=&quot;keyword&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;method&quot;&gt;pledgify&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;agent&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;WWW&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;Mechanize&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt;  &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;('&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;http://pledgie.org/accounts/login&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;')&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;  &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;forms&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;['&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;account[login]&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;']&lt;/span&gt;    &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;GitHub&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;PledgieUser&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;['&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;account[password]&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;']&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant&quot;&gt;GitHub&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;constant&quot;&gt;PledgiePass&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt;  &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;ident&quot;&gt;link&lt;/span&gt;  &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;links&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;(/&lt;/span&gt;&lt;span class=&quot;regex&quot;&gt;Create A Campaign&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;/)&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt;  &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;  &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;forms&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;['&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;campaign[title]&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;']&lt;/span&gt;        &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;FooBarz&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;['&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;campaign[paypal]&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;']&lt;/span&gt;       &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;email&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;['&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;campaign[description]&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;']&lt;/span&gt;  &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;The best project evar!&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;&amp;quot;&lt;/span&gt; 
  &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;['&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;campaign[end_date(1i)]&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;']&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;years&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;from_now&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;to_s&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;punct&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;buttons&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;ident&quot;&gt;update_attribute&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;symbol&quot;&gt;:pledgie&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ident&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ident&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;[/&lt;/span&gt;&lt;span class=&quot;regex&quot;&gt;&lt;span class=&quot;escape&quot;&gt;\d&lt;/span&gt;+&lt;/span&gt;&lt;span class=&quot;punct&quot;&gt;/])&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Take the pledgie attribute we just grabbed and put a cool badge in their repository&amp;#8217;s detail box.&lt;/p&gt;


&lt;div&gt;&lt;img src=&quot;http://img.skitch.com/20080505-ny4cigb52pgf5rnad4xge325k2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;

	&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; &lt;a href=&quot;http://pledgie.org/accounts/github&quot;&gt;Watch the millions pour in&lt;/a&gt; for GitHub&amp;#8217;s hard-working open source committers.&lt;/p&gt;


	&lt;p&gt;The obvious caveat here is that it relies on Pledgie not drastically changing the structure of its &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, but it&amp;#8217;s incredibly satisfying to throw something together like this in such a short amount of time.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;PS.&lt;/strong&gt; If you&amp;#8217;re on GitHub and wondering how you missed the original announcement, the post is here: &lt;a href=&quot;http://github.com/blog/57-getting-paid-the-open-source-way&quot;&gt;http://github.com/blog/57-getting-paid-the-open-source-way&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~f/errtheblog?a=SprL6H&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~f/errtheblog?i=SprL6H&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content:encoded>
	<dc:date>2008-05-15T02:19:29+00:00</dc:date>
	<dc:creator>PJ</dc:creator>
</item>
<item rdf:about="tag:weblog.jamisbuck.org,2008-02-16:4194">
	<title>Jamis Buck: Dealing with project overload</title>
	<link>http://weblog.jamisbuck.org/2008/2/16/dealing-with-project-overload</link>
	<content:encoded>&lt;p&gt;I’ve got my plate full of projects that need attention, and the stress has been getting to me. Everybody has different ways of dealing with stress, but I think mine is the least effective: ignoring things doesn’t make them go away.&lt;/p&gt;


	&lt;p&gt;So, I’m taking a more active approach. Starting immediately, I’m going to be spending one hour, every day, six days a week, clearing away the backlog of projects. I’ll post a comment each day to keep myself honest—if I don’t leave a comment, you may assume I did not do any work that day!&lt;/p&gt;


	&lt;p&gt;Here is a list of what I’ll be working on, more or less in order of priority:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Capistrano 2.2.0. This will primarily be a maintenance release, and mostly requires that the &lt;a href=&quot;http://dev.rubyonrails.org/query?status=new&amp;amp;#38;status=assigned&amp;amp;#38;status=reopened&amp;amp;#38;component=Capistrano&amp;amp;#38;order=priority&quot;&gt;patches that are pending&lt;/a&gt; be tested and applied. It will also update the Net::SSH and Net::SFTP gem dependencies so that they explicitly exclude any 2.0 versions of those gems.&lt;/li&gt;
		&lt;li&gt;Net::SFTP 1.1.1. This is a super minor release with no new features. All it will do is update the gem dependency on Net::SFTP such that it won’t try to load Net::SSH v2.&lt;/li&gt;
		&lt;li&gt;Net::SSH v2, Net::SFTP v2, Net::SCP v1. These will be released simultaneously. They are an 80% rewrite of the original code (and yeah, rewrites are evil, but sometimes they are necessary). The &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; has changed, and scripts written against the existing &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; will almost certainly be broken by the upgrade, so make sure you are depending on version 1.x.&lt;/li&gt;
		&lt;li&gt;Capistrano 2.3.0. This is another maintenance release, which simply modifies Capistrano to work with the new Net::SSH and Net::SFTP versions. (Possibly Net::SCP, too, not sure about that yet).&lt;/li&gt;
		&lt;li&gt;SQLite3/Ruby 1.2.2. A maintenance release. Haven’t seen a release on this for a long, long time. No new features planned, but &lt;a href=&quot;http://rubyforge.org/tracker/?group_id=274&quot;&gt;lots of bug fixes are pending&lt;/a&gt;.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;I’m not even going to try and give an &lt;span class=&quot;caps&quot;&gt;ETA&lt;/span&gt; on these. Just know that I’m working through them, an hour a day, and that progress is finally being made. I’ll post what I worked on in the comments to this thread, for those who want to follow along.&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-14T20:39:43+00:00</dc:date>
	<dc:creator>Jamis</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-20975090.post-4683995300507623856">
	<title>Charles Oliver Nutter: The Great JRuby Japanese Tour</title>
	<link>http://headius.blogspot.com/2008/05/great-jruby-japanese-tour.html</link>
	<content:encoded>Yes, friends, it's time one again for a JRuby tour. This trip, we're localizing to the islands of Japan. Do I have any Japanese readers out there?&lt;br /&gt;&lt;br /&gt;Here's our route for this trip...it's going to be a crazy ten days:&lt;br /&gt;&lt;br /&gt;&lt;div align=&quot;center&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;a href=&quot;http://maps.google.com/maps/ms?ie=UTF8&amp;amp;oe=UTF-8&amp;amp;hl=en&amp;amp;msa=0&amp;amp;msid=107605916602742758676.00044d3853e936abfca11&amp;amp;ll=34.948991,135.615234&amp;amp;spn=2.502832,9.707885&amp;amp;source=embed&quot;&gt;View Larger Map&lt;/a&gt;&lt;/small&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;June 19: Tsukuba, Ruby Kaigi&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tom Enebo and I will be presenting JRuby at the &lt;a href=&quot;http://jp.rubyist.net/RubyKaigi2008/english.html&quot;&gt;Ruby Kaigi 2008&lt;/a&gt; in Tsukuba this year, as well as meeting up with other Ruby implementers making the trip and communing with the locals. The Kaigi was great last year...lots of fun, great company, and an excellent community. We're both really excited about it. JRuby has come a long way, so we'll be doing a whirlwind tour of performance, Rails, GUI support, and finishing off with something special. It should be a great conference again this year.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;June 23: Matsue, Lecture at Shimane University, Meetup with Matz and Locals&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We were invited to present JRuby at Shimane University, as part of a lecture series they're doing on Ruby. And since Matz is based on Matsue, we'll certainly meet up with him to talk a bit offline...I expect he'll be pulled many directions at the Kaigi.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;June 24: Fukuoka, Ruby Business Commons&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tom did a keynote last year for the Ruby Business Commons, a group of Rubyists proactively trying to bring Ruby to the business community. I suspect we'll deliver another talk or just meet up with them and see how things have progressed in the past year. At any rate, Tom enjoyed the trip to Fukuoka, so I'm looking forward to this.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;June 25-27: Tokyo, meetup with local partners, universities, Rubyists?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Whenever Tom and I travel to Japan or meet up with Japanese associates, we put ourselves entirely in the hands of Sun Japan, and specifically our excellent friend and guide Takashi Shitamichi. So far, the Tokyo leg of our trip has a few embedded question marks, but I'm sure Shitamichi-san will be able to fill our days from dawn until dusk with events. Hopefully we'll have a little time to take a breath and poke around Tokyo again, but either way it will be a great end to the tour.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Spreading the Word&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'd really like to jam in as much Ruby and JRuby meetups, discussions, and talks as possible on this trip, so feel free to reblog (and perhaps translate) this entry, contact me, Tom, and Takashi directly...especially if you know of any good events while we're in Tokyo. And if you're press, Takashi can certainly hook you up if there's time in the tour (for emails...use firstname.lastname@sun.com).&lt;br /&gt;&lt;br /&gt;JRuby is ready for the Japanese Ruby community, and we're coming to town to help send it off!</content:encoded>
	<dc:date>2008-05-14T19:37:35+00:00</dc:date>
	<dc:creator>Charles Oliver Nutter</dc:creator>
</item>
<item rdf:about="http://tomcopeland.blogs.com/juniordeveloper/2008/05/mod_rails-and-c.html">
	<title>Tom Copeland: mod_rails and Capistrano</title>
	<link>http://tomcopeland.blogs.com/juniordeveloper/2008/05/mod_rails-and-c.html</link>
	<content:encoded>&lt;p&gt;Here's the Capistrano code I've been using with mod_rails:

&lt;/p&gt;

&lt;pre&gt;namespace :deploy do&lt;br /&gt;&amp;nbsp; desc &amp;quot;Restarting mod_rails with restart.txt&amp;quot;&lt;br /&gt;&amp;nbsp; task :restart, :roles =&amp;gt; :app, :except =&amp;gt; { :no_release =&amp;gt; true } do&lt;br /&gt;&amp;nbsp; &amp;nbsp; run &amp;quot;touch #{current_path}/tmp/restart.txt&amp;quot;&lt;br /&gt;&amp;nbsp; end&lt;br /&gt;&lt;br /&gt;&amp;nbsp; [:start, :stop].each do |t|&lt;br /&gt;&amp;nbsp; &amp;nbsp; desc &amp;quot;#{t} task is a no-op with mod_rails&amp;quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; task t, :roles =&amp;gt; :app do ; end&lt;br /&gt;&amp;nbsp; end&lt;br /&gt;end&lt;/pre&gt;

&lt;p&gt;I think that's all there is to it... as far as I can tell, start and stop don't make much sense in a mod_rails context.&amp;nbsp; I suppose you could use them to disable the app altogether somehow, although that kind of relates to &lt;a href=&quot;http://code.google.com/p/phusion-passenger/issues/detail?id=53&amp;amp;colspec=ID%20Type%20Status%20Priority%20Milestone%20Stars%20Summary&quot;&gt;this issue&lt;/a&gt; about &lt;code&gt;maintenance.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Credit for the restart task goes to &lt;a href=&quot;http://jimneath.org/2008/05/10/using-capistrano-with-passenger-mod_rails/&quot;&gt;Jim Neath&lt;/a&gt;; the change I made was just to put it in the &lt;code&gt;deploy&lt;/code&gt; namespace.&amp;nbsp; Works either way, though.&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-14T17:37:01+00:00</dc:date>
</item>
<item rdf:about="http://pragdave.blogs.pragprog.com/pragdave/2008/05/test-driven-rai.html">
	<title>Dave Thomas: Test-Driven Rails Studio</title>
	<link>http://pragdave.blogs.pragprog.com/pragdave/2008/05/test-driven-rai.html</link>
	<content:encoded>&lt;p&gt;&lt;img src=&quot;http://pragmaticstudio.com/images/studio/jim-teaching-framed.png&quot; alt=&quot;Jim Weirich&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I have a blast teaching at the &lt;a href=&quot;http://pragmaticstudio.com&quot;&gt;Pragmatic Studios&lt;/a&gt;.. Mike and Nicole run excellent courses, the format is incredible, and the students enthusiastic. I love presenting with two or three other instructors—it keeps the energy level high, and I always manage to learn a lot from them.&lt;/p&gt;

&lt;p&gt;Which is why it's a shame I won't be able to be at two of the upcoming Studios, &lt;a href=&quot;http://pragmaticstudio.com/railsadvanced&quot;&gt;Advanced Rails&lt;/a&gt; in Denver on June 12–14 and &lt;a href=&quot;http://pragmaticstudio.com/testing-rails/&quot;&gt;Test-Driven Development with Rails&lt;/a&gt; on June 9–11. I'm doubly bummed because the latter is taught by Jim Weirich and Joe O'Brien, both old friends from the Ruby community. I've never heard Joe teach, but I've often sat and admired Jim as he takes some complex subject and reduces in to its basics in the most incredibly entertaining ways. If you're in to Rails, and want to take your testing to the next level, I believe there are still some seats available. And if you do get there, tell 'em I said hi! I'm jealous.&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-14T15:54:08+00:00</dc:date>
</item>
<item rdf:about="http://tomcopeland.blogs.com/juniordeveloper/2008/05/mod_rails-for-y.html">
	<title>Tom Copeland: mod_rails for your staging environment</title>
	<link>http://tomcopeland.blogs.com/juniordeveloper/2008/05/mod_rails-for-y.html</link>
	<content:encoded>&lt;p&gt;This is more of a twitter than a proper blog entry, but if you're using &lt;a href=&quot;http://modrails.com/&quot;&gt;mod_rails&lt;/a&gt; for an environment other than production, don't forget to set &lt;code&gt;RailsEnv staging&lt;/code&gt; or whatever your environment name is in your Apache configuration file.&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-14T15:10:37+00:00</dc:date>
</item>
<item rdf:about="tag:weblog.jamisbuck.org,2008-04-11:4355">
	<title>Jamis Buck: More preview releases from the Net::SSH family</title>
	<link>http://weblog.jamisbuck.org/2008/4/11/more-preview-releases-from-the-net-ssh-family</link>
	<content:encoded>&lt;p&gt;I’ve got lots of code to share with you all today:&lt;/p&gt;


	&lt;h3&gt;Net::SSH 2.0 Preview Release #3&lt;/h3&gt;


	&lt;p&gt;Not very many external changes, but channels now have an &lt;code&gt;on_open_failure&lt;/code&gt; callback that you can employ to be told when a channel could not be opened.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;channel = ssh.open_channel &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |ch|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;channel.on_open_failure &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |ch, code, reason|&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;could not open channel because &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;reason.inspect&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;code&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This change was necessary to make port forwarding a bit more reliable for Net::SSH::Gateway (see below).&lt;/p&gt;


	&lt;p&gt;Also, individual Net::SSH sessions may contain their own custom properties, much as Net::SSH channel objects do, which can be quite handy when you need to keep some state associated with the session.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;ssh[:key] = &quot;value&quot;&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;This change (and several other internal refactorings) was necessary for the correct working of the Net::SSH::Multi library (see below).&lt;/p&gt;


	&lt;p&gt;To get the preview release #3 (version 1.99.2):&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;gem install --source http://gems.jamisbuck.org net-ssh&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;You can follow development via GitHub:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;&lt;a href=&quot;http://github.com/jamis/net-ssh/tree/master&quot;&gt;http://github.com/jamis/net-ssh/tree/master&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


	&lt;h3&gt;Net::SFTP 2.0 Preview Release #2&lt;/h3&gt;


	&lt;p&gt;All that was added in this preview release was custom properties on Upload instances:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;uploader = sftp.upload(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;local.file&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;remote.file&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;uploader[&lt;span class=&quot;sy&quot;&gt;:failed&lt;/span&gt;] = &lt;span class=&quot;pc&quot;&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This was necessary to get Capistrano file transfers to work with Net::SFTP 2.0.&lt;/p&gt;


	&lt;p&gt;To get the preview release #2 (version 1.99.1):&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;gem install --source http://gems.jamisbuck.org net-sftp&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;You can follow development via GitHub:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;&lt;a href=&quot;http://github.com/jamis/net-sftp/tree/master&quot;&gt;http://github.com/jamis/net-sftp/tree/master&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


	&lt;h3&gt;Net::SSH::Gateway 1.0 Preview Release #1&lt;/h3&gt;


	&lt;p&gt;Net::SSH::Gateway is (in essence) the extraction of the gateway code from Capistrano into its own library. It lets you tunnel &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; connections through some “gateway” server to servers that would be otherwise inaccessible.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;net/ssh/gateway&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;gateway = &lt;span class=&quot;co&quot;&gt;Net&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;SSH&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Gateway&lt;/span&gt;.new(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;gateway.host&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;gateway.ssh(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;remote.host&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |ssh|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;You can also use it as a general facilitator for forwarding connections over a local port, when you don’t care what port is to be used—you just want to connect to a remote server.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;gateway.open(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;remote.host&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;80&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |port|&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;Net&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;HTTP&lt;/span&gt;.get_print &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;127.0.0.1&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/path&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, port&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The current thinking is that the next release of Capistrano will ditch its own gateway implementation in favor of Net::SSH::Gateway. To get this first preview release (version 0.99.0):&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;gem install --source http://gems.jamisbuck.org net-ssh-gateway&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;You can follow development via GitHub:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;&lt;a href=&quot;http://github.com/jamis/net-ssh-gateway/tree/master&quot;&gt;http://github.com/jamis/net-ssh-gateway/tree/master&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


	&lt;h3&gt;Net::SSH::Multi 1.0 Preview Release #1&lt;/h3&gt;


	&lt;p&gt;Net::SSH::Multi is the guts of Capistrano, extracted into a library of their own. It allows you to define and categorize servers, and then execute commands in parallel on them, or on subsets of them, using an interface similar, if not identical, to that of Net::SSH::Connection::Session and Channel.&lt;/p&gt;


	&lt;p&gt;Eventually, Capistrano will be refactored to take advantage of Net::SSH::Multi, but doing so will require some significant changes to Capistrano’s innards, and would almost certainly break many third-party libraries. Thus, you won’t see Capistrano on Net::SSH::Multi until Capistrano 3.0 or so (which will &lt;em&gt;not&lt;/em&gt; be the next release of Capistrano). However, you can use Net::SSH::Multi to implement most of Capistrano’s functionality in whatever form you like. Want Capistrano-in-a-rakefile? Have at it!&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;net/ssh/multi&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;Net&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;SSH&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Multi&lt;/span&gt;.start &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |session|&lt;tt&gt;
&lt;/tt&gt;  session.use &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;jamis@somewhere.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  session.use &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;jamis@elsewhere.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  session.exec &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  session.loop&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Grab the first preview release (version 0.99.0):&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;gem install --source http://gems.jamisbuck.org net-ssh-multi&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;You can follow development via GitHub:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;&lt;a href=&quot;http://github.com/jamis/net-ssh-multi/tree/master&quot;&gt;http://github.com/jamis/net-ssh-multi/tree/master&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;For all of these libraries I’ve tried to make the rdoc and ri documentation as informative as possible, so please refer to those to get started. If those aren’t helpful enough, let me know what could make them more useful!&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-14T14:30:19+00:00</dc:date>
	<dc:creator>Jamis</dc:creator>
</item>
<item rdf:about="tag:blogger.com,1999:blog-20975090.post-5678536949833072644">
	<title>Charles Oliver Nutter: RubySpec: Bringing Ruby Test Suites Together</title>
	<link>http://headius.blogspot.com/2008/05/rubyspec-bringing-ruby-test-suites.html</link>
	<content:encoded>Hooray! &lt;a href=&quot;http://rubyspec.org/&quot;&gt;The RubySpec Project&lt;/a&gt;, a collection of runnable specifications for Ruby 1.8.6ish behavior, has graduated into its own domain. Finally there's a lively, fast-moving, independent project to create a Ruby specification and test kit. And it's already well on its way.&lt;br /&gt;&lt;br /&gt;Better documentation on how to pull the specs, update them, and use them for your own Ruby implementation (you do have a Ruby implementation, don't you?) are still being ironed out, but the repository is already available at the &lt;a href=&quot;http://github.com/brixen/rubyspec/tree/master&quot;&gt;RubySpec github&lt;/a&gt; address, so you can pull them and start reading and running them. Also see the &lt;a href=&quot;http://github.com/brixen/mspec/tree/master&quot;&gt;MSpec github&lt;/a&gt; for a lightweight (lighter than RSpec) tool to run the specs with.&lt;br /&gt;&lt;br /&gt;But this post is not just about the the RubySpec project...Brian Ford is putting together an official announcement for that as we speak. This post is a call to action.&lt;br /&gt;&lt;br /&gt;JRuby currently encompasses something like 6 separate test suites:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Our &lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/test/&quot;&gt;old JRuby test suite&lt;/a&gt; using &quot;minirunit&quot;, a small runit clone no longer in wide use (the camelCase.rb tests at that URL)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/test/externals/bfts/&quot;&gt;Ryan Davis and Eric Hodel's &quot;BFTS&quot; suite&lt;/a&gt;, a narrow but deep set of tests for a few core classes&lt;/li&gt;&lt;li&gt;Our &lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/test/&quot;&gt;newer set of JRuby tests&lt;/a&gt; using test/unit (the underscore_case.rb tests at that URL)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/test/externals/mri/&quot;&gt;MRI's own set of tests&lt;/a&gt;, from the Ruby 1.8 repository (link is to our somewhat out-of-date copy)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A &lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/test/rubicon/&quot;&gt;test/unit port of the Rubicon test suite&lt;/a&gt;, originally written by Dave Thomas while writing the Pickaxe books&lt;/li&gt;&lt;li&gt;The &lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/test/externals/ruby_test/&quot;&gt;ruby_test test suite&lt;/a&gt;, a suite of tests created by Daniel Berger for his projects (link is to our out-of-date copy)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;We don't want to run these tests forever...we would rather just run the RubySpec. So this is where we need help.&lt;br /&gt;&lt;br /&gt;Much of these tests are already encompassed in the RubySpec specs. BFTS, for example, focuses only on a very few core classes, which have been heavily covered in RubySpec. In many cases, these test suites even overlap each other, meaning that our 3 minute test run could probably be a lot shorter. If we could just replace our test suite with the RubySpec (modulo JRuby-specific bits like Java integration), we'd be very happy.&lt;br /&gt;&lt;br /&gt;But we can't afford to do that unless we know we're not throwing away good tests. The RubySpec is a work in progress, and there are always going to be gaps. It would be folly to throw away our tests without consideration. So that's where you come in.&lt;br /&gt;&lt;br /&gt;We need to start at A and work our way through Z, porting over any test cases that aren't covered in the RubySpec.&lt;br /&gt;&lt;br /&gt;I started the process tonight, adding a number of missing cases from our test_array.rb script and deleting everything I ported and everything that was already covered. It took perhaps an hour to go through, and it was of a reasonable size. Many other scripts will be much smaller, some will be larger.&lt;br /&gt;&lt;br /&gt;The benefits extend far, far beyond JRuby of course. By adding missing test cases, we're going to ensure that all new implementations have a complete spec to go on. We're going to make sure there aren't a lot of incompatibilities you users have to deal with. And we're going to show all those other languages (who are still laughing at our lack of a spec) that we can do this in our own Ruby way.&lt;br /&gt;&lt;br /&gt;So what are you waiting for? Contact &lt;a href=&quot;http://github.com/brixen&quot;&gt;Brian Ford&lt;/a&gt; and get access to the specs (perhaps after paying a one-patch toll)...have a look at the &lt;a href=&quot;http://svn.codehaus.org/jruby/trunk/jruby/test/&quot;&gt;JRuby test repository&lt;/a&gt;...pick a file, and start comparing. Tell your friends, email your favorite Ruby list, blog and reblog this effort. The time is now to pull together all the disparate suites into one. RubySpec is ready!</content:encoded>
	<dc:date>2008-05-14T01:08:07+00:00</dc:date>
	<dc:creator>Charles Oliver Nutter</dc:creator>
</item>
<item rdf:about="tag:technomancy.us,2007:in%20which%20light%20is%20shed%20upon%20some%20previously%20unexplored%20frontiers">
	<title>Phil Hagelberg: in which light is shed upon some previously unexplored frontiers</title>
	<link>http://technomancy.us/109</link>
	<content:encoded>&lt;p&gt;So I've been working on modularizing a big project at work. The REST API for this one project needs to be used in multiple places, so
I've taken it out of the Rails app and spun it off into its own server
using &lt;a href=&quot;http://rack.rubyforge.org&quot;&gt;Rack&lt;/a&gt;. Rack is a library
that abstracts away the gory details of HTTP and gives you a nice
object-oriented wrapper for it, allowing you to plug it into multiple
different backends. It's great for accelerating development on your
simple lightweight services that wouldn't otherwise justify a Merb or
Rails application. Ezra gives &lt;a href=&quot;http://brainspl.at/articles/2008/02/16/so-merb-core-is-built-on-rack-you-say-why-should-i-care&quot;&gt;a
good explanation of why you might be interested in Rack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anyhow, I was able to put this together fairly quickly by hooking
up libxml, ActiveRecord, and Rack. (If I were doing it again I'd use
&lt;a href=&quot;http://github.com/codahale/faster-builder/tree/master&quot;&gt;faster-builder&lt;/a&gt;,
which I found out about a few hours after I started the project, but
whatever.) But this particular project must be able to support
ridiculously large XML responses that could be larger than 4GB. On a
32-bit machine this is... well... problematic. The solution, of
course, is to stream the response back to the client as it's
generated so it doesn't have to all be in memory at once.&lt;/p&gt;

&lt;p&gt;Unfortunately the only Ruby support for HTTP streaming I was able
to find by searching the web is about streaming static files. I was
getting pretty discouraged until Ezra mentioned that Merb bundles a
patched version of Rack that allows streaming of programmatic
content.&lt;/p&gt;

&lt;p&gt;Sure enough, Merb's changes to Rack &lt;a href=&quot;http://technomancy.us/static/code/streaming_quine.rb&quot;&gt;do the
trick&lt;/a&gt;:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;require &lt;span class=&quot;string&quot;&gt;'rubygems'&lt;/span&gt;
require &lt;span class=&quot;string&quot;&gt;'rack/response'&lt;/span&gt;
require &lt;span class=&quot;string&quot;&gt;'rack/handler/mongrel'&lt;/span&gt;

&lt;span class=&quot;comment-delimiter&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;Launches an HTTP server on http://localhost:9999/N that streams its own code N times
&lt;/span&gt;&lt;span class=&quot;type&quot;&gt;Rack&lt;/span&gt;::&lt;span class=&quot;type&quot;&gt;Handler&lt;/span&gt;::&lt;span class=&quot;type&quot;&gt;Mongrel&lt;/span&gt;.run(&lt;span class=&quot;type&quot;&gt;Proc&lt;/span&gt;.new &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; |env|
                             [200, {}, &lt;span class=&quot;type&quot;&gt;Proc&lt;/span&gt;.new &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; |response|
                                response.send_status_no_connection_close(&lt;span class=&quot;string&quot;&gt;''&lt;/span&gt;)
                                response.send_header
                                env[&lt;span class=&quot;string&quot;&gt;'PATH_INFO'&lt;/span&gt;][/(\d+)/].to_i.times &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt;
                                  response.write &lt;span class=&quot;type&quot;&gt;File&lt;/span&gt;.read(__FILE__) + &lt;span class=&quot;string&quot;&gt;'\n'&lt;/span&gt;; sleep 1
                                &lt;span class=&quot;keyword&quot;&gt;end&lt;/span&gt;
                                response.write &lt;span class=&quot;string&quot;&gt;'\r\n\r\n'&lt;/span&gt;
                              &lt;span class=&quot;keyword&quot;&gt;end&lt;/span&gt;]
                           &lt;span class=&quot;keyword&quot;&gt;end&lt;/span&gt;, :&lt;span class=&quot;type&quot;&gt;Port&lt;/span&gt; =&amp;gt; 9999)
&lt;/pre&gt;

&lt;p&gt;I check the streaming with curl; if it's properly streamed the &lt;tt&gt;%
Received&lt;/tt&gt; will climb slowly instead of jumping at once to 100:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;$ curl http://localhost:9999/7 &gt; /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  5310    0  5310    0     0    755      0 --:--:--  0:00:07 --:--:--   796&lt;/pre&gt;

&lt;p&gt;It's not clear to me why this functionality isn't in the standard
Rack distribution. Merb seems to be Rack's biggest user, so the fact
that they have to bundle their own patched version seemes quite
odd. Anyway, if you need HTTP streaming outside Merb, you can use my
&lt;a href=&quot;http://technomancy.us/static/code/rack-0.3.0.gem&quot;&gt;version of
Rack&lt;/a&gt;. I haven't been able to get the gem served by Github;
unreproducible remote problems in the gem build process are very
opaque and give no feedback. Will look into this later.&lt;/p&gt;

&lt;p&gt;I'm going to try to get the changes into the mainline rack, but if
Merb hasn't been able to get it accepted this may not actually
happen. The meat of the patch is three lines, but I've got a bunch
of other stuff that allows the project to actually build as a gem;
the source as I found it was not in a working state. (Who knew there
were people out there who haven't yet discovered &lt;a href=&quot;http://http://blog.zenspider.com/2006/09/farmer-ted-uses-hoe-to-beat-ra.html&quot;&gt;hoe&lt;/a&gt;?)&lt;/p&gt;

&lt;p&gt;Much thanks to Ezra for the fix. I was starting to lose hope that
I'd even be able to even pull this off without resorting to
low-level Mongrel invocations. Even though the fix is available in
Merb, it's not really very clear how to use it, so I thought this
post would save other people from going through the same crazy hoops
I had to.&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-13T23:31:01+00:00</dc:date>
	<dc:creator>Phil Hagelberg</dc:creator>
</item>
<item rdf:about="tag:chneukirchen@yahoo.de,2004-06:chris-blogs-x-20080513-170804">
	<title>Chris Neukirchen: Off to Potsdam: Attending S3</title>
	<link>http://chneukirchen.org/blog/archive/2008/05/off-to-potsdam-attending-s3.html</link>
	<content:encoded>&lt;p&gt;Tomorrow I take the train to
&lt;a href=&quot;http://www.potsdam.de/cms/ziel/26670/EN/&quot;&gt;Potsdam&lt;/a&gt; to attend the
&lt;a href=&quot;http://www.swa.hpi.uni-potsdam.de/s3/index.html&quot;&gt;Workshop on Self-sustaining Systems
(S3)&lt;/a&gt;, which means I
get the chance of meeting &lt;a href=&quot;http://dreamsongs.com/&quot;&gt;rpg&lt;/a&gt; and many other
people that worked on Lisp, Self and related cool stuff in real life.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://chneukirchen.org/repos/foam&quot;&gt;stuff I&amp;#8217;m working on&lt;/a&gt; got not
finished by far, but maybe I can write down enough on the train to
explain it to interested parties.&lt;/p&gt;

&lt;p&gt;If you want to hook up, don&amp;#8217;t hesitate to &lt;a href=&quot;http://purl.org/net/chneukirchen&quot;&gt;contact
me&lt;/a&gt;.  I&amp;#8217;m there until Saturday
morning.&lt;/p&gt;

&lt;p&gt;Anarchaia and chris blogs will resume publishing Sunday, May 18.&lt;/p&gt;

&lt;p&gt;NP: Manu Chao&amp;#8212;Politik Kills&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-13T17:08:04+00:00</dc:date>
	<dc:creator>Christian Neukirchen</dc:creator>
</item>
<item rdf:about="http://onestepback.org/index.cgi/General/PresentingCodeUpdate.red">
	<title>Jim Weirich: Presenting Code ... An Update</title>
	<link>http://onestepback.org/index.cgi/General/PresentingCodeUpdate.red</link>
	<content:encoded>&lt;p&gt;&lt;em&gt;I received some feedback on the &amp;#8216;Presenting Code&amp;#8217; post from
yesterday.&lt;/em&gt;&lt;/p&gt;


	&lt;h2&gt;Presenting Code &amp;#8230; An Update&lt;/h2&gt;


	&lt;p&gt;I got lots of feedback on the &amp;#8220;Presenting Code&amp;#8221; post.  In addition to
&lt;a href=&quot;http://beust.com/weblog&quot;&gt;Cédric Beust&amp;#8217;s&lt;/a&gt; initial comments, the
following people had something to say on the topic:&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://johnwilger.com/&quot;&gt;John Wilger&lt;/a&gt; asked on Twitter why I didn&amp;#8217;t use
&amp;#8220;file:&amp;#8221; (rather than &amp;#8220;http:&amp;#8221; and a local web server).  Unfortunately,
Keynote will not do a web view from a &amp;#8220;file:&amp;#8221; style &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.madstop.com/&quot;&gt;Luke Kanies&lt;/a&gt; reports that he does something
similar.  He uses Vim (rather than Ruby + the Syntax gem) to generate
the highlighted &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;.  He also adds:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;In general, this method works out great, but the one thing I
would say is that you should &lt;strong&gt;always&lt;/strong&gt; uncheck &amp;#8220;automatic update&amp;#8221;.
Otherwise, you&amp;#8217;ll find that it tries to update 10 seconds before your
presentation starts and your web server isn&amp;#8217;t available.&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Ok, that&amp;#8217;s good advice. &lt;span class=&quot;caps&quot;&gt;BTW&lt;/span&gt;, I would be very interested in a script
(AppleScript or Ruby+OSA) that would iterate over the pages in a
Keynote presentation and refresh all the WebViews.  Any takers?&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://blog.grayproductions.net/&quot;&gt;James Edward Gray II&lt;/a&gt; and &lt;a href=&quot;http://www.clarkware.com&quot;&gt;Mike
Clark&lt;/a&gt; mentioned the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; output bundle.
James gives the following details:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Select Bundles → TextMate → Create &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; From Document (or Create &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; From Document With Line Numbers, if you prefer)&lt;/li&gt;
		&lt;li&gt;Preview the document in TextMate with Window ⇢ Show Web Preview&lt;/li&gt;
		&lt;li&gt;Highlight and Edit → Copy the content you want from the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; window&lt;/li&gt;
		&lt;li&gt;Switch to Keynote and Edit → Paste&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Mike (who credits &lt;a href=&quot;http://codefluency.com&quot;&gt;Bruce Williams&lt;/a&gt; as his
source for this tip) also provided a
&lt;a href=&quot;http://s3.amazonaws.com/pragmaticstudio/textmate-keynote.mov&quot;&gt;video&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Couple of items on the above:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;When creating the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; from the document, convert the whole
  document.  Once in Web Preview mode you can cut and paste only what
  you want.&lt;/li&gt;
		&lt;li&gt;Choose a TextMate theme with a background that matches the
  background in your presenetation to get the best effect for your
  colors.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;&lt;a href=&quot;http://drnicwilliams.com/&quot;&gt;Dr. Nic&lt;/a&gt; also mentions a &amp;#8220;Copy as &lt;span class=&quot;caps&quot;&gt;RTF&lt;/span&gt;&amp;#8221; 
TextMate bundle.  (I&amp;#8217;m not sure if this is the same as James and
Mike&amp;#8217;s hint above or something different).&lt;/p&gt;


	&lt;p&gt;Finally, &lt;a href=&quot;http://mysterycoder.blogspot.com/&quot;&gt;Chris Nelson&lt;/a&gt; confirms
(via Twitter): &amp;#8220;AFAIK there is no equivalent of web views in
OpenOffice :(&amp;#8220;&lt;/p&gt;</content:encoded>
	<dc:date>2008-05-13T12:14:40+00:00</dc:date>
</item>
<item rdf:about="http://onestepback.org/index.cgi/General/PresentingCode.red">
	<title>Jim Weirich: Presenting Code</title>
	<link>http://onestepback.org/index.cgi/General/PresentingCode.red</link>
	<content:encoded>&lt;p&gt;&lt;em&gt;This exchange on twitter got me thinking&amp;#8230;&lt;/em&gt;&lt;/p&gt;


	&lt;h2&gt;Twittering &amp;#8230;&lt;/h2&gt;


	&lt;p&gt;I noticed the following twitter conversation this evening between
&lt;a href=&quot;http://twitter.com/objo&quot; title=&quot;Joe O'Brien&quot;&gt;objo&lt;/a&gt; and &lt;a href=&quot;http://twitter.com/superchris&quot; title=&quot;Chris
Nelson&quot;&gt;superchris&lt;/a&gt;:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;superchris:&lt;/span&gt;&lt;/strong&gt;   any good recommendations on showing code samples in OpenOffice Impress?&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;objo:&lt;/span&gt;&lt;/strong&gt;   @superchris yeah, get a mac and use Keynote&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;objo:&lt;/span&gt;&lt;/strong&gt;   otherwise, I would screenshot emacs&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;superchris:&lt;/span&gt;&lt;/strong&gt;   @objo.. ya know, i almost added &amp;#8220;And I&amp;#8217;ll smack anyone who says get a Mac&amp;#8221; but ran out of space&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;superchris:&lt;/span&gt;&lt;/strong&gt;   @objo&amp;#8230; but actually your idea of using NetBeans screenshots is pretty good&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;objo:&lt;/span&gt;&lt;/strong&gt;   @superchris you never listen &amp;#8230;. &lt;span class=&quot;caps&quot;&gt;EMACS&lt;/span&gt; not netbeans. Come on man.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;superchris:&lt;/span&gt;&lt;/strong&gt;   @objo just being helpful by translating for you.. :)&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span&gt;superchris:&lt;/span&gt;&lt;/strong&gt; planning to code with NetBeans on linux
  forever for no other reason but to annoy @objo&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;h2&gt;ScreenShots &amp;#8230; Yuck!&lt;/h2&gt;


	&lt;p&gt;The problem Chris is trying to solve is putting code snippets into a
presentation.  There just isn&amp;#8217;t a good way to do this in modern
presentation programs.&lt;/p&gt;


	&lt;p&gt;In the old days, I would generate my presentation completely in &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;
from a simple text markup file.  The generation process was controlled
by rake.  This allowed me to changed the code, run the unit tests and
rebuild the presentation all with a simple rake command.  Eventually,
I got up to speed with &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; and could make some really nice looking
presentations, all from &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Although I could get nice looking slides with &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, it was a lot of
work getting it to work just so.  Eventually, I abandoned that
approach and swithed to a modern slide presentation program (Keynote
in my case).&lt;/p&gt;


	&lt;p&gt;Although generating the slides is a bit easier in Keynote (or
PowerPoint, or Open Office Impress), reproducing code for technical
talks is much harder.   You generally have two choices:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Cut and paste the code text into Keynote losing any syntax
  highlighting you might have had, or&lt;/li&gt;
		&lt;li&gt;Take a screen shot of the code in your fancy editor, preserving the
  syntax highlighting but losing the &amp;#8220;text&amp;#8221; nature of the code.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Neither option is pleasant.  The former punishes the audience by
making the code harder to read, the latter punishes you making the
presentation hard to change. (I once saw Dave Thomas giving a Ruby
talk and he noticed that he had a minor typo in the code.  He switched
to edit mode in Keynote with the intent of fixing it on the spot, then
he realized that the code was in a graphic image and was uneditable).&lt;/p&gt;


	&lt;p&gt;Of the two options, I&amp;#8217;ve been using the text cut&amp;#8217;n&amp;#8217;paste technique for
most things.  In the twitter conversation above, Chris is considering
the edit snapshot technique.&lt;/p&gt;


	&lt;h2&gt;Other Options?&lt;/h2&gt;


	&lt;p&gt;I&amp;#8217;ve heard rumors of someone working on a script that will insert code
snippets into the Keynote data file directly.  Unfortunately, as far
as I know, they are still rumors at this time.&lt;/p&gt;


	&lt;p&gt;But here&amp;#8217;s another idea.  I&amp;#8217;ve prototyped this, and think it will
work.  But be warned I haven&amp;#8217;t tried this on a really presentation
yet.&lt;/p&gt;


	&lt;h2&gt;Presenting Code &amp;#8230; A Proof of Concept&lt;/h2&gt;


	&lt;p&gt;While perusing the options in Keynote, I noticed an insert option called &amp;#8220;Web View&amp;#8221;&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://onestepback.org/images/rublog/present_code/present_code_web_view.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;It turns out that this option allows you to include a web page in your
presentation.  For example, here is my blog inserted directly into the
presentation.  Clicking on the &amp;#8220;web view&amp;#8221; object will show an &amp;#8220;update&amp;#8221; 
button that will refresh that page from the web.&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://onestepback.org/images/rublog/present_code/present_code_blog.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;So, all I have to do is get the code onto a web page, formatted nicely
with syntax highlighting, and Keynote will suck it into the
presentation, more or less automatically for me.  Cool.&lt;/p&gt;


	&lt;p&gt;Getting it formatted is easy.  That&amp;#8217;s just a small little Rake task
with a good syntax highlighting library.  I used &lt;code&gt;Syntax&lt;/code&gt; (its a gem,
docs on Rubyforge), but there are other options out there.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s the rakefile:&lt;/p&gt;


&lt;pre class=&quot;ruby&quot;&gt;
#!/usr/bin/env ruby

require &quot;rake/clean&quot; 

CLOBBER.include('*.html')

task :default =&amp;gt; :extract
task :extract =&amp;gt; &quot;hello.html&quot; 

file &quot;hello.html&quot; =&amp;gt; &quot;hello.rb&quot; do
  extract &quot;hello.html&quot;, &quot;hello.rb&quot; 
end
&lt;/pre&gt;

	&lt;p&gt;and here is the &lt;code&gt;rakelib/extract.rake&lt;/code&gt; library:&lt;/p&gt;


&lt;pre class=&quot;ruby&quot;&gt;
#!/usr/bin/env ruby

require 'syntax/convertors/html'

def extract(outfile, infile)
  open(outfile, &quot;w&quot;) do |out|
    out.puts &quot;&amp;lt;html&amp;gt;&quot; 
    out.puts &quot;  &amp;lt;head&amp;gt;&quot; 
    out.puts &quot;    &amp;lt;style type=\&quot;text/css\&quot;&amp;gt;&quot; 
    out.puts %(
.ruby { font-size: 24pt; font-weight: bold; }
.ruby .normal {}
.ruby .comment { color: #888; font-style: italic; }
.ruby .keyword { color: #A00; font-weight: bold; }
.ruby .method { color: #077; }
.ruby .class { color: #074; }
.ruby .module { color: #050; }
.ruby .punct { color: #447; font-weight: bold; }
.ruby .symbol { color: #099; }
.ruby .string { color: #944; }
.ruby .char { color: #F07; }
.ruby .ident { color: #004; }
.ruby .constant { color: #07F; }
.ruby .regex { color: #B66; }
.ruby .number { color: #D55; }
.ruby .attribute { color: #377; }
.ruby .global { color: #3B7; }
.ruby .expr { color: #227; })
    out.puts &quot;    &amp;lt;/style&amp;gt;&quot; 
    out.puts &quot;  &amp;lt;/head&amp;gt;&quot; 
    out.puts &quot;  &amp;lt;body&amp;gt;&quot; 
    out.puts &quot;    &amp;lt;pre class=\&quot;ruby\&quot;&amp;gt;&quot; 
    code = open(infile) { |f| f.read }
    convertor = Syntax::Convertors::HTML.for_syntax(&quot;ruby&quot;)
    html = convertor.convert(code)
    out.puts html
    out.puts &quot;    &amp;lt;/pre&amp;gt;&quot; 
    out.puts &quot;  &amp;lt;/body&amp;gt;&quot; 
    out.puts &quot;&amp;lt;/html&amp;gt;&quot; 
  end
end
&lt;/pre&gt;

	&lt;p&gt;Edit the &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; styles above to tweek the output to exactly the colors
you want.  I&amp;#8217;ve added a large font-size line to make the code big
enough for teh presentation (I hate small code fonts in presentations,
you can ask &lt;a href=&quot;http://twitter.com/objo&quot;&gt;objo&lt;/a&gt; about my rants on &lt;em&gt;that&lt;/em&gt;
topic.)&lt;/p&gt;


	&lt;p&gt;Now we need to get the code on a web page.  No need to get fancy here.
I have a script called &lt;code&gt;servefiles&lt;/code&gt; that will start a webrick process
that serves files from the current directory.  Just start it up with
&amp;#8220;servefiles 3333&amp;#8221; (the 3333 is the port to use).  Servefiles will
display its &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; in its startup message, like so:&lt;/p&gt;


&lt;pre class=&quot;shell&quot;&gt;
$ servefiles 3333
URL: http://tardis.local:3333
[2008-03-23 00:47:37] INFO  WEBrick 1.3.1
[2008-03-23 00:47:37] INFO  ruby 1.8.6 (2008-03-03) [i686-darwin9.2.0]
[2008-03-23 00:47:37] INFO  WEBrick::HTTPServer#start: pid=874 port=3333
&lt;/pre&gt;

	&lt;p&gt;Here&amp;#8217;s the code for &lt;code&gt;servefiles&lt;/code&gt;:&lt;/p&gt;


&lt;pre class=&quot;ruby&quot;&gt;
#!/usr/bin/env ruby
require 'webrick'
include WEBrick

dir = Dir::pwd
port = (ARGV.first || (12000 + (dir.hash % 1000))).to_i

puts &quot;URL: http://#{Socket.gethostname}:#{port}&quot; 

s = HTTPServer.new(
  :Port            =&amp;gt; port,
  :DocumentRoot    =&amp;gt; dir
)

trap(&quot;INT&quot;){ s.shutdown }
s.start
&lt;/pre&gt;

	&lt;p&gt;Now all we have to do is cut and paste the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; given by &lt;code&gt;servefiles&lt;/code&gt;
into keynote and append the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; file name we wish to add to our
presentation:&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://onestepback.org/images/rublog/present_code/present_code_hello.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Now, to update the code in the presentation, I need to:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Edit the original code base (and run unit tests against it).&lt;/li&gt;
		&lt;li&gt;Run rake&lt;/li&gt;
		&lt;li&gt;Press the &amp;#8220;Update Now&amp;#8221; button in Keynote.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Not bad.&lt;/p&gt;


	&lt;h2&gt;It&amp;#8217;s Just a Proof of Concept&lt;/h2&gt;


	&lt;p&gt;Just be warned, I haven&amp;#8217;t tried this in a real presentation yet.  I&amp;#8217;ve
just spent an hour or so seeing if all the pieces would work together.
There are some obvious things to explore.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The extraction code could be enhanced to pull snippets from files
  based on tags.  Or even better, being able to say &amp;#8220;Extract Method m
  from Class C&amp;#8221;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;I&amp;#8217;m using a fixed font size, but extract could easily take the font
  size as an argument or even calculate the proper font size given the
  amount of text found in the snippet.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul