<?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>The Bark Blog &#187; Ruby</title>
	<atom:link href="http://bark.metacasa.net/category/geekery/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://bark.metacasa.net</link>
	<description>Random musings from the earthy depths.</description>
	<lastBuildDate>Tue, 02 Mar 2010 18:23:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Flaming Hoops: Rails Logging Tricks</title>
		<link>http://bark.metacasa.net/2007/02/12/flaming-hoops-rails-logging-tricks/</link>
		<comments>http://bark.metacasa.net/2007/02/12/flaming-hoops-rails-logging-tricks/#comments</comments>
		<pubDate>Mon, 12 Feb 2007 13:11:13 +0000</pubDate>
		<dc:creator>Umberdog</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://bark.metacasa.net/2007/02/12/flaming-hoops-rails-logging-tricks/</guid>
		<description><![CDATA[Many people enjoy the sideshow carnival cliche of mammals jumping through flaming hoops.  It&#8217;s quick, it&#8217;s fun, and it invokes a harmless façade of danger.  In that vein, this new series of hoop-vaulting articles will push against the bumper-guards of the average Ruby on Rails playground, exploring faux danger and hopefully providing some [...]]]></description>
			<content:encoded><![CDATA[<p>Many people enjoy the sideshow carnival cliche of mammals jumping through flaming hoops.  It&#8217;s quick, it&#8217;s fun, and it invokes a harmless façade of danger.  In that vein, this new series of hoop-vaulting articles will push against the bumper-guards of the average Ruby on Rails playground, exploring faux danger and hopefully providing some light entertainment.</p>

<p>This first batch of tips fiddles with unit test logging by tweaking the <code>test/unit/test_helper.rb</code> file.  By default, when you run <code>rake test:units</code> from the top level directory of your Rails application, all logging output goes into <code>log/test.log</code>.  If that&#8217;s not good enough, if you want a different name or location for your test output, the change is easy.  Add this to the end of <code>test_helper.rb</code>:</p>

<p>TESTLOG = File.expand<em>path(&#8221;#{RAILS</em>ROOT}/log/flamey-test.log&#8221;)
ActiveRecord::Base.logger = Logger.new(TESTLOG)</p>

<p>If you&#8217;re writing a standalone ActiveRecord application outside of a Rails environment, you&#8217;ll have to explicitly create and assign a logger yourself.  The easiest solution is to pass <code>Logger.new</code> a simple file name.</p>

<p>ActiveRecord::Base.logger = Logger.new(&#8221;test.log&#8221;)</p>

<p>Unfortunately this will drop the log file into whichever relative directory you run the tests from.  What you probably want is to anchor it to the <code>test_helper.rb</code> file (which you&#8217;ll also have to create yourself in a standalone application).</p>

<p>TESTLOG = File.expand_path(File.dirname(<strong>FILE</strong>) + &#8220;/test.log&#8221;)
ActiveRecord::Base.logger = Logger.new(TESTLOG)</p>

<p>A slightly better place is in a <code>log</code> directory, sibling to the test directory:</p>

<p>TESTLOG = File.expand_path(File.dirname(<strong>FILE</strong>) + &#8220;/../log/test.log&#8221;)
ActiveRecord::Base.logger = Logger.new(TESTLOG)</p>

<p>More tips on the flip side&#8230;</p>

<p><span id="more-23"></span></p>

<p>Another handy hoop trick is to provide a command-line switch for STDOUT logging.  To send output to a file, invoke your tests as normal; to send output to the console, set LOG_STDOUT in your environment to anything, e.g. <code>LOG_STDOUT=yes ruby test/my_test.rb</code>.</p>

<p>TESTLOG = File.expand<em>path(File.dirname(<strong>FILE</strong>) + &#8220;/test.log&#8221;)
ActiveRecord::Base.logger = ENV["LOG</em>STDOUT"] ?
Logger.new(STDOUT) : Logger.new(TESTLOG)</p>

<p>Of course, there&#8217;s always the lower level logging properties.  To turn off the special color markup (who on earth made that the default?!?):</p>

<p>ActiveRecord::Base.colorize_logging = false</p>

<p>To filter the logging output by severity level:</p>

<p>ActiveRecord::Base.logger.level = Logger::INFO</p>

<p>And finally, this line tags the log file (or console output) with a friendly banner whenever the <code>test_helper.rb</code> file is loaded, which amounts to every time you run the tests:</p>

<p>ActiveRecord::Base.logger.info(
&#8220;#{&#8221;=&#8221;<em>25} RUNNING UNIT TESTS #{&#8221;=&#8221;</em>25}\n\t\t\t#{Time.now.to_s}\n#{&#8221;=&#8221;*70}&#8221;)</p>

<p>It looks like this:</p>

<p>========================= RUNNING UNIT TESTS =========================</p>

<h1>Mon Feb 12 10:39:50 CST 2007</h1>

<p>Have fun, and stay tuned for the next Hoop o&#8217; fire.</p>
]]></content:encoded>
			<wfw:commentRss>http://bark.metacasa.net/2007/02/12/flaming-hoops-rails-logging-tricks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nginx at 10,000 Feet</title>
		<link>http://bark.metacasa.net/2007/02/11/nginx-at-10000-feet/</link>
		<comments>http://bark.metacasa.net/2007/02/11/nginx-at-10000-feet/#comments</comments>
		<pubDate>Mon, 12 Feb 2007 00:37:52 +0000</pubDate>
		<dc:creator>Umberdog</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://bark.metacasa.net/2007/02/11/nginx-at-10000-feet/</guid>
		<description><![CDATA[Lately, five letters have begun to rattle around the Ruby on Rails universe with increasing frequency: nginx (allegedly pronounced &#8220;engine x&#8221;).  This new toy is a reverse proxy HTTP server that can serve as a high-performance, lightweight replacement for Apache.  In particular, it works well as a load-balancing front end for a Mongrel [...]]]></description>
			<content:encoded><![CDATA[<p>Lately, five letters have begun to rattle around the Ruby on Rails universe with increasing frequency: <a href="http://wiki.codemongers.com/Nginx">nginx</a> (allegedly pronounced &#8220;engine x&#8221;).  This new toy is a <a href="http://en.wikipedia.org/wiki/Reverse_proxy">reverse proxy</a> HTTP server that can serve as a high-performance, lightweight replacement for Apache.  In particular, it works well as a load-balancing front end for a <a href="http://mongrel.rubyforge.org">Mongrel</a> cluster running a Ruby on Rails application.</p>

<p><a href="http://wiki.codemongers.com/NginxWhyUseIt">According to one elated nginx user</a>:</p>

<blockquote>
  <p>The only solution I know of that&#8217;s extremely high performance that offers all of the features that you want is Nginx&#8230; I currently have Nginx doing reverse proxy of over tens of millions of HTTP requests per day (thats a few hundred per second) on a single server. At peak load it uses about 15MB RAM and 10% CPU on my particular configuration (FreeBSD 6).</p>
  
  <p>Under the same kind of load, Apache falls over (after using 1000 or so processes and god knows how much RAM), Pound falls over (too many threads, and using 400MB+ of RAM for all the thread stacks), and Lighty leaks more than 20MB per hour (and uses more CPU, but not significantly more).</p>
</blockquote>

<p>It does seem like a lean, powerful solution for sites that control their entire technology stack; of course, it doesn&#8217;t help those of us on shared hosting providers like <a href="http://dreamhost.com/">Dreamhost</a> who must wait for the admins to carefully and excruciatingly evaluate each new service they roll out.</p>

<p>A quick Googlry turns up quite a few articles on nginx:</p>

<ul>
<li><p><a href="http://brainspl.at/articles/2006/08/23/nginx-my-new-favorite-front-end-for-mongrel-cluster">&#8220;Nginx, my new favorite front end for mongrel cluster&#8221;</a> by Ezra Zygmuntowicz</p></li>
<li><p><a href="http://blog.kovyrin.net/2006/08/22/high-performance-rails-nginx-lighttpd-mongrel">&#8220;High-Performance Ruby On Rails Setups Test: mongrel vs lighttpd vs nginx&#8221;</a> and <a href="http://blog.kovyrin.net/category/web-tech/nginx/">many other nginx articles</a> by Alexey N. Kovyrin</p></li>
<li><p><a href="http://blog.labratz.net/articles/2006/10/03/rails-deployment-apache-lighttpd-nginx-mongrel-cluster">&#8220;(Rails Deployment &#8211; Apache &#8211; Lighttpd) + Nginx &amp; Mongrel Cluster&#8221;</a> by LabRat</p></li>
<li><p><a href="http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/">&#8220;Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You&#8221;</a> by Coda Hale</p></li>
<li><p><a href="http://blog.integralimpressions.com/articles/2006/08/30/nginx-the-front-end-solution-for-rails-deployment">&#8220;nginx: the front end solution for rails deployment?&#8221;</a> by Dominic Damian</p></li>
</ul>

<p>If you&#8217;re able, I&#8217;d highly recommend checking it out.  On the other hand, if you&#8217;re one of the poor, lonely stack-impaired minions like myself, maybe you can wring a few drops of vicariousness from the gushy victory stories above.</p>
]]></content:encoded>
			<wfw:commentRss>http://bark.metacasa.net/2007/02/11/nginx-at-10000-feet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing Rails Model Plugins</title>
		<link>http://bark.metacasa.net/2007/02/07/testing-rails-model-plugins/</link>
		<comments>http://bark.metacasa.net/2007/02/07/testing-rails-model-plugins/#comments</comments>
		<pubDate>Wed, 07 Feb 2007 22:49:51 +0000</pubDate>
		<dc:creator>Umberdog</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://bark.metacasa.net/2007/02/07/testing-rails-model-plugins/</guid>
		<description><![CDATA[Extending your Ruby on Rails application with a plugin is very simple: run the code generator to create the template code, then drizzle your yummy application and test code into the supplied directories.  Rails automatically adds all plugin lib directories to the $LOAD_PATH.  Add a class to your plugin and your Rails application [...]]]></description>
			<content:encoded><![CDATA[<p>Extending your Ruby on Rails application with a plugin is very simple: run the code generator to create the template code, then drizzle your yummy application and test code into the supplied directories.  Rails automatically adds all plugin <code>lib</code> directories to the <code>$LOAD_PATH</code>.  Add a class to your plugin and your Rails application can start using it immediately.  You don&#8217;t even need a <code>require</code> statement.  This is the same mechanism that auto-loads model classes in the <code>app/models</code> directory.</p>

<p>This works nicely for the plugin&#8217;s <code>lib</code> directory, but what about its <code>test</code> directory?  Unfortunately, by default plugin tests are pretty bland.  They use the plain unit test suite supplied by Ruby, and not any of the extended Rails test framework.  This will leave our plugin&#8217;s test classes with no access to fixtures, <code>database.yml</code> configuration, or any of those nice class auto-loading features.</p>

<p>Fear not!  It&#8217;s easy to wire the full Rails model testing framework into any plugin.  Details below&#8230;.</p>

<p><span id="more-20"></span></p>

<p>(continued)</p>

<p>To get us started, let&#8217;s generate stubs for our imaginary SkinnyFeet plugin:</p>

<blockquote>
  <p>script/generate plugin skinny<em>feet
  create  vendor/plugins/skinny</em>feet/lib
  create  vendor/plugins/skinny<em>feet/tasks
  create  vendor/plugins/skinny</em>feet/test
  create  vendor/plugins/skinny<em>feet/README
  create  vendor/plugins/skinny</em>feet/Rakefile
  create  vendor/plugins/skinny<em>feet/init.rb
  create  vendor/plugins/skinny</em>feet/install.rb
  create  vendor/plugins/skinny<em>feet/uninstall.rb
  create  vendor/plugins/skinny</em>feet/lib/skinny<em>feet.rb
  create  vendor/plugins/skinny</em>feet/tasks/skinny<em>feet</em>tasks.rake
  create  vendor/plugins/skinny<em>feet/test/skinny</em>feet_test.rb</p>
</blockquote>

<p>The generated test stub is boring as rocks, and completely devoid of Rails-ness:</p>

<h1>vendor/plugins/skinny<em>feet/test/skinny</em>feet_test.rb</h1>

<p>require &#8216;test/unit&#8217;</p>

<p>class SkinnyFeetTest &lt; Test::Unit::TestCase</p>

<h1>Replace this with your real tests.</h1>

<p>def test<em>this</em>plugin
flunk
end
end</p>

<p>In a test file generated by Rails for a model class, the <code>${RAILS_ROOT}/test/test_helper.rb</code> file pulls in the Rails environment.  In theory, we could reference that application helper file from the plugin, but that&#8217;s a bit ugly and dangerous.  Our fancy plugin might someday reside in random applications.  We have no idea what dastardly hacks they&#8217;ve done to their own <code>test_helper.rb</code> file.  We certainly don&#8217;t want the application test suite to break our plugin test suite.</p>

<p>Let&#8217;s be safe and create our own test helper class inside the plugin.  The minimum we need is the first three lines of the default generated <code>test_helper.rb</code> file.  Note that we have to extend the path to <code>environment.rb</code> by three levels since we&#8217;re nested deep in the vendor directory.</p>

<h1>vendor/plugins/skinny<em>feet/test/test</em>helper.rb</h1>

<p>ENV["RAILS<em>ENV"] = &#8220;test&#8221;
require File.expand</em>path(File.join(File.dirname(<strong>FILE</strong>),
&#8216;../../../../config/environment&#8217;))
require &#8216;test_help&#8217;</p>

<p>Then in each database-hammering plugin test file, replace the <code>require 'test/unit'</code> statement at the top with:</p>

<h1>vendor/plugins/skinny<em>feet/test/whichever</em>test.rb</h1>

<p>require File.dirname(<strong>FILE</strong>) + &#8216;/test_helper&#8217;</p>

<p>With this simple change, our plugin gains access to everything we&#8217;ve been missing: the application&#8217;s <code>database.yml</code> file, the fixtures directory, and the auto-loading feature.  We can now start using classes we&#8217;ve implemented in our plugin <code>lib</code> directory without bothering with <code>require</code> statements (as long as we follow the proper Rails file-naming conventions).</p>

<p>Also, the <code>fixtures</code> directive should work to load data fixtures into the database for testing &#8212; except it&#8217;ll grab those fixture files from the default application directory at <code>${RAILS_ROOT}/test/fixtures/</code>.  Instead, we want to create our own fixtures directory inside our plugin, at <code>vendor/plugin/skinny_feet/test/fixtures</code>.  To override the default fixture directory (and control other fixture settings), add this to the bottom of the plugin&#8217;s <code>test_helper.rb</code> file:</p>

<h1>vendor/plugins/skinny<em>feet/test/test</em>helper.rb</h1>

<p>class Test::Unit::TestCase
self.use<em>transactional</em>fixtures = true
self.use<em>instantiated</em>fixtures = false
self.fixture<em>path = File.expand</em>path(File.dirname(<strong>FILE</strong>) + &#8220;/fixtures&#8221;)
end</p>

<p>The disadvantage to loading up Rails for each test suite is that it introduces a significant performance hit.  You won&#8217;t want to do this for tests that don&#8217;t interact with the database.</p>
]]></content:encoded>
			<wfw:commentRss>http://bark.metacasa.net/2007/02/07/testing-rails-model-plugins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Palm Database Parsing With Ruby</title>
		<link>http://bark.metacasa.net/2006/03/23/palm-database-parsing-with-ruby/</link>
		<comments>http://bark.metacasa.net/2006/03/23/palm-database-parsing-with-ruby/#comments</comments>
		<pubDate>Thu, 23 Mar 2006 14:47:00 +0000</pubDate>
		<dc:creator>Umberdog</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://bark.metacasa.net/2006/03/23/palm-database-parsing-with-ruby/</guid>
		<description><![CDATA[Tracking hours for a handful of billable projects can be a lot of scribblin' and calculatin'.  So I was pleased to find the <a href="http://www.psync.com/PunchClock.shtml">PunchClock</a> time tracker application for PalmOS.  It's missing a few features I'd like, but on the whole it does a great job.  The main problem is counting hours for my bi-monthly timesheet.  PunchClock can show summaries by day, by week, by two-week, by month, and by year...but not bi-monthly.  So I'm still stuck with hand-calculating it myself.]]></description>
			<content:encoded><![CDATA[<p>Tracking hours for a handful of billable projects can be a lot of scribblin&#8217; and calculatin&#8217;.  So I was pleased to find the <a href="http://www.psync.com/PunchClock.shtml">PunchClock</a> time tracker application for PalmOS.  It&#8217;s missing a few features I&#8217;d like, but on the whole it does a great job.  The main problem is counting hours for my bi-monthly timesheet.  PunchClock can show summaries by day, by week, by two-week, by month, and by year&#8230;but not bi-monthly.  So I&#8217;m still stuck with hand-calculating it myself.<span id="more-10"></span></p>

<p>A while back, I threw something together in Java, using the <a href="http://jpilot-db.sourceforge.net/">JPilot DB</a> library to parse Palm PRC database files.  It was a bit clunky, even at 550 lines of source code (not including JPilot), but it mostly did the job.</p>

<p>Never really satisfied with the Java hack, but lacking the time to improve it, I just let it sit, using it every couple weeks, then not at all.  Finally, last night, I sat down with the <a href="http://www.palmos.com/dev/support/docs/fileformats/PDB+PRCFormat.html">Palm online docs</a> plus a <a href="http://www.nsbasic.com/palm/info/technotes/TN02a.htm">tech note</a> I found long ago, to see what it would be like to do it as a Ruby script.</p>

<p>Lo and behold, it only took me about 60 lines of Ruby code (only 30 of which is parsing code), from start to finish.  I had to fiddle with the pack/unpack specs a bit, but things fell together quickly.  I was impressed by how intuitive Ruby scripting was.  It was easy to group results by year or by year-and-month, etc., by using a Time object as the hash key (see by<em>year() and by</em>month() methods below).  Here&#8217;s the source code for the parser&#8230;so far.</p>

<pre>class Record
attr_accessor :start, :stop
def initialize(start, stop)
@start, @stop = start, stop
end

def to_s
"#{@start} - #{@stop}"
end
end

class TimeDb
attr_accessor :record_count, :records
def initialize(filename)
@contents = File.read(filename)
parse
end

def parse
@hdr, @body = @contents.unpack("a78 a*")
@hdrparts = @hdr.unpack("Z32 nn A4 A4 A4 III A4 A4 II n ")
@record_count = @hdrparts.last

@records = []
for i in 0...@record_count
offset, flags, id = @body[(i * 8)...(i * 8 + 8)].unpack("I c a3")
next if flags == -64

record = @contents[offset..(offset + 14)]
date_time, hour, minute, time_spent = record.unpack("xxx a3 x CC x I")

date_time = date_time.insert(0, 0.chr).unpack("I").first
month = (date_time &#038; 0xf00000) >> 20
day = (date_time &#038; 0xf8000) >> 15
year = (date_time &#038; 0x7fff)

t1 = Time.gm(year, month, day, hour, minute)
t2 = t1 + time_spent
@records < < Record.new(t1, t2)
end
end

def by_year
map = {}
@records.each do |record|
key = Time.gm record.start.year
(map[key] ||= []) << record
end
map
end

def by_month
map = {}
@records.each do |record|
key = Time.gm record.start.year, record.start.month
(map[key] ||= []) << record
end
map
end

end</pre>

<p>And here's a sample of code to list all entries by month.</p>

</pre><pre>db = TimeDb.new("PC_MyProject.pdb")

map = db.by_month
map.keys.sort.each do |key|
puts "  #{key.strftime("%Y/%m/%d")}n #{map[key].inspect}nn"
end</pre>

<p>I'm very pleased with the results.  The next step is to write a little Rails app to provide an interactive browser for my PunchClock databases.  And after that, tools for creating <a href="#SuperMemo">SuperMemo</a> databases.  Fun fun fun....</p>
]]></content:encoded>
			<wfw:commentRss>http://bark.metacasa.net/2006/03/23/palm-database-parsing-with-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby Brewings</title>
		<link>http://bark.metacasa.net/2005/12/07/ruby-brewings/</link>
		<comments>http://bark.metacasa.net/2005/12/07/ruby-brewings/#comments</comments>
		<pubDate>Thu, 08 Dec 2005 05:14:00 +0000</pubDate>
		<dc:creator>Umberdog</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://bark.umberdog.com/?p=5</guid>
		<description><![CDATA[Computer programming is like any other career: you have to give it a kick in the John Henry every once in awhile to keep it interesting, otherwise you risk boredom, stagnation, or worse.  That&#8217;s how Java feels lately.  It has lost its luster, its challenging crackle.  The initial discovery and adventure has [...]]]></description>
			<content:encoded><![CDATA[<p>Computer programming is like any other career: you have to give it a kick in the John Henry every once in awhile to keep it interesting, otherwise you risk boredom, stagnation, or worse.  That&#8217;s how <a href="http://java.sun.com/">Java</a> feels lately.  It has lost its luster, its challenging crackle.  The initial discovery and adventure has been buried in a paradoxical swamp of rote boilerplate coding and dizzying <a href="http://java.sun.com/j2ee/index.jsp">Enterprise Specifications</a>.</p>

<p>Time for a change of pace.</p>

<p>My first breath of fresh life recently was <a href="http://developer.apple.com/cocoa/">Apple&#8217;s Cocoa Toolkit</a> for developing native Mac OS X applications, using the Objective-C programming language.  So far so good, but it&#8217;s a huge code library with tons of great tools, and it only works on modern Apple systems.  Great for my hobby projects, but it doesn&#8217;t really help me at my day job.</p>

<p>Enter the <a href="http://www.ruby-lang.org/en/">Ruby Programming Language</a>, a fully object-oriented scripting language with solid cross platform support (OS X, Windows, UNIX) and a wealth of built-in libraries.  I&#8217;ve just scratched the surface, but it does seem to light up that special spark that I&#8217;ve been missing from Java lately.  A change of pace will really help fire me up again at work, and shake off those creeping doldrums.  Let&#8217;s hope!</p>
]]></content:encoded>
			<wfw:commentRss>http://bark.metacasa.net/2005/12/07/ruby-brewings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
