<?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"
	>

<channel>
	<title>Light Year Blog</title>
	<atom:link href="http://lightyearsoftware.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://lightyearsoftware.com/blog</link>
	<description>Starting up in the midwest after ten years in Silicon Valley</description>
	<pubDate>Thu, 12 Jun 2008 15:26:16 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>What else might be in Snow Leopard?</title>
		<link>http://lightyearsoftware.com/blog/2008/06/what-else-might-be-in-snow-leopard/</link>
		<comments>http://lightyearsoftware.com/blog/2008/06/what-else-might-be-in-snow-leopard/#comments</comments>
		<pubDate>Thu, 12 Jun 2008 15:15:23 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/?p=30</guid>
		<description><![CDATA[Apple Inc. announced Mac OS X 10.6 &#8220;Snow Leopard&#8221; at WWDC&#8217;08 on Monday, but other than a press release and a page each for 10.6 Client and Server, very little information was given that isn&#8217;t covered under the WWDC NDA.
Still, one &#8220;feature&#8221; is interesting, especially in the face of (mostly confirmed) rumors that 10.6 will [...]]]></description>
			<content:encoded><![CDATA[<p>Apple Inc. announced Mac OS X 10.6 &#8220;Snow Leopard&#8221; at WWDC&#8217;08 on Monday, but other than a <a href="http://www.apple.com/pr/library/2008/06/09snowleopard.html">press release</a> and a page each for 10.6 <a href="http://www.apple.com/macosx/snowleopard/">Client</a> and <a href="http://www.apple.com/server/macosx/snowleopard/">Server</a>, very little information was given that isn&#8217;t covered under the WWDC NDA.</p>
<p>Still, one &#8220;feature&#8221; is interesting, especially in the face of (<a href="http://www.logicielmac.com/news5041/Snow_Leopard__adieu_les_PPC_.html">mostly</a> <a href="http://www.macrumors.com/2008/06/11/mac-os-x-snow-leopard-drops-powerpc-support/">confirmed</a>) rumors that 10.6 will drop support for the PowerPC:</p>
<blockquote><p>Snow Leopard dramatically reduces the footprint of Mac OS X, making it even more efficient for users, and giving them back valuable hard drive space for their music and photos.</p></blockquote>
<p>Dropping PowerPC will save reduce the size of executable code by around 50%.  Here is the output of <tt>otool -f</tt> for iTunes:</p>
<pre>Fat headers
fat_magic 0xcafebabe
nfat_arch 2
architecture 0
    cputype 18
    cpusubtype 0
    capabilities 0x0
    offset 4096
    size 17345088
    align 2^12 (4096)
architecture 1
    cputype 7
    cpusubtype 3
    capabilities 0x0
    offset 17350656
    size 17053824
    align 2^12 (4096)</pre>
<p>The PowerPC&#8217;s CPU type is 18 (look in <tt>/usr/include/mac/machine.h</tt>), so the PowerPC code in the main iTunes executable accounts for 50.4% of the total.  I&#8217;m going to assume that this ratio will mostly hold true for frameworks, too.</p>
<p>The entire iTunes bundle is 122 MB, though.  Trimming the 16.5 MB + 1 MB of bundled frameworks off of that is only about 14%; not what I&#8217;d call a &#8220;dramatic&#8221; footprint reduction.  What else might they have planned?</p>
<p>Another couple of options are transparent compression at the filesystem layer and conversion of image resources to a vector format.</p>
<p>Apple&#8217;s own page says that read/write ZFS will be in 10.6 Server, so it&#8217;s reasonable to expect it will be in Client, too, perhaps with some of the more advanced features disabled.  ZFS includes an option to transparently compress data.  NTFS on Windows has had this for years, and third-party products did it on FAT years before that, so it&#8217;s entirely reasonable to expect that Macs will finally get this, too.  71% of the iTunes bundle is resources, mostly localizations, and inside those, the largest directories are for the in-app help, which is HTML.</p>
<p>Support for resolution independence has been <a href="http://www.appleinsider.com/articles/04/08/23/mac_os_x_tiger_to_support_resolution_independent_ui_larger_icons.html">rumored for years</a>, and while Apple has <a href="http://developer.apple.com/releasenotes/GraphicsImaging/RN-ResolutionIndependentUI/index.html">supported it to some degree since 10.4</a>, it hasn&#8217;t really caught on.  Might they finally be converting all of the system image resources to a vector format?  I don&#8217;t have any numbers on it, but a vector graphic is certain to take up much less space than a 512&#215;512 PNG.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/06/what-else-might-be-in-snow-leopard/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Advertising and Making Money Online</title>
		<link>http://lightyearsoftware.com/blog/2008/05/advertising-and-making-money-online/</link>
		<comments>http://lightyearsoftware.com/blog/2008/05/advertising-and-making-money-online/#comments</comments>
		<pubDate>Mon, 05 May 2008 16:24:15 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Business]]></category>

		<category><![CDATA[Entrepreneurship]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/?p=6</guid>
		<description><![CDATA[David Heinemeier Hansson gave an amusing talk at Startup School &#8216;08 and it echoes something I&#8217;ve been thinking about for some time.  A lot of web sites out there get very, very popular and yet there is no indication they plan to make money.  Many more web sites fall back on advertising as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.37signals.com/svn/posts/981-the-secret-to-making-money-online">David Heinemeier Hansson gave an amusing talk</a> at Startup School &#8216;08 and it echoes something I&#8217;ve been thinking about for some time.  A lot of web sites out there get very, very popular and yet there is no indication they plan to make money.  Many more web sites fall back on advertising as their primary business model.</p>
<p>ZingLists isn&#8217;t terrifically popular, but I&#8217;ve given a lot of thought to how it might generate some revenue and least pay the hosting bill.  Up to now, I&#8217;ve taken the easy route and put Google ads on the list summary pages.  They aren&#8217;t very intrusive and once in a while they&#8217;re actually useful, displaying an ad that helps you cross something off that list.</p>
<p>There are really two problems with relying on advertising as a business model.  The first is my problem.  Relying on someone else to sell the ads (Google) means you essentially have a single customer.  If something happens to that customer, all of your revenue disappears in a puff of smoke.  Google disabled my account about a week ago and I can&#8217;t get them to tell me why.  It&#8217;s the whole account, too: AdSense, Analytics, Gmail, Calendar, everything.  I have no idea what the perceived problem is, though my best guess is click fraud.  That sucks, though, because I can&#8217;t control an end-user&#8217;s behavior, and if I don&#8217;t show them the ads, I have no chance of generating revenue.  So Google AdSense (or any single provider of ads) is not a real business model.</p>
<p>The second big problem with advertising is this simple question: why are you in business?  Is it to sell advertising or to write software / provide a service?  If it&#8217;s the latter, I&#8217;m sorry to inform you that generating revenue by selling your own ads means you are in fact in the business of selling ads, not writing software.  This is not a business I want to be in.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/05/advertising-and-making-money-online/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Another Example of How Not to Do Customer Relations</title>
		<link>http://lightyearsoftware.com/blog/2008/05/another-example-of-how-not-to-do-customer-relations/</link>
		<comments>http://lightyearsoftware.com/blog/2008/05/another-example-of-how-not-to-do-customer-relations/#comments</comments>
		<pubDate>Fri, 02 May 2008 14:24:44 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Business]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/?p=29</guid>
		<description><![CDATA[Mozy finally announced their 1.0 release for Mac OS X.  I haven&#8217;t heard from these guys since I signed up for the notification, probably more than a year ago.  Then today, out of the blue, I get an email that leads off with:

One of the nice things about being an ugly American is [...]]]></description>
			<content:encoded><![CDATA[<p>Mozy finally announced their 1.0 release for Mac OS X.  I haven&#8217;t heard from these guys since I signed up for the notification, probably more than a year ago.  Then today, out of the blue, I get an email that leads off with:</p>
<blockquote><p>
One of the nice things about being an ugly American is that I make all sorts of ignorant and culturally insensitive remarks about other countries. And as luck would have it, I had that opportunity last week when I visited Montreal. (That&#8217;s in Canada.)  </p>
<p>The first thing I noticed about Montreal is that it&#8217;s a very clean city - like Toronto in that respect. Oh wait - actually, the first thing I noticed was the streets were on fire and full of police and rioting citizens because I guess they won an O-KAY (that&#8217;s hockey) game.
</p></blockquote>
<p>Admitting that you&#8217;re a jerk doesn&#8217;t give you a free pass to go ahead and act like a jerk.  If anything, it&#8217;s worse because you&#8217;ve made it clear that you know it&#8217;s wrong.</p>
<p>And as a method of contacting a list of people who otherwise haven&#8217;t heard from your company before?  This isn&#8217;t how I&#8217;d choose to establish a relationship with potential customers.</p>
<p>I&#8217;ll rest well knowing that Mozy won&#8217;t get any of my money, especially with so many other options available in their market.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/05/another-example-of-how-not-to-do-customer-relations/feed/</wfw:commentRss>
		</item>
		<item>
		<title>sql_logging Updated for Edge Rails</title>
		<link>http://lightyearsoftware.com/blog/2008/04/sql_logging-updated-for-edge-rails/</link>
		<comments>http://lightyearsoftware.com/blog/2008/04/sql_logging-updated-for-edge-rails/#comments</comments>
		<pubDate>Thu, 24 Apr 2008 21:59:47 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/?p=28</guid>
		<description><![CDATA[I updated the sql_logging plug-in today to work on Edge Rails.  The PostgreSQL adapter on Edge tries to load a different database driver, and explicitly loading it when the application isn&#8217;t using it causes a crash when the server starts.  Today&#8217;s change reworks things by asking ActiveRecord what adapter it&#8217;s using and only loading the [...]]]></description>
			<content:encoded><![CDATA[<p>I updated the sql_logging plug-in today to work on Edge Rails.  The PostgreSQL adapter on Edge tries to load a different database driver, and explicitly loading it when the application isn&#8217;t using it causes a crash when the server starts.  Today&#8217;s change reworks things by asking ActiveRecord what adapter it&#8217;s using and only loading the extensions for it.</p>
<p>One other change includes making PostgreSQL query statistics work on Rails 2.0.  The adapter there prefers to call the execute method instead of query.</p>
<p>Things should still work on Rails 1.2, but I&#8217;m moving applications to 2.0 whenever possible, so I&#8217;ll rely on a bug report if something is broken.</p>
<p>Finally, I&#8217;ll leave with a little tip: statistics aren&#8217;t kept for queries that lack a name or look like Rails asking for schema information.  If you have a significant amount of query work done using the raw connection (select_all or select_one), make sure you give the query a name so it can be tracked properly and show up in the top 10 list.</p>
<p>Get the plug-in from svn at http://svn.lightyearsoftware.com/svn/plugins/sql_logging.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/04/sql_logging-updated-for-edge-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Quality of Service</title>
		<link>http://lightyearsoftware.com/blog/2008/04/quality-of-service/</link>
		<comments>http://lightyearsoftware.com/blog/2008/04/quality-of-service/#comments</comments>
		<pubDate>Mon, 21 Apr 2008 18:26:51 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Business]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/?p=27</guid>
		<description><![CDATA[I clearly take my job a little too seriously.
I&#8217;ve been filling up some free hours these past couple of weeks putting some polish on ZingLists.  Most of the changes involve tweaking a few things here and there, but the big one is that I&#8217;m adding a mobile interface for the most essential features, and [...]]]></description>
			<content:encoded><![CDATA[<p>I clearly take my job a little too seriously.</p>
<p>I&#8217;ve been filling up some free hours these past couple of weeks putting some polish on <a href="http://zinglists.com">ZingLists</a>.  Most of the changes involve tweaking a few things here and there, but the big one is that I&#8217;m adding a mobile interface for the most essential features, and that necessitated moving from Rails 1.2 to Rails 2.0.</p>
<p>Everything went smoothly during development, but late Friday, when I pushed the code to production, anything that touched the new code died with a scary-looking illegal instruction signal.  My production server runs FreeBSD, and I had upgraded a few other packages to stay current with security issues and bug fixes, so this left me with the cold feeling of a completely dead site late on a Friday afternoon.</p>
<p>As it turns out, while I haven&#8217;t solved the problem yet, I got lucky through some over-engineering on my part when I first wrote my Capistrano deployment recipes.  I do deployments in two stages.  Stage 1: push the code, run migrations and background tasks (e.g generating a Google sitemap).  Stage 2: move configuration files into place, switch the &#8220;current&#8221; symlink and restart processes.  Since I hadn&#8217;t run stage 2 yet, everything was still working fine.</p>
<p><a href="http://getsatisfaction.com/twitter/topics/web_not_posting_tweets_from_people_i_follow">Twitter also pushed some new code</a> on Friday, but they&#8217;re having problems big enough that the site may as well be down.</p>
<p>ZingLists is microscopic compared to Twitter in just about every way imaginable.  I&#8217;m one guy with no VC, Twitter is a dozen-ish people with at least a few million in VC.  Neither of us are making any money off our web sites.  Shouldn&#8217;t I be the one that doesn&#8217;t care about my uptime?</p>
<p>I&#8217;m optimistic that I will solve my &#8220;illegal instruction&#8221; problem with Rails 2.0, so in the interest of priming this post for anyone else who runs into the same thing, here&#8217;s a summary of the issue.  (I expect most of you will stop reading here.)</p>
<p>The &#8220;illegal instruction&#8221; seems to be a case of the Ruby interpreter not dealing well with a stack overflow.  This could be from deep recursion, but I doubt it in my case since the same works fine in development.  Even simple things like <tt>List.find(:all)</tt> from <tt>script/console</tt> causes the problem, and that&#8217;s a simple ActiveRecord query.</p>
<p>On FreeBSD 6.2, the Ruby port is always compiled with pthreads.  Because of the way that this version of FreeBSD is written, if a dynamic shared object loaded into a running program needs a shared library (like pthreads), that library must be linked to by the executing program.  In this case, that&#8217;s the Ruby interpreter.  The default pthreads stack size on FreeBSD is relatively small compared to other operating systems, though I couldn&#8217;t track down an exact number.  It&#8217;s in the ballpark of 64 KB or 128 KB.  Linux usually uses something closer to 1 or 2 MB.</p>
<p>My theory at the moment is that Rails 2.0 nests method calls deeper than 1.2, just enough to exhaust the stack and trigger the illegal instruction signal.  I&#8217;m guessing this is because the stack overflow results in some random bit of code being executed.  I&#8217;m on the AMD64 platform, and I believe it marks non-code pages with the NX (no execute) bit, so a jump off to a random address is highly likely to be caught by the kernel.</p>
<p>I don&#8217;t really want to recompile or hack the Ruby interpreter to make pthreads stacks larger, since I&#8217;d have to make the same fix every time Ruby is updated.  I&#8217;m going to try to replicate the problem in a 6.2 virtual machine, then upgrade it to 6.3 and possibly 7.0 to see if either of those solve it.  Barring a response from the Ruby port maintainer, I may even look at switching to Ubuntu Linux, though I hate to do that since I&#8217;m otherwise very satisfied with FreeBSD.</p>
<p><strong>Updated April 24:</strong> so as usual, admitting in public that I have a problem with some code virtually guarantees that the problem is in my code.  I had an infinite recursion bug due to an &lt;tt&gt;:include&lt;/tt&gt; on an association.  FreeBSD simply died really fast, probably due its small thread stack, but I also was missing an adequate test case to catch the problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/04/quality-of-service/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Working with ActiveRecord Callbacks</title>
		<link>http://lightyearsoftware.com/blog/2008/03/working-with-activerecord-callbacks/</link>
		<comments>http://lightyearsoftware.com/blog/2008/03/working-with-activerecord-callbacks/#comments</comments>
		<pubDate>Thu, 20 Mar 2008 01:29:09 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/2008/03/working-with-activerecord-callbacks/</guid>
		<description><![CDATA[This post should be subtitled &#8220;And how not to waste one of YOUR afternoons because of them.&#8221;
As the documentation describes, there are a total of 18 &#8220;normal&#8221; callbacks defined by ActiveRecord that allow you to manage the lifecycle of your objects.  For the purpose of this post, I define &#8220;normal&#8221; as callbacks that can [...]]]></description>
			<content:encoded><![CDATA[<p>This post should be subtitled &#8220;And how not to waste one of YOUR afternoons because of them.&#8221;</p>
<p>As the documentation describes, there are a total of 18 &#8220;normal&#8221; callbacks defined by ActiveRecord that allow you to manage the lifecycle of your objects.  For the purpose of this post, I define &#8220;normal&#8221; as callbacks that can be implemented in a way other than overriding the named method.  There are two more (<tt>after_initialize</tt> and <tt>after_find</tt>), but they must be implemented as an overridden method, so my argument here does not apply to them.</p>
<p>The short of it: don&#8217;t define your callbacks as explicit methods.  In other words, don&#8217;t do this:</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#5A0A0A; font-weight:bold;">after_save</span>
  <span style="color:#008000; font-style:italic;"># ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>OK, so why?  The answer boils down to how ActiveRecord executes callbacks and why it may decide to stop running the chain.</p>
<p>Explicit method implementations like this come dead last in the calling order, and since callbacks can return <tt>false</tt> and stop the execution of further callbacks, your code may never be executed.  This can come as a complete surprise, because associations might define callbacks.  For example, <tt>has_one</tt> defines an <tt>after_save</tt> callback that will try to save the associated model if you just saved a new record or if the associated model is a new record.  If for some reason that associated model isn&#8217;t valid, the return value is false and ActiveRecord kills the chain of callbacks.  Perhaps you have an <tt>after_save</tt> method explicitly defined that would fix this problem?  It won&#8217;t be called, no exception is raised and you&#8217;ll spend a couple of hours reading ActiveRecord code to piece things together.</p>
<p>The ActiveRecord::Callbacks documentation explains most of this, but in bits and pieces and never in a way that makes it clear to how to best avoid trouble.  Here are my new rules of the road:</p>
<ol>
<li> Declare callbacks either as symbols to method names (not named after their callback), inline blocks, strings (for eval) or completely separate objects.</li>
<li> Declare them very early in your model, but especially <em>before</em> associations.  Associations may declare their own callbacks and you probably want yours to run first.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/03/working-with-activerecord-callbacks/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The sql_logging Debugging Plug-In</title>
		<link>http://lightyearsoftware.com/blog/2008/02/the-sql_logging-debugging-plug-in/</link>
		<comments>http://lightyearsoftware.com/blog/2008/02/the-sql_logging-debugging-plug-in/#comments</comments>
		<pubDate>Mon, 18 Feb 2008 15:27:13 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/2008/02/the-sql_logging-debugging-plug-in/</guid>
		<description><![CDATA[One of my current projects involves significantly improving the search function in a Rails application, a thorny problem that led me to come up with the method to quiet down the Rails logger in my SQL log silencer.  It turns out, that wasn&#8217;t enough.  I have expanded quite a bit on that idea [...]]]></description>
			<content:encoded><![CDATA[<p>One of my current projects involves significantly improving the search function in a Rails application, a thorny problem that led me to come up with the method to quiet down the Rails logger in my <a href="http://lightyearsoftware.com/blog/2008/01/a-sql-log-silencer/">SQL log silencer</a>.  It turns out, that wasn&#8217;t enough.  I have expanded quite a bit on that idea by folding in some useful debugging aids from other developers, making them more useful, and adding a SQL query &#8220;hit list&#8221; after each request completes.  I&#8217;m releasing it as the sql_logging plug-in.</p>
<p>Installation is the usual (on one line):</p>
<p><code>$ script/plugin install \<br />
http://svn.lightyearsoftware.com/svn/plugins/sql_logging<br />
</code></p>
<p>So, what does this give you?</p>
<p>Out of the box, you get these new things:</p>
<ul>
<li>A count of the number of rows returned and a rough count of bytes for each SELECT query</li>
<li>A summary at the end of the request of the total number of queries, bytes returned and SQL executions</li>
<li>Each SQL execution includes a clean-up backtrace to show you exactly what part of your code triggered the query</li>
<li>A summary at the end of the request showing a &#8220;top 10&#8243; list of queries</li>
</ul>
<p>The last one is particular useful.  Queries are grouped by their backtrace, and then sorted by either number of executions, rows returned or bytes returned.  This provides an <em>excellent</em> way to target your performance optimization work.</p>
<p>When sorted by executions, you very quickly see where the same code is triggering a query over and over, and can spend your optimization time trying to reduce this by adding the model to an earlier query (via <tt>:include</tt>) or by getting more rows at a time by batching up loads (<tt>WHERE id IN (&#8230;)</tt>).  Here&#8217;s a sample:</p>
<pre>Completed in 13.01586 (0 reqs/sec) | Rendering: 2.69928 (20%) | DB: 8.68216 (66%), 154 selects, 1728.1 KB, 166 execs
Top 10 SQL executions:
  Executed 95 times, returning 180 rows (230.5 KB):
    app/models/merge_keyword.rb:34:in `get_merges_by_keyword'
    app/models/merge_keyword.rb:30:in `each'
    app/models/merge_keyword.rb:30:in `get_merges_by_keyword'
    app/models/merge.rb:107:in `search'
    app/models/merge.rb:105:in `each'
    app/models/merge.rb:105:in `search'
    app/controllers/search_controller.rb:98:in `results'
  Executed 22 times, returning 30 rows (1.3 KB):
    app/models/merge.rb:80:in `attribute'
    app/views/merges/_result_line.rhtml:2:in `_run_rhtml_47app47views47merges47_result_line46rhtml'
    app/views/search/results.rhtml:172:in `_run_rhtml_47app47views47search47results46rhtml'
    app/views/search/results.rhtml:170:in `each'
    app/views/search/results.rhtml:170:in `each_with_index'
    app/views/search/results.rhtml:170:in `_run_rhtml_47app47views47search47results46rhtml'
  Executed 20 times, returning 30 rows (1.2 KB):
    app/models/merge.rb:80:in `attribute'
    app/helpers/application_helper.rb:40:in `merge_detail_link'
    app/views/merges/_result_line.rhtml:26:in `_run_rhtml_47app47views47merges47_result_line46rhtml'
    app/views/search/results.rhtml:172:in `_run_rhtml_47app47views47search47results46rhtml'
    app/views/search/results.rhtml:170:in `each'
    app/views/search/results.rhtml:170:in `each_with_index'
    app/views/search/results.rhtml:170:in `_run_rhtml_47app47views47search47results46rhtml'
</pre>
<p>By sorting by rows or bytes returned, you may be able to determine that you need to let the database do more of the filtering work.  It may be inefficient to have the database return a pile of rows to your application, only to discard a bunch of them.</p>
<p>The silencer from my previous post is in there, too, along with a new silencer that quiets only the backtrace for the duration of the block:</p>

<div class="wp_syntax"><div class="code"><pre class="rails">silence_sql <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#008000; font-style:italic;"># ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
silence_sql_backtrace <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#008000; font-style:italic;"># ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>I must give a big hat tip to <a href="http://gurge.com/blog/">Adam Doppelt</a> and <a href="http://terralien.com/">Nathaniel Talbott</a>.  Adam&#8217;s <a href="http://gurge.com/blog/2006/11/09/rails-sql-logging-improvements/">SQL logging enhancements</a> formed the basis for the logging enhancements here.  I made them a little more generic so they worked with both MySQL and PostgreSQL, as well as tracking executions for things that don&#8217;t return data.  Nathaniel&#8217;s <a href="http://terralien.com/projects/querytrace/">QueryTrace</a> plug-in has been around for a while, and I originally tried making this new plug-in simply work with it, but in the end decided to fold the functionality in so the &#8220;top 10&#8243; list didn&#8217;t duplicate the backtrace cleaning code.  I also added a regexp to the cleaner so it excludes the plug-in&#8217;s code from the backtrace.</p>
<p>There are a few more goodies in the plug-in, so look at the <a href="http://svn.lightyearsoftware.com/svn/plugins/sql_logging/README">README</a> for more details.</p>
<p><strong>Update:</strong> I fixed a few bugs and added a feature.  The plug-in now ignores queries whose name ends with &#8221; Column&#8221;.  These are internal Rails queries and their inclusion skewed the results.</p>
<p>The new feature tracks the execution time of SQL, and lets you sort the top-10 list by either total time for all instances of the SQL or the median execution time.  Total time is also now the default sorting method, as this is probably the best way to attack SQL optimization: whatever is taking up the biggest percentage of your time in the database is a good place to start.</p>
<p><strong>Update 2:</strong> The plug-in works on Rails 2.0.2 now.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/02/the-sql_logging-debugging-plug-in/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A SQL Log Silencer</title>
		<link>http://lightyearsoftware.com/blog/2008/01/a-sql-log-silencer/</link>
		<comments>http://lightyearsoftware.com/blog/2008/01/a-sql-log-silencer/#comments</comments>
		<pubDate>Fri, 18 Jan 2008 22:36:27 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/2008/01/a-sql-log-silencer/</guid>
		<description><![CDATA[Here&#8217;s something I just whipped up to quiet ActiveRecord&#8217;s logging in development mode.  Normally, ActiveRecord&#8217;s AbstractAdapter logs every SQL query as it is made.  Sometimes, it&#8217;s nice to quiet this down without changing your log level while tracking down a problem.

class ActiveRecord::ConnectionAdapters::AbstractAdapter
  def log_info_with_silencing&#40;sql, name, runtime&#41;
    unless ActiveRecord::Base.silence_sql_logging
  [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s something I just whipped up to quiet ActiveRecord&#8217;s logging in development mode.  Normally, ActiveRecord&#8217;s AbstractAdapter logs every SQL query as it is made.  Sometimes, it&#8217;s nice to quiet this down without changing your log level while tracking down a problem.</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::ConnectionAdapters::AbstractAdapter</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> log_info_with_silencing<span style="color:#006600; font-weight:bold;">&#40;</span>sql, name, runtime<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">silence_sql_logging</span>
      log_info_without_silencing<span style="color:#006600; font-weight:bold;">&#40;</span>sql, name, runtime<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  alias_method_chain <span style="color:#ff3333; font-weight:bold;">:log_info</span>, <span style="color:#ff3333; font-weight:bold;">:silencing</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> SqlSilencer
  <span style="color:#9966CC; font-weight:bold;">def</span> silence_sql
    logging = <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">silence_sql_logging</span>
    <span style="color:#9966CC; font-weight:bold;">begin</span>
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">silence_sql_logging</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
      <span style="color:#9966CC; font-weight:bold;">yield</span>
    <span style="color:#9966CC; font-weight:bold;">ensure</span>
      <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">silence_sql_logging</span> = logging
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  @@silence_sql_logging = <span style="color:#0000FF; font-weight:bold;">false</span>
  cattr_accessor <span style="color:#ff3333; font-weight:bold;">:silence_sql_logging</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">include</span> SqlSilencer
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#6666ff; font-weight:bold;">ActionController::Base</span>
  <span style="color:#9966CC; font-weight:bold;">include</span> SqlSilencer
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Drop this into a file in <tt>config/initializers</tt> if you&#8217;re on Rails 2.0 or <tt>require</tt> it from within <tt>environment.rb</tt> for pre-2.0.</p>
<p>To use inside a controller action or model method, simply wrap the code you want to silence inside a block:</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#9966CC; font-weight:bold;">def</span> index
  silence_sql <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#008000; font-style:italic;"># lots of work here...</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>One interesting side effect of this is that you can easily see how much database work is done as a result of what&#8217;s in your view.  Wrap the entire controller action inside a <tt>silence_sql</tt> block, then look at your log.  Any queries you see are a result of things you didn&#8217;t load in the controller.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2008/01/a-sql-log-silencer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Natural Language Date &#038; Time Parsing for ActiveRecord</title>
		<link>http://lightyearsoftware.com/blog/2007/12/natural-language-date-time-parsing-for-activerecord/</link>
		<comments>http://lightyearsoftware.com/blog/2007/12/natural-language-date-time-parsing-for-activerecord/#comments</comments>
		<pubDate>Mon, 17 Dec 2007 02:37:50 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/2007/12/natural-language-date-time-parsing-for-activerecord/</guid>
		<description><![CDATA[Chronic is a nice natural language parser for Ruby, but my first stab at adding it to a Rails application immediately felt wrong.  I was adding special case code in a controller to re-parse the field if the initial parse failed.  Of course, that needed to be duplicated for every field I wanted [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://chronic.rubyforge.org/">Chronic</a> is a nice natural language parser for Ruby, but my first stab at adding it to a Rails application immediately felt wrong.  I was adding special case code in a controller to re-parse the field if the initial parse failed.  Of course, that needed to be duplicated for every field I wanted to support it.</p>
<p>A much better (second) idea was, why not add this directly to ActiveRecord?  Every model gets it for free, and it turns out the code is hardly any more complicated.</p>

<div class="wp_syntax"><div class="code"><pre class="rails"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_record'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'chronic'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">module</span> ChronicParser
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">extended</span><span style="color:#006600; font-weight:bold;">&#40;</span>object<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> object
      alias_method_chain <span style="color:#ff3333; font-weight:bold;">:string_to_date</span>, <span style="color:#ff3333; font-weight:bold;">:chronic</span>
      alias_method_chain <span style="color:#ff3333; font-weight:bold;">:string_to_time</span>, <span style="color:#ff3333; font-weight:bold;">:chronic</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> string_to_date_with_chronic<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
    value = string_to_date_without_chronic<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> value.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      now = TzTime.<span style="color:#9900CC;">now</span> <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
      value = Chronic.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>string, <span style="color:#ff3333; font-weight:bold;">:now</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> now<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_date</span> <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    value
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> string_to_time_with_chronic<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
    value = string_to_time_without_chronic<span style="color:#006600; font-weight:bold;">&#40;</span>string<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> value.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      now = TzTime.<span style="color:#9900CC;">now</span> <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
      value = Chronic.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>string, <span style="color:#ff3333; font-weight:bold;">:now</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> now<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    value
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">ActiveRecord::ConnectionAdapters::Column</span>.<span style="color:#9900CC;">extend</span><span style="color:#006600; font-weight:bold;">&#40;</span>ChronicParser<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Put this where it will be executed during Rails initialization and you&#8217;re done.</p>
<p>Note also that while Chronic doesn&#8217;t claim to support time zones, this code will do the right thing by supplying a local perspective of the user&#8217;s current time, using <a href="http://weblog.jamisbuck.org/2007/2/2/introducing-tztime">TzTime</a>.  Someone in Japan using your site (which is hosted in California) in the early morning will get the expected result for &#8220;tomorrow.&#8221;</p>
<p>If a zone hasn&#8217;t been set for TzTime, it&#8217;ll fall back on the server&#8217;s current time.  If you aren&#8217;t using TzTime, modify appropriately.</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2007/12/natural-language-date-time-parsing-for-activerecord/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rails 1.2.4, RESTful Routes and Custom Actions</title>
		<link>http://lightyearsoftware.com/blog/2007/10/rails-124-restful-routes-and-custom-actions/</link>
		<comments>http://lightyearsoftware.com/blog/2007/10/rails-124-restful-routes-and-custom-actions/#comments</comments>
		<pubDate>Mon, 08 Oct 2007 19:45:53 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lightyearsoftware.com/blog/2007/10/rails-124-restful-routes-and-custom-actions/</guid>
		<description><![CDATA[If you use RESTful routes and define custom actions for your resources, you might suddenly find your custom action don&#8217;t work after upgrading to 1.2.4.  Whereas this used to work fine in 1.2.3:

map.resources :users
map.resources :users, :collection =&#62; &#123; :signin =&#62; :any,
              [...]]]></description>
			<content:encoded><![CDATA[<p>If you use RESTful routes and define custom actions for your resources, you might suddenly find your custom action don&#8217;t work after upgrading to 1.2.4.  Whereas this used to work fine in 1.2.3:</p>

<div class="wp_syntax"><div class="code"><pre class="rails">map.<span style="color:#9900CC;">resources</span> <span style="color:#ff3333; font-weight:bold;">:users</span>
map.<span style="color:#9900CC;">resources</span> <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:collection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:signin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:any</span>,
                                       <span style="color:#ff3333; font-weight:bold;">:signout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:post</span>,
                                       <span style="color:#ff3333; font-weight:bold;">:forgot_password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:any</span>,
                                       <span style="color:#ff3333; font-weight:bold;">:welcome</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:get</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
map.<span style="color:#9900CC;">resources</span> <span style="color:#ff3333; font-weight:bold;">:member</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:email</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:get</span>,
                                     <span style="color:#ff3333; font-weight:bold;">:prefs</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:get</span>,
                                     <span style="color:#ff3333; font-weight:bold;">:close</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:post</span> <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>This is actually wrong, and creates duplicate entries in the routing table.  The symptom of this problem is that your custom actions (e.g. <tt>/users/signin</tt>) will run the <tt>show</tt> action with a bogus ID of <tt>signin</tt>.</p>
<p>The proper way to define these resource routes is in one shot:</p>

<div class="wp_syntax"><div class="code"><pre class="rails">map.<span style="color:#9900CC;">resources</span> <span style="color:#ff3333; font-weight:bold;">:users</span>, <span style="color:#ff3333; font-weight:bold;">:collection</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:signin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:any</span>,
                                       <span style="color:#ff3333; font-weight:bold;">:signout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:post</span>,
                                       <span style="color:#ff3333; font-weight:bold;">:forgot_password</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:any</span>,
                                       <span style="color:#ff3333; font-weight:bold;">:welcome</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:get</span> <span style="color:#006600; font-weight:bold;">&#125;</span>,
                      <span style="color:#ff3333; font-weight:bold;">:member</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:email</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:get</span>,
                                   <span style="color:#ff3333; font-weight:bold;">:prefs</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:get</span>,
                                   <span style="color:#ff3333; font-weight:bold;">:close</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:post</span> <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>(Thanks to wolfmanjm on the rubyonrails-talk list for posting and answering his own question, as I was having the exact same problem.)</p>
]]></content:encoded>
			<wfw:commentRss>http://lightyearsoftware.com/blog/2007/10/rails-124-restful-routes-and-custom-actions/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.477 seconds -->
<!-- Cached page served by WP-Cache -->
