<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Thursday Night &#187; Ruby</title>
	<atom:link href="http://blog.paulbetts.org/index.php/category/programming/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.paulbetts.org</link>
	<description>Paul Betts's personal website / blog / what-have-you</description>
	<lastBuildDate>Tue, 27 Sep 2011 21:17:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>A C# 3.5 pattern &#8211; the Accept Block pattern</title>
		<link>http://blog.paulbetts.org/index.php/2010/01/10/a-c-3-5-pattern-the-accept-block-pattern/</link>
		<comments>http://blog.paulbetts.org/index.php/2010/01/10/a-c-3-5-pattern-the-accept-block-pattern/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 02:25:35 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Mono / .NET]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/?p=390</guid>
		<description><![CDATA[A coworker pointed me towards this blog post as a useful trick to make code read cleaner. I&#8217;ve been using this trick in C# for quite some time, as it&#8217;s a very fundamental pattern in Ruby programming. In my head I call this the &#8220;Accept Block&#8221; pattern, but I&#8217;m fairly certain its just a syntactic [...]]]></description>
			<content:encoded><![CDATA[<p>
A coworker pointed me towards <a href="http://msdnrss.thecoderblogs.com/2009/12/07/silencing-exceptions-in-a-little-better-way/">this blog post</a> as a useful trick to make code read cleaner. I&#8217;ve been using this trick in C# for quite some time, as it&#8217;s a <i>very</i> fundamental pattern in Ruby programming. In my head I call this the &#8220;Accept Block&#8221; pattern, but I&#8217;m fairly certain its just a syntactic version of an existing pattern (the Strategy pattern?). In some sense, it&#8217;s like being able to write your own version of the &#8220;using&#8221; or &#8220;lock&#8221; statements.
</p>
<p>Here&#8217;s the old imperative way you might write some code:</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw2 {color: #000000; font-weight: bold;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .kw4 {color: #993333;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .co2 {color: #339933;}.ch_code_container .coMULTI {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .me1 {color: #202020;}.ch_code_container .me2 {color: #202020;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw4">void</span> Foo<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SetupTheDatabase<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bool ShouldExit = SomeFunctionThatNeedsADatabase<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; TeardownTheDatabase<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ShouldExit<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;</p>
<p>&nbsp; &nbsp; DoOtherStuff<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
<p>
And here&#8217;s how you&#8217;d rewrite it using the pattern:
</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw2 {color: #000000; font-weight: bold;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .kw4 {color: #993333;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .co2 {color: #339933;}.ch_code_container .coMULTI {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .me1 {color: #202020;}.ch_code_container .me2 {color: #202020;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw4">void</span> WithEnsureDatabaseIsSetup<span class="br0">&#40;</span>Action block<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SetupTheDatabase<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; try <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; block<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span> finally <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; TeardownTheDatabase<span class="br0">&#40;</span><span class="br0">&#41;</span>;&nbsp; <span class="co1">// Note: Make sure this doesn&#8217;t throw!</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Foo<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; bool ShouldExit;</p>
<p>&nbsp; &nbsp; WithEnsureDatabaseIsSetup<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#41;</span> =&gt; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ShouldExit = SomeFunctionThatNeedsADatabase<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ShouldExit<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; DoOtherStuff<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
<p>
In my opinion, the 2nd version is better to read, and more importantly, allows you to encapsulate the &#8220;setup/teardown&#8221; pattern &#8211; this way, this block of code is consistent, removes copy-paste errors from writing the same thing over and over again, and is easily updated if you want to do additional work when setting up the database.
</p>
<h2>But there&#8217;s a gotcha!</h2>
<p>
There&#8217;s a bug in the above code though that&#8217;s quite subtle, and that has bitten me a few times &#8211; the syntax <code>() => { }</code> is defining a <a href="http://en.wikipedia.org/wiki/Closure_(computer_science)">closure</a>, an anonymous function who can use variables bound inside its lexical environment (to understand the difference, take a look at that ShouldExit variable &#8211; even though it&#8217;s not a parameter of the function, we were still able to use it). When you call <code>return</code>, in the original example we will exit <code>Foo()</code> &#8211; in the new version, we will exit the closure and still execute <code>DoOtherStuff()</code>!  Here&#8217;s how we should fix it:
</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw2 {color: #000000; font-weight: bold;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .kw4 {color: #993333;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .co2 {color: #339933;}.ch_code_container .coMULTI {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .me1 {color: #202020;}.ch_code_container .me2 {color: #202020;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw4">void</span> Foo<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; bool ShouldExit;</p>
<p>&nbsp; &nbsp; WithEnsureDatabaseIsSetup<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#41;</span> =&gt; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ShouldExit = SomeFunctionThatNeedsADatabase<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ShouldExit<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>; &nbsp; &nbsp; <span class="co1">// Now we&#8217;ll return properly</span></p>
<p>&nbsp; &nbsp; DoOtherStuff<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
<h2>Ruby doesn&#8217;t have this problem</h2>
<p>
This is a fundamental pattern in Ruby and built into the language and the runtime, so much so that it has special syntax to make it happen. However in Ruby a &#8220;block&#8221; is a slightly different syntactic structure than a function, so <code>return</code> will do what you expect:
</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color:#9966CC; font-weight:bold;}.ch_code_container .kw2 {color:#0000FF; font-weight:bold;}.ch_code_container .kw3 {color:#CC0066; font-weight:bold;}.ch_code_container .co1 {color:#008000; font-style:italic;}.ch_code_container .coMULTI {color:#000080; font-style:italic;}.ch_code_container .es0 {color:#000099;}.ch_code_container .br0 {color:#006600; font-weight:bold;}.ch_code_container .st0 {color:#996600;}.ch_code_container .nu0 {color:#006666;}.ch_code_container .me1 {color:#9900CC;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw1">def</span> Foo<span class="br0">&#40;</span>an_array<span class="br0">&#41;</span><br />
&nbsp; &nbsp; an_array.<span class="me1">each</span> <span class="br0">&#123;</span> |item|&nbsp; <span class="co1"># This is a block with 1 param</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">print</span> item<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">return</span> <span class="kw1">if</span> item &gt; <span class="nu0">2</span>&nbsp; <span class="co1"># Actually returns from Foo, not from block</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="kw1">end</span></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2010/01/10/a-c-3-5-pattern-the-accept-block-pattern/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Yikes! for nerds: how to get the code</title>
		<link>http://blog.paulbetts.org/index.php/2008/06/05/yikes-for-nerds-how-to-get-the-code/</link>
		<comments>http://blog.paulbetts.org/index.php/2008/06/05/yikes-for-nerds-how-to-get-the-code/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 03:27:31 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Yikes!]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2008/06/05/yikes-for-nerds-how-to-get-the-code/</guid>
		<description><![CDATA[I ran out of time yesterday, but as promised, here&#8217;s how to build and run Yikes! Quick Start /* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: [...]]]></description>
			<content:encoded><![CDATA[<p>
I ran out of time yesterday, but as promised, here&#8217;s how to build and run Yikes!
</p>
<h2>Quick Start</h2>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;">git clone git://github.com/xpaulbettsx/yikes.git<br />
<span class="kw3">cd</span> yikes<br />
rake &amp;&amp; rake ffmpeg<br />
ruby lib/main.rb -l /path/to/videos -t /path/to/ipod/output -r <span class="nu0">1800</span> -b</div>
<h2>Getting the code</h2>
<p>
By far, the best way to get the code is via <a href="http://en.wikipedia.org/wiki/Git_(software)">Git</a>; this lets you view the entire commit history, as well as send me changes. If you don&#8217;t have Git, you can download precompiled source code trees for <a href="http://paulbetts.org/projects/yikes/yikes_pre0.5_linux.zip">Linux</a> or <a href="http://paulbetts.org/projects/yikes/yikes_pre0.5_osx.zip">Mac OS X 10.5</a>. The Git clone URL via <a href="http://github.com/xpaulbettsx/yikes/tree/master">Github</a> is git://github.com/xpaulbettsx/yikes.git
</p>
<h2>Building (&#8220;Huh? Building? On Ruby?&#8221;)</h2>
<p>
<i>(If you downloaded the precompiled version, skip this part!)</i> Even though the application is in Ruby, we need to build ffmpeg and its associated libraries from source, so you need to have the XCode tools installed, and you probably need MacPorts as well. While building this takes forever, it&#8217;s fairly easy:
</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;">rake &amp;&amp; rake ffmpeg</div>
<h2>Running the app</h2>
<p>
Right now, you have to run Yikes! from the command line, but the syntax is pretty easy. Here&#8217;s a sample:</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw3">cd</span> yikes_public</p>
<p><span class="co1"># The long version</span><br />
ruby lib/main.rb &#8211;library /path/to/videos &#8211;target /path/to/ipod/output &#8211;rate <span class="nu0">1800</span> &#8211;background</p>
<p><span class="co1"># or if you want the short version</span><br />
ruby lib/main.rb -l /path/to/videos -t /path/to/ipod/output -r <span class="nu0">1800</span> -b</p>
<p><span class="co1"># If you want to run it on the sample files for development, there&#8217;s an easier way</span><br />
rake run</div></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2008/06/05/yikes-for-nerds-how-to-get-the-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Yikes! It&#8217;s your videos on your iPod!</title>
		<link>http://blog.paulbetts.org/index.php/2008/06/04/yikes-its-your-videos-on-your-ipod/</link>
		<comments>http://blog.paulbetts.org/index.php/2008/06/04/yikes-its-your-videos-on-your-ipod/#comments</comments>
		<pubDate>Wed, 04 Jun 2008 17:14:30 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Yikes!]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2008/06/04/yikes-its-your-videos-on-your-ipod/</guid>
		<description><![CDATA[For awhile, I&#8217;ve been working on a project that is pretty cool, and I&#8217;m finally getting near the &#8220;first 90% done&#8221; software development mark; now I&#8217;ve got the 2nd 90% to get it to production-quality, and the 3rd 90% will make it actually good. Here&#8217;s the screenshot: Yes, the UI is rough-draft, I&#8217;ve got to [...]]]></description>
			<content:encoded><![CDATA[<p>
For awhile, I&#8217;ve been working on a project that is pretty cool, and I&#8217;m finally getting near the &#8220;first 90% done&#8221; software development mark; now I&#8217;ve got the 2nd 90% to get it to production-quality, and the 3rd 90% will make it actually <i>good</i>. Here&#8217;s the screenshot:
</p>
<p align="center">
<img src="http://blog.paulbetts.org/wp-photos/yikes_screenshot.png" /><br />
<i>Yes, the UI is rough-draft, I&#8217;ve got to go to town on it in CSSEdit</i>
</p>
<h2>What&#8217;s it do?</h2>
<p>
In its simple mode, Yikes! will take a directory and convert all the movies to iPod/iPhone format (H.264 MPEG-4&#8242;s, so compatible with most players), and it will skip files it&#8217;s already converted. This isn&#8217;t too far off from what you could do with Handbrake and some clever bash scripts.
</p>
<p>
However, you can also run the program in background mode, and this is where it gets really useful. You give the program a folder of videos, and a place to put the iPod videos, and it will start a web site that you can go to on another computer, where you can see the converted videos, download them, or <i>(and here&#8217;s the clever part)</i>, add it to iTunes as a video podcast, which will copy all the videos to your iPod automagically.
</p>
<h2>Where&#8217;s the code?</h2>
<p>
Github! <a href="http://github.com/xpaulbettsx/yikes">http://github.com/xpaulbettsx/yikes</a><br />
<b>Update:</b> Changed URL from earlier, merged webif-ramaze into master
</p>
<p>
Later today once I&#8217;m back at home I&#8217;ll put up a &#8220;how to get/build the code&#8221;, as it&#8217;s a little tricky. I&#8217;m working on official releases for Mac and Linux, and a Windows port is in the future; while I haven&#8217;t been coding towards it, I also have made sure to not choose anything that&#8217;s <i>completely</i> impossible for Win32.
</p>
<h2>Thoughts? Ideas? Comments? Want to help?</h2>
<p>
Since I&#8217;m always busy with work, it&#8217;s taken me quite a while to get to this point, and I&#8217;m definitely open to accepting contributions and making this a real open-source project; so far, I&#8217;ve set up Github and a <a href="http://xpaulbettsx.lighthouseapp.com/projects/11154-yikes/">bug tracker</a> (but no mailing list, forums, documentation, etc).  If you&#8217;re not handy with coding, websites, or art/design, I would even just appreciate suggestions or ideas for cool features. My Email address is paul at paulbetts dot org, let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2008/06/04/yikes-its-your-videos-on-your-ipod/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting a backtrace in Ruby</title>
		<link>http://blog.paulbetts.org/index.php/2007/12/25/getting-a-backtrace-in-ruby/</link>
		<comments>http://blog.paulbetts.org/index.php/2007/12/25/getting-a-backtrace-in-ruby/#comments</comments>
		<pubDate>Wed, 26 Dec 2007 04:20:49 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2007/12/25/getting-a-backtrace-in-ruby/</guid>
		<description><![CDATA[Here&#8217;s a handy trick I found while trying to practice more of &#8220;red-green-refactor&#8221;, a method that will dump the stack of every thread without halting the application. Note that this trick uses fork(), so Windows Rubyists are out in the cold (all three of them). /* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container {font-family: monospace;font-size: [...]]]></description>
			<content:encoded><![CDATA[<p>
Here&#8217;s a handy trick I found while trying to practice more of <a href="http://en.wikipedia.org/wiki/Test-driven_development#Test-Driven_Development_Cycle">&#8220;red-green-refactor&#8221;</a>, a method that will dump the stack of every thread <i>without</i> halting the application. Note that this trick uses <code>fork()</code>, so Windows Rubyists are out in the cold (all three of them).
</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color:#9966CC; font-weight:bold;}.ch_code_container .kw2 {color:#0000FF; font-weight:bold;}.ch_code_container .kw3 {color:#CC0066; font-weight:bold;}.ch_code_container .co1 {color:#008000; font-style:italic;}.ch_code_container .coMULTI {color:#000080; font-style:italic;}.ch_code_container .es0 {color:#000099;}.ch_code_container .br0 {color:#006600; font-weight:bold;}.ch_code_container .st0 {color:#996600;}.ch_code_container .nu0 {color:#006666;}.ch_code_container .me1 {color:#9900CC;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw1">def</span> dump_stacks<br />
&nbsp; &nbsp; <span class="kw3">fork</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ObjectSpace.<span class="me1">each_object</span><span class="br0">&#40;</span>Thread<span class="br0">&#41;</span> <span class="kw1">do</span> |th|<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; th.<span class="kw3">raise</span> Exception, <span class="st0">&quot;Stack Dump&quot;</span> <span class="kw1">unless</span> Thread.<span class="me1">current</span> == th<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">raise</span> Exception, <span class="st0">&quot;Stack Dump&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div>
<p>
This is courtesy of Robert Klemme, via the <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/164342">Ruby Talk mailing list</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2007/12/25/getting-a-backtrace-in-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A powerful UI programming metaphor from Aaron Hillegass</title>
		<link>http://blog.paulbetts.org/index.php/2007/09/22/a-powerful-ui-programming-metaphor-from-aaron-hillegass/</link>
		<comments>http://blog.paulbetts.org/index.php/2007/09/22/a-powerful-ui-programming-metaphor-from-aaron-hillegass/#comments</comments>
		<pubDate>Sat, 22 Sep 2007 18:38:11 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2007/09/22/a-powerful-ui-programming-metaphor-from-aaron-hillegass/</guid>
		<description><![CDATA[Once upon a time (before Baywatch), there was a man with no name. Knight Industries decided that if this man were given guns and wheels and booster rockets, he would be the perfect crime-fighting tool. First they thought, &#8220;Let&#8217;s subclass him and override everything we need to add the guns and wheels and booster rockets.&#8221; [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Once upon a time (before <i>Baywatch</i>), there was a man with no name. Knight Industries decided that if this man were given guns and wheels and booster rockets, he would be the perfect crime-fighting tool. First they thought, &#8220;Let&#8217;s subclass him and override everything we need to add the guns and wheels and booster rockets.&#8221; The problem was that to subclass Michael Knight, you would need to know an awful lot about his guts so that you could wire them to guns and booster rockets. So instead, they created a helper object, the Knight Industries 2000 Super Car, or &#8220;Kitt&#8221;.</p>
<p>Notice how this is different from the RoboCop approach. RoboCop was a man subclassed and extended. The whole RoboCop project involved dozens of surgeons who extended the man&#8217;s brain into a fighting machine. This is the approach taken with many object-oriented frameworks.</p>
<p>While approaching the perimeter of an arms dealer compound, Michael Knight would speak to Kitt over his watch-radio.  &#8220;Kitt&#8221;, he would say, &#8220;I need to get to the other side of that wall.&#8221; Kitt would then blast a big hole in the wall with a rocket. After destroying the wall, Kitt would return control to Michael, who would stroll through the rubble.
</p></blockquote>
<p><i> &#8211; from <a href="http://www.amazon.com/gp/redirect.html%3FASIN=0321213149%26tag=thurnigh-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0321213149%253FSubscriptionId=1N9AHEAQ2F6SVD97BE02">Cocoa Programming for Mac OS X</a>, by Aaron Hillegass</i></p>
<p>
Even if you don&#8217;t care about programming on the Mac, you should take a look because the developers at NeXT were really ahead of their time when they created the Cocoa framework. Objective C is like the &#8220;metal&#8221; version of Ruby, especially when you look at features in Obj-C like how their vtables are structured and their emphasis on introspection and mixins (called &#8220;categories&#8221; in Obj-C), and Cocoa takes full advantage of these features to make a really elegant, reusable UI framework.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2007/09/22/a-powerful-ui-programming-metaphor-from-aaron-hillegass/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>pathedit 0.1 &#8211; Change your filesystem using your favorite editor</title>
		<link>http://blog.paulbetts.org/index.php/2007/09/21/pathedit-01-change-your-filesystem-using-your-favorite-editor/</link>
		<comments>http://blog.paulbetts.org/index.php/2007/09/21/pathedit-01-change-your-filesystem-using-your-favorite-editor/#comments</comments>
		<pubDate>Fri, 21 Sep 2007 05:12:28 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2007/09/21/pathedit-01-change-your-filesystem-using-your-favorite-editor/</guid>
		<description><![CDATA[I read on one of the Planets about this idea, but I could never find the post so I reimplemented the idea in Ruby. The idea is, you can use a text editor to do mass file moves/renames/copies/etc. I wrote it to organize my downloaded TV shows, and it works pretty well and hasn&#8217;t eaten [...]]]></description>
			<content:encoded><![CDATA[<p>
I read on one of the Planets about this idea, but I could never find the post so I reimplemented the idea in Ruby. The idea is, you can use a text editor to do mass file moves/renames/copies/etc. I wrote it to organize my downloaded TV shows, and it works pretty well and hasn&#8217;t eaten any of my data yet. Of course, the standard caveats apply.
</p>
<p align="center">
<embed src="http://blog.paulbetts.org/wp-filez/PatheditDemo.mov" width=585 height=560 autoplay="false" /></p>
<div align="center"><i>People who are too lazy to read can now instead watch this window</i></div>
</p>
<p>
The utility reads paths from either standard input or passed as parameters. Here&#8217;s the output from <code>--help</code></p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;">Usage: pathedit <span class="br0">&#91;</span>options<span class="br0">&#93;</span> file1 file2 file3&#8230;<br />
If no files are given, the paths will be <span class="kw3">read</span> from standard input</p>
<p>Specific options:<br />
&nbsp; &nbsp; -a, &#8211;action <span class="kw3">type</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Action to perform <span class="br0">&#40;</span>one of <span class="st0">&#8216;copy&#8217;</span>, <span class="st0">&#8216;move&#8217;</span>, <span class="st0">&#8216;symlink&#8217;</span><span class="br0">&#41;</span></p>
<p>Common options:<br />
&nbsp; &nbsp; -d, &#8211;debug&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Run <span class="kw1">in</span> debug mode <span class="br0">&#40;</span>Extra messages<span class="br0">&#41;</span><br />
&nbsp; &nbsp; -v, &#8211;verbose&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Run verbosely<br />
&nbsp; &nbsp; -h, &#8211;<span class="kw3">help</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Show this message<br />
&nbsp; &nbsp; &nbsp; &nbsp; &#8211;version&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Show version</div>
</p>
<h2>Caveats for this version</h2>
<ul>
<li>Might give you problems on Windows unless you pass paths as parameters &#8211; soon to be fixed</li>
<li>Can only use GUI editors in Linux, cause that&#8217;s the only operating system that handles GUI apps <i>correctly</i> &#8211; hopefully I can fix this too</li>
</ul>
<h2>Download it!</h2>
<p><ul <li><a href="http://www.paulbetts.org/projects/pathedit-0.1.rb">pathedit-0.1.rb</a></ul></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2007/09/21/pathedit-01-change-your-filesystem-using-your-favorite-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://blog.paulbetts.org/wp-filez/PatheditDemo.mov" length="809771" type="video/quicktime" />
		</item>
		<item>
		<title>Qt4 Ruby and Metaprogramming 0.1 &#8211; Wiring up slots automatically</title>
		<link>http://blog.paulbetts.org/index.php/2007/09/08/qt4-ruby-and-metaprogramming-01-wiring-up-slots-automatically/</link>
		<comments>http://blog.paulbetts.org/index.php/2007/09/08/qt4-ruby-and-metaprogramming-01-wiring-up-slots-automatically/#comments</comments>
		<pubDate>Sun, 09 Sep 2007 03:20:14 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[QT/KDE]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2007/09/08/qt4-ruby-and-metaprogramming-01-wiring-up-slots-automatically/</guid>
		<description><![CDATA[In my attempts to learn Qt 4 and QtRuby, it&#8217;s pretty obvious that there&#8217;s a huge potential for doing Rails-like things, such as declaration by convention. To this end, here&#8217;s an example of what you can do with the code I&#8217;m writing: this loads a UI file and wires something up to the Open action: [...]]]></description>
			<content:encoded><![CDATA[<p>
In my attempts to learn Qt 4 and QtRuby, it&#8217;s pretty obvious that there&#8217;s a huge potential for doing Rails-like things, such as declaration by convention. To this end, here&#8217;s an example of what you can do with the code I&#8217;m writing: this loads a UI file and wires something up to the Open action:
</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color:#9966CC; font-weight:bold;}.ch_code_container .kw2 {color:#0000FF; font-weight:bold;}.ch_code_container .kw3 {color:#CC0066; font-weight:bold;}.ch_code_container .co1 {color:#008000; font-style:italic;}.ch_code_container .coMULTI {color:#000080; font-style:italic;}.ch_code_container .es0 {color:#000099;}.ch_code_container .br0 {color:#006600; font-weight:bold;}.ch_code_container .st0 {color:#996600;}.ch_code_container .nu0 {color:#006666;}.ch_code_container .me1 {color:#9900CC;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw3">require</span> &#8216;Qt&#8217;</p>
<p><span class="kw1">class</span> ActionOpenHandler &lt; Qt::Object<br />
&nbsp; &nbsp; slots <span class="st0">&quot;on_activated()&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> initialize<span class="br0">&#40;</span>main = <span class="kw2">nil</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">super</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @main = main<br />
&nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> on_activated<br />
&nbsp; &nbsp; &nbsp; &nbsp; path = <span class="kw2">nil</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Qt::FileDialog.<span class="me1">new</span> <span class="kw1">do</span> |fd|<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; path = fd.<span class="me1">get_open_file_name</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">return</span> <span class="kw1">unless</span> path</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; text = <span class="kw2">nil</span>;&nbsp;File.<span class="kw3">open</span><span class="br0">&#40;</span>path, &#8216;r&#8217;<span class="br0">&#41;</span> <span class="br0">&#123;</span>|f| text = f.<span class="me1">read</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @main.<span class="me1">findChild</span><span class="br0">&#40;</span>Qt::TextEdit, <span class="st0">&quot;textBrowser&quot;</span><span class="br0">&#41;</span>.<span class="me1">text</span> = text<br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></p>
<p>a = Qt::Application.<span class="me1">new</span><span class="br0">&#40;</span>ARGV<span class="br0">&#41;</span><br />
QtSuperLoader.<span class="me1">new</span>.<span class="me1">initialize_and_hook</span><span class="br0">&#40;</span><span class="st0">&quot;./main.ui&quot;</span><span class="br0">&#41;</span>.<span class="me1">show</span><br />
a.<span class="kw3">exec</span></div>
<p>
Next, I&#8217;m seeking to replace the ugly line <code>"@main.findChild(Qt::TextEdit, "textBrowser").text = text"</code> with the more palatable <code>"@main.text_browser.text = text"</code>. However, this is a bit more tricky, because findChild creates strongly-typed objects &#8211; there may be some trickery to get around it though involving QMetaObject.
</p>
<p>
Here&#8217;s the files, including the code that supports it all: <a href="http://www.paulbetts.org/projects/qttest.rb">qttest.rb</a> and <a href="http://www.paulbetts.org/projects/Translator.ui">Translator.ui</a>
</p>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2007/09/08/qt4-ruby-and-metaprogramming-01-wiring-up-slots-automatically/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Extracting a zip file in Ruby</title>
		<link>http://blog.paulbetts.org/index.php/2007/07/29/extracting-a-zip-file-in-ruby/</link>
		<comments>http://blog.paulbetts.org/index.php/2007/07/29/extracting-a-zip-file-in-ruby/#comments</comments>
		<pubDate>Sun, 29 Jul 2007 08:21:19 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2007/07/29/extracting-a-zip-file-in-ruby/</guid>
		<description><![CDATA[I just spent like 2 hours trying to get this damn piece of code to work &#8211; trying to extract a zip file to a temporary directory. Most of my problems were because of the lack of documentation in rubyzip, but the end result appears to work. Here it is, obviously you need the abovementioned [...]]]></description>
			<content:encoded><![CDATA[<p>I just spent like 2 hours trying to get this damn piece of code to work &#8211; trying to extract a zip file to a temporary directory. Most of my problems were because of the lack of documentation in <code>rubyzip</code>, but the end result appears to work. Here it is, obviously you need the abovementioned library from Rubygems. </p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:300px;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color:#9966CC; font-weight:bold;}.ch_code_container .kw2 {color:#0000FF; font-weight:bold;}.ch_code_container .kw3 {color:#CC0066; font-weight:bold;}.ch_code_container .co1 {color:#008000; font-style:italic;}.ch_code_container .coMULTI {color:#000080; font-style:italic;}.ch_code_container .es0 {color:#000099;}.ch_code_container .br0 {color:#006600; font-weight:bold;}.ch_code_container .st0 {color:#996600;}.ch_code_container .nu0 {color:#006666;}.ch_code_container .me1 {color:#9900CC;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:300px;"><span class="br0">&#91;</span>&#8216;rubygems&#8217;, &#8216;pathname&#8217;, &#8216;zip/zip&#8217;<span class="br0">&#93;</span>.<span class="me1">each</span> <span class="br0">&#123;</span>|x| <span class="kw3">require</span> x<span class="br0">&#125;</span></p>
<p>UUIDchars = <span class="br0">&#40;</span><span class="st0">&quot;a&quot;</span>..<span class="st0">&quot;f&quot;</span><span class="br0">&#41;</span>.<span class="me1">to_a</span> + <span class="br0">&#40;</span><span class="st0">&quot;0&quot;</span>..<span class="st0">&quot;9&quot;</span><span class="br0">&#41;</span>.<span class="me1">to_a</span><br />
<span class="kw1">def</span> uuid_seg<span class="br0">&#40;</span>len<span class="br0">&#41;</span><br />
&nbsp; ret = <span class="st0">&quot;&quot;</span><br />
&nbsp; <span class="nu0">1</span>.<span class="me1">upto</span><span class="br0">&#40;</span>len<span class="br0">&#41;</span> <span class="br0">&#123;</span> |i| ret &lt; &lt; UUIDchars<span class="br0">&#91;</span><span class="kw3">rand</span><span class="br0">&#40;</span>UUIDchars.<span class="me1">size</span><span class="nu0">-1</span><span class="br0">&#41;</span><span class="br0">&#93;</span> <span class="br0">&#125;</span>; ret<br />
<span class="kw1">end</span></p>
<p><span class="kw1">def</span> random_uuid<br />
&nbsp; <span class="st0">&quot;#{uuid_seg(8)}-#{uuid_seg(4)}-#{uuid_seg(4)}-#{uuid_seg(4)}-#{uuid_seg(12)}&quot;</span><br />
<span class="kw1">end</span></p>
<p><span class="kw1">def</span> extract_zip_to_tempdir<span class="br0">&#40;</span>zip_path<span class="br0">&#41;</span><br />
&nbsp; temp_root = Pathname.<span class="me1">new</span><span class="br0">&#40;</span><span class="br0">&#40;</span>ENV<span class="br0">&#91;</span>&#8216;TEMP&#8217;<span class="br0">&#93;</span> || ENV<span class="br0">&#91;</span>&#8216;TMP&#8217;<span class="br0">&#93;</span> || &#8216;/tmp&#8217;<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; <span class="kw3">raise</span> <span class="st0">&quot;Can&#8217;t find a temp directory&quot;</span> <span class="kw1">unless</span> temp_root.<span class="me1">exist</span>?</p>
<p>&nbsp; <span class="co1"># Figure out our temp directory</span><br />
&nbsp; temp_dir = <span class="kw2">nil</span><br />
&nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>temp_dir = temp_root.<span class="me1">join</span><span class="br0">&#40;</span>random_uuid<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>.<span class="me1">exist</span>?<br />
&nbsp; &nbsp; <span class="kw2">nil</span><br />
&nbsp; <span class="kw1">end</span><br />
&nbsp; temp_dir.<span class="me1">mkpath</span></p>
<p>&nbsp; ZipFile.<span class="kw3">open</span><span class="br0">&#40;</span>zip_path<span class="br0">&#41;</span> <span class="kw1">do</span> |zf|<br />
&nbsp; &nbsp; zf.<span class="me1">each</span> <span class="kw1">do</span> |e| <br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>m = /^<span class="br0">&#40;</span>.<span class="me1">*</span><span class="br0">&#41;</span><span class="br0">&#91;</span>\\\/<span class="br0">&#93;</span><span class="br0">&#91;</span>^\\\/<span class="br0">&#93;</span>*$/.<span class="me1">match</span><span class="br0">&#40;</span>e.<span class="me1">name</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; temp_dir.<span class="me1">join</span><span class="br0">&#40;</span>m<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">mkpath</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; zf.<span class="me1">extract</span><span class="br0">&#40;</span>e.<span class="me1">name</span>, File.<span class="me1">join</span><span class="br0">&#40;</span>temp_dir.<span class="me1">to_s</span>, e.<span class="me1">name</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">end</span></p>
<p>&nbsp; temp_dir.<span class="me1">to_s</span><br />
<span class="kw1">end</span></div>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2007/07/29/extracting-a-zip-file-in-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t worry, I haven&#8217;t forgotten QtRuby on Win32!</title>
		<link>http://blog.paulbetts.org/index.php/2007/07/22/dont-worry-i-havent-forgotten-qtruby-on-win32/</link>
		<comments>http://blog.paulbetts.org/index.php/2007/07/22/dont-worry-i-havent-forgotten-qtruby-on-win32/#comments</comments>
		<pubDate>Mon, 23 Jul 2007 01:32:45 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[QT/KDE]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2007/07/22/dont-worry-i-havent-forgotten-qtruby-on-win32/</guid>
		<description><![CDATA[I was planning on posting the same kind of tutorial for Win32 for using QtRuby, but I&#8217;m currently stuck as to how to get it to build. After fighting with random build glitches for three hours or so (making progress, slowly), I&#8217;m currently stuck here: /* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container {font-family: monospace;font-size: [...]]]></description>
			<content:encoded><![CDATA[<p>
I was planning on posting the same kind of tutorial for Win32 for using QtRuby, but I&#8217;m currently stuck as to how to get it to build. After fighting with random build glitches for three hours or so (making progress, slowly), I&#8217;m currently stuck here:</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;">Compiled with:<br />
C:/MinGW/bin/g++.exe&nbsp; &nbsp;-IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtDBus -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtTest<br />
&nbsp;-IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtUiTools -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtScript -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/<span class="kw1">in</span><br />
clude/QtSvg -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtXml -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtSql -IC:/Qt/<span class="nu0">4.3</span>.<br />
<span class="nu0">0</span>/include/QtOpenGL -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtNetwork -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtDesig<br />
ner -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtDesigner -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtAssistant -IC:/Qt/<span class="nu0">4</span><br />
.<span class="nu0">3.0</span>/include/Qt3Support -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtGui -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/QtCore<br />
&nbsp;-IC:\Qt\<span class="nu0">4.3</span><span class="nu0">.0</span>\mkspecs/default -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include/Qt -IC:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/include&nbsp; C<br />
:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQtCore4.a C:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQtNetwork4.a C:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQ<br />
tSql4.a C:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQtXml4.a C:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQtGui4.a C:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/<br />
libQtUiTools.a C:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQtSvg4.a C:/Qt/<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQtOpenGL4.a C:/Qt/<br />
<span class="nu0">4.3</span><span class="nu0">.0</span>/lib/libQt3Support4.a&nbsp; -o C:\Users\paulbe\AppData\Local\Temp/<span class="nu0">3428</span>-qtguess C<br />
:\Users\paulbe\AppData\Local\Temp/<span class="nu0">3428</span>-qtguess.cpp<br />
Compiler output:<br />
C:\Users\paulbe\AppData\Local\Temp/<span class="nu0">3428</span>-qtguess.cpp:<span class="nu0">8</span>:<span class="nu0">2</span>: warning: no newline at<br />
end of file<br />
C:\Users\paulbe\AppData\Local\Temp/ccMxaaaa.o<span class="br0">&#40;</span>.text+0&#215;147<span class="br0">&#41;</span>:<span class="nu0">3428</span>-qtguess.cpp: <br />
undefined reference to `_imp___ZN12QApplicationC1ERiPPci<span class="st0">&#8216;<br />
C:<span class="es0">\U</span>sers<span class="es0">\p</span>aulbe<span class="es0">\A</span>ppData<span class="es0">\L</span>ocal<span class="es0">\T</span>emp/ccMxaaaa.o(.text+0&#215;154):3428-qtguess.cpp: <br />
undefined reference to `QApplication::~QApplication()&#8217;</span><br />
collect2: ld returned <span class="nu0">1</span> <span class="kw3">exit</span> status</div>
<p>Thoughts? It looks like I&#8217;ve got some sort of compiler mismatch (one library compiled with MSVC and one compiled with MinGW, probably). I have no idea where though, I&#8217;m 85% sure that Qt is compiled with MinGW
</p>
<p><b>Update:</b> Alright, the new plan is to compile everything from scratch, and see if I can get some better results.</p>
<p><b>Update 2:</b> It&#8217;s definitely the compiler difference:</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;">&gt; objdump -x C:\Qt\<span class="nu0">4.3</span><span class="nu0">.0</span>\lib\libQtGui4.a</p>
<p><span class="br0">&#123;</span> Snip! <span class="br0">&#125;</span></p>
<p>SYMBOL TABLE:<br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 .text<br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">2</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 .idata$<span class="nu0">7</span><br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 .idata$<span class="nu0">5</span><br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">4</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 .idata$<span class="nu0">4</span><br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">4</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">5</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 .idata$<span class="nu0">6</span><br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">5</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 __ZN12QApplicationC2ERiPPci<br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">6</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 __imp___ZN12QApplicationC2ERiPPci<br />
<span class="br0">&#91;</span>&nbsp; <span class="nu0">7</span><span class="br0">&#93;</span><span class="br0">&#40;</span>sec&nbsp; <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>fl 0&#215;00<span class="br0">&#41;</span><span class="br0">&#40;</span>ty&nbsp; &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#40;</span>scl&nbsp; &nbsp;<span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>nx <span class="nu0">0</span><span class="br0">&#41;</span> 0&#215;00000000 __head_QtGui4_dll</div>
<p> The compiler&#8217;s looking for <code>__imp___ZN12QApplicationC1ERiPPci</code>, but the precompiled library has C2. I don&#8217;t understand why Qt&#8217;s distributing a busted library &#8211; this would break even their samples in straight C++ &#8211; it&#8217;s possible that Mingw updated behind their back though.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2007/07/22/dont-worry-i-havent-forgotten-qtruby-on-win32/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cross-platform UI with Qt4 and Ruby &#8211; Mac/Linux HOWTO</title>
		<link>http://blog.paulbetts.org/index.php/2007/07/22/cross-platform-ui-with-qt4-and-ruby-maclinux-howto/</link>
		<comments>http://blog.paulbetts.org/index.php/2007/07/22/cross-platform-ui-with-qt4-and-ruby-maclinux-howto/#comments</comments>
		<pubDate>Sun, 22 Jul 2007 23:03:41 +0000</pubDate>
		<dc:creator>Paul Betts</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[QT/KDE]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.paulbetts.org/index.php/2007/07/22/cross-platform-ui-with-qt4-and-ruby-maclinux-howto/</guid>
		<description><![CDATA[Today I&#8217;ve spent the day working on figuring out how to make UIs using Ruby and Qt4. If you haven&#8217;t heard of it, Qt4 is an awesome UI framework written in C++. Since C++ is way too much work, some great KDE devs wrote a bindings generator for Qt4 called qt4-qtruby. While this package is [...]]]></description>
			<content:encoded><![CDATA[<p>
Today I&#8217;ve spent the day working on figuring out how to make UIs using Ruby and Qt4. If you haven&#8217;t heard of it, <a href="http://trolltech.com/products/qt">Qt4<a /> is an awesome UI framework written in C++. Since C++ is way too much work, some great KDE devs wrote a bindings generator for Qt4 called </a><a href="http://developer.kde.org/language-bindings/ruby/index.html">qt4-qtruby</a>. While this package is fairly &#8220;linuxy&#8221;, it&#8217;s pretty easy to build it on Mac OS X too, making it possible to write GUI programs for OS X without having to delve into RubyCocoa which has too much hackiness (in my opinion), or even worse, Objective C. Furthermore, your code that you write on OS X will look great on Windows and Linux too!
</p>
<h2>Starting from scratch</h2>
<p>
First, install Ruby. If you&#8217;re using Linux, you&#8217;ll probably use the package manager to install Ruby <b>and the Ruby development libraries!</b> (Ubuntu will run <code>sudo apt-get install ruby irb ruby-dev</code>) OS X Tiger ships with Ruby by default, but you&#8217;ll want to install an updated version, via the <a href="http://rubyosx.rubyforge.org/">Ruby one-click installer</a>, then disable the old Ruby by using the following command:</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="co1">## Only do this on Mac! Linux doesn&#8217;t need this nonsense ##</span><br />
touch ~/.bashrc &amp;&amp; <span class="kw3">echo</span> <span class="st0">&#8216;export PATH=&quot;/usr/local/bin:$PATH&quot;&#8217;</span> &gt;&gt; ~/.bashrc<br />
sudo mv /usr/lib/libruby<span class="nu0">.1</span>.dylib /usr/lib/_libruby<span class="nu0">.1</span>.dylib</div>
</p>
<h2>Installing Qt4 and QtRuby</h2>
<p>
First, install Qt4 by using your package manager on Linux (in Ubuntu, use the <code>-kdecopy</code> packages, they are more up to date), or by downloading the DMG from the <a href="http://trolltech.com/developer/downloads/qt/mac">Qt/Mac Open Source Edition Download</a> page. You&#8217;ll also need <a href="http://www.macports.org/">MacPorts</a> (and by proxy, the XCode tools). Also, download the <a href="http://rubyforge.org/frs/?group_id=181&#038;release_id=12479">Qt4 Ruby bindings source code</a> from Rubyforge and save it to the Desktop.
</p>
<p>
Here&#8217;s the cool thing about QtRuby, and the advantage of building it from source: the build framework for QtRuby scans through whatever version of Qt you have installed, and <i>dynamically</i> builds the bindings. This means, there&#8217;s no waiting for new Qt features to be available in Ruby, it&#8217;s always up-to-date! Which is quite handy, because it seems like every minor version of Qt has new cool stuff.
</p>
<p>
Next, we have to do a bit of hackery &#8211; unfortunately, there&#8217;s no easy way to install QtRuby but it&#8217;s not so hard. Here&#8217;s what you&#8217;ll run:</p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color: #b1b100;}.ch_code_container .kw3 {color: #000066;}.ch_code_container .co1 {color: #808080; font-style: italic;}.ch_code_container .es0 {color: #000099; font-weight: bold;}.ch_code_container .br0 {color: #66cc66;}.ch_code_container .st0 {color: #ff0000;}.ch_code_container .nu0 {color: #cc66cc;}.ch_code_container .re0 {color: #0000ff;}.ch_code_container .re1 {color: #0000ff;}.ch_code_container .re2 {color: #0000ff;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw3">cd</span> ~/Desktop<br />
sudo port install cmake&nbsp; &nbsp;<span class="co1">## CMake is a cool build system</span><br />
tar -xzvf qt4-qtruby<span class="nu0">-1.4</span><span class="nu0">.9</span>.tgz &amp;&amp; <span class="kw3">cd</span> ./qt4-qtruby<span class="nu0">-1.4</span><span class="nu0">.9</span><br />
cmake .<br />
make &amp;&amp; sudo make install</div>
</p>
<h2>Try it out!</h2>
<p>
Once you&#8217;ve got it built, try this sample code to see some of the new features in Qt 4.3 &#8211; this code will run a natively-styled wizard in Windows, Mac, and Linux without any changes! Unfortunately, this code isn&#8217;t very elegant or Ruby-like, but it&#8217;s a base that someone could write a really elegant UI framework over like RoR. </p>
<style type="text/css">/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */.ch_code_container  {font-family: monospace;font-size: 10pxheight:100%;}.ch_code_container .imp {font-weight: bold; color: red;}.ch_code_container .kw1 {color:#9966CC; font-weight:bold;}.ch_code_container .kw2 {color:#0000FF; font-weight:bold;}.ch_code_container .kw3 {color:#CC0066; font-weight:bold;}.ch_code_container .co1 {color:#008000; font-style:italic;}.ch_code_container .coMULTI {color:#000080; font-style:italic;}.ch_code_container .es0 {color:#000099;}.ch_code_container .br0 {color:#006600; font-weight:bold;}.ch_code_container .st0 {color:#996600;}.ch_code_container .nu0 {color:#006666;}.ch_code_container .me1 {color:#9900CC;}</style>
<div class="ch_code_container" style="font-family: monospace;font-size: 10pxheight:100%;"><span class="kw3">require</span> &#8216;Qt&#8217;<br />
a = Qt::Application.<span class="me1">new</span><span class="br0">&#40;</span>ARGV<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> create_intro_page<br />
&nbsp; &nbsp; &nbsp; &nbsp; page = Qt::WizardPage.<span class="me1">new</span> <span class="kw1">do</span> |p|<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">p</span>.<span class="me1">title</span> = <span class="st0">&quot;Introduction&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; label = Qt::Label.<span class="me1">new</span><span class="br0">&#40;</span><span class="st0">&quot;This is a wizard!&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; label.<span class="me1">word_wrap</span> = <span class="kw2">true</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; layout = Qt::VBoxLayout.<span class="me1">new</span> <span class="kw1">do</span> |v|<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v.<span class="me1">add_widget</span><span class="br0">&#40;</span>label<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; page.<span class="me1">layout</span> = layout<br />
&nbsp; &nbsp; &nbsp; &nbsp; page<br />
<span class="kw1">end</span></p>
<p>wiz = Qt::Wizard.<span class="me1">new</span> <span class="kw1">do</span> |x|<br />
&nbsp; &nbsp; &nbsp; &nbsp; x.<span class="me1">add_page</span><span class="br0">&#40;</span>create_intro_page<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; x.<span class="me1">set_window_title</span><span class="br0">&#40;</span><span class="st0">&quot;Test Wizard&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; x.<span class="me1">show</span><br />
<span class="kw1">end</span></p>
<p>a.<span class="kw3">exec</span></div>
</p>
<p align="center">
<table>
<tr>
<td align="center">
<a href="http://blog.paulbetts.org/wp-photos/WizardOSX.png"><img src="http://blog.paulbetts.org/wp-photos/WizardOSX_Small.png" /></a><br />
<i>On Mac OS X</i>
</td>
<td align="center">
<a href="http://blog.paulbetts.org/wp-photos/WizardLinux.png"><img src="http://blog.paulbetts.org/wp-photos/WizardLinux_Small.png" /></a><br />
<i>On Linux</i>
</td>
</tr>
</table>
<h2>In summary:</h2>
<ol>
<li>Install a Ruby that doesn&#8217;t suck, and hack your environment so it works right</li>
<li>Install Qt and MacPorts</li>
<li>Build QtRuby and install it</li>
<li>Make UIs for all 3 platforms without hating your life</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.paulbetts.org/index.php/2007/07/22/cross-platform-ui-with-qt4-and-ruby-maclinux-howto/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

