<?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>Tender Lovemaking</title>
	<atom:link href="http://tenderlovemaking.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://tenderlovemaking.com</link>
	<description>The act of making love, tenderly.</description>
	<pubDate>Mon, 04 Aug 2008 18:44:49 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>Identifying unknown music with Ruby</title>
		<link>http://tenderlovemaking.com/2008/08/04/identifying-unknown-music-with-ruby/</link>
		<comments>http://tenderlovemaking.com/2008/08/04/identifying-unknown-music-with-ruby/#comments</comments>
		<pubDate>Mon, 04 Aug 2008 18:44:49 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[earworm]]></category>

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

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

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=147</guid>
		<description><![CDATA[Ben Bleything inspired me (or rather distracted me from my yak shaving) to get my music library cleaned up and remove duplicates.  Unfortunately my duplicates don't necessarily have ID3 tags, and they may be in different formats, so I wrote a gem called "earworm" which will identify unknown music.  First I'll give you [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.bleything.net/" onclick="javascript:urchinTracker ('/outbound/article/blog.bleything.net');">Ben Bleything</a> inspired me (or rather distracted me from my <a href="http://github.com/aaronp/zomg/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">yak</a> <a href="http://github.com/aaronp/nokogiri/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">shaving</a>) to get my music library cleaned up and remove duplicates.  Unfortunately my duplicates don't necessarily have ID3 tags, and they may be in different formats, so I wrote a gem called "<a href="http://earworm.rubyforge.org/earworm/" onclick="javascript:urchinTracker ('/outbound/article/earworm.rubyforge.org');">earworm</a>" which will identify unknown music.  First I'll give you a code sample, then explain how to get earworm working, and finally explain how earworm works.</p>
<p>Here is the code sample:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ew = Earworm::Client.<span class="me1">new</span><span class="br0">&#40;</span>'MY Music DNS Key'<span class="br0">&#41;</span><br />
info = ew.<span class="me1">identify</span><span class="br0">&#40;</span>:file =&gt; '/home/aaron/unknown.<span class="me1">wav</span>'<span class="br0">&#41;</span><br />
<span class="kw3">puts</span> <span class="st0">&quot;#{info.artist_name} - #{info.title}&quot;</span></div>
</div>
<p>Earworm just needs a MusicDNS key and a file name to return information about your unknown audio.</p>
<p>Okay, now for getting  the gem to work.  Unfortunately this takes a little work right now.  You need to install a few libraries before earworm will work.  These libraries let you decode and identify mp3, ogg, and wav files.</p>
<p>For OS X (assuming you have MacPorts already installed) do this:</p>
<div class="codesnip-container" >$ sudo port install libogg libvorbis lame libofa</div>
<p>For Linux:</p>
<div class="codesnip-container" >$ sudo yum install libogg-devel libvorbis-devel lame-devel libofa</div>
<p>Then just install the gem like so:</p>
<div class="codesnip-container" >$ sudo gem install earworm</div>
<p>The final thing you need is a key from <a href="http://www.musicip.com/dns/index.jsp" onclick="javascript:urchinTracker ('/outbound/article/www.musicip.com');">MusicDNS</a> which you can obtain <a href="http://www.musicip.com/dns/license.jsp" onclick="javascript:urchinTracker ('/outbound/article/www.musicip.com');">here</a>.  The key is free for non-commercial applications.  Now you should be set!  Earworm will automatically decode mp3 files and ogg files for you, so you don't have to do that yourself.</p>
<p>How does earworm work?  First, it relies on <a href="http://icanhasaudio.com/" onclick="javascript:urchinTracker ('/outbound/article/icanhasaudio.com');">icanhasaudio</a> for audio decoding.  Second, it uses <a href="http://ruby-doc.org/stdlib/libdoc/dl/rdoc/index.html" onclick="javascript:urchinTracker ('/outbound/article/ruby-doc.org');">DL</a> to wrap <a href="http://code.google.com/p/musicip-libofa/" onclick="javascript:urchinTracker ('/outbound/article/code.google.com');">libofa</a>.  libofa takes between 10 and 135 seconds of audio and generates a hash.  After getting the hash for the audio snippet, earworm posts the hash (along with your key and some other info) to MusicDNS's web service.  The web services returns an XML document with information about the audio snippet.  Earworm parses the XML document and returns a nice object containing the information you requested.  Thats it!  No magic, and very simple (IMO) <a href="http://github.com/aaronp/earworm/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">source code</a>.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/08/04/identifying-unknown-music-with-ruby/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Back Home!</title>
		<link>http://tenderlovemaking.com/2008/07/08/back-home/</link>
		<comments>http://tenderlovemaking.com/2008/07/08/back-home/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 18:34:06 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[life]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=146</guid>
		<description><![CDATA[I'm finally back home.  I went to Japan a few weeks ago for vacation, and I also spoke at Ruby Kaigi 2008.  Ruby Kaigi was so much fun!  I've been studying Japanese for a little over a year, but I've never been to Japan.  It was exciting and fun to talk [...]]]></description>
			<content:encoded><![CDATA[<p>I'm finally back home.  I went to Japan a few weeks ago for vacation, and I also spoke at <a href="http://jp.rubyist.net/RubyKaigi2008/" onclick="javascript:urchinTracker ('/outbound/article/jp.rubyist.net');">Ruby Kaigi 2008</a>.  Ruby Kaigi was so much fun!  I've been studying Japanese for a little over a year, but I've never been to Japan.  It was exciting and fun to talk to people, and I made a bunch of new Japanese friends.  I'd really like to thank Leonard Chin for helping out at the Kaigi.  My language skills aren't good enough, and he was kind enough to fill in the gaps.  Thank you!</p>
<p>While I was in Japan, I noticed <a href="http://en.wikipedia.org/wiki/QR_Code" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">QR Codes</a> everywhere.  QR Codes are basically really awesome bar codes.  They can hold much more information in a smaller amount of space.  They can be easily decoded from images taken with digital cameras.  They have these codes everywhere in Japan, and the idea is that people can take a photo with the camera on their cell phone, then the phone decodes the QR Code.  I believe most of the QR codes contain information about the company, or possibly a URL to the company's website.</p>
<p>The company that created the format says that the format is open, but unfortunately I have to pay for the spec.  I can download the spec in Japanese for free, but my Japanese isn't that good!  So unfortunately I'm stuck with either the <a href="http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=43655" onclick="javascript:urchinTracker ('/outbound/article/www.iso.org');">ISO spec</a> (which is over $200) or the <a href="https://www.aimglobal.org/estore/ProductDetails.aspx?ProductID=31" onclick="javascript:urchinTracker ('/outbound/article/www.aimglobal.org');">AIM spec</a> ($85).  I don't understand why they are so expensive.....  I think I'll buy the AIM one, and hope that it is the same as the ISO one.</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/07/08/back-home/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Meow meow meow meow meow</title>
		<link>http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/</link>
		<comments>http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 19:56:52 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[computadora]]></category>

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

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=141</guid>
		<description><![CDATA[The other day I wrote an app called dejour to give me growl notifications from all the *jour gems out there.  I used Eric Hodel's awesome ruby-growl library.  Unfortunately it does all communications over the interweb, so you have to tweak some knobs in Growl to get it to work.  I stumbled [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I wrote an app called <a href="http://github.com/aaronp/dejour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">dejour</a> to give me growl notifications from <a href="http://github.com/chad/gitjour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">all</a> <a href="http://github.com/evanphx/gemjour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">the</a> <a href="http://github.com/jbarnette/pastejour/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">*jour</a> gems out there.  I used Eric Hodel's awesome <a href="http://segment7.net/projects/ruby/growl/" onclick="javascript:urchinTracker ('/outbound/article/segment7.net');">ruby-growl</a> library.  Unfortunately it does all communications over the interweb, so you have to tweak some knobs in Growl to get it to work.  I stumbled across a ruby/cocoa example using Growl, fixed it up, and released a gem called "Meow".</p>
<p>Meow lets you post notifications to your local machine without adjusting Growl.  If you're on OS X 10.5, just do:</p>
<div class="codesnip-container" >$ gem install meow</div>
<p>Then you can do this:</p>
<div class="codesnip-container" >$ ruby -r rubygems -e'require "meow"; Meow.notify("meow", "meow", "meow")'</div>
<p>No growl tweaks required!  Here is a code sample that is a little more explanatory:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'rubygems'<br />
<span class="kw3">require</span> 'meow'</p>
<p>meep = Meow.<span class="me1">new</span><span class="br0">&#40;</span>'My Application Name'<span class="br0">&#41;</span><br />
meep.<span class="me1">notify</span><span class="br0">&#40;</span>'Message Title', 'Message Description'<span class="br0">&#41;</span></div>
</div>
<p>Be sure to check out <a href="http://meow.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/meow.rubyforge.org');">the documentation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/06/06/meow-meow-meow-meow-meow/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Write your Rails view in&#8230;&#8230;.  JavaScript?</title>
		<link>http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/</link>
		<comments>http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/#comments</comments>
		<pubDate>Tue, 06 May 2008 18:33:30 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[johnson]]></category>

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

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=139</guid>
		<description><![CDATA[In my last post about Johnson, I said that next time I would talk about the JavaScript parse tree that Johnson provides.  Well, I changed my mind.  Sorry.
I want to write about a rails plugin that I added to Johnson.  Brohuda Katz wrote an ERb type parser in JavaScript, and added it [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="/2008/04/23/take-it-to-the-limit-one-more-time/">last post about Johnson</a>, I said that next time I would talk about the JavaScript parse tree that <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">Johnson</a> provides.  Well, I changed my mind.  Sorry.</p>
<p>I want to write about a rails plugin that I added to Johnson.  <a href="http://www.yehudakatz.com/" onclick="javascript:urchinTracker ('/outbound/article/www.yehudakatz.com');">Brohuda Katz</a> wrote an <a href="http://github.com/jbarnette/johnson/tree/master/js/johnson/template.js" onclick="javascript:urchinTracker ('/outbound/article/github.com');">ERb type parser in JavaScript</a>, and added it to the (yet to be released) Johnson distribution.  With that in mind, and looking at the new template handlers in edge rails, I was able to throw together a rails plugin that allows me to use JavaScript in my rails view code.</p>
<p>Lets get to the code.  Here is my controller:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw1">class</span> JohnsonController &lt; ApplicationController<br />
&nbsp; <span class="kw1">def</span> index<br />
&nbsp; &nbsp; @users = User.<span class="me1">find</span><span class="br0">&#40;</span>:all<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></div>
</div>
<p>And my EJS view (the file is named index.html.ejs):</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">&lt;% <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw2">var</span> user in at.users<span class="br0">&#41;</span> <span class="br0">&#123;</span> %&gt;<br />
&nbsp; &lt;%= user.first_name<span class="br0">&#40;</span><span class="br0">&#41;</span> %&gt;&lt;br /&gt;<br />
&lt;% <span class="br0">&#125;</span> %&gt;</div>
</div>
<p>The johnson rails plugin puts controller instance variables in to a special javascript variable called "at".  The "at" variable is actually a proxy to the controller, lazily fetching instance variables from the controller and importing those objects in to javascript land.</p>
<p>Lets take a look at the plugin, its only a few lines:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw1">class</span> EJSHandler &lt; ActionView::TemplateHandler<br />
&nbsp; <span class="kw1">class</span> EJSProxy <span class="co1"># :nodoc:</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> initialize<span class="br0">&#40;</span>controller<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; @controller = controller<br />
&nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> key?<span class="br0">&#40;</span>pooperty<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; @controller.<span class="me1">instance_variables</span>.<span class="kw1">include</span>?<span class="br0">&#40;</span><span class="st0">&quot;@#{pooperty}&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#40;</span>pooperty<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; @controller.<span class="me1">instance_variable_get</span><span class="br0">&#40;</span><span class="st0">&quot;@#{pooperty}&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="br0">&#91;</span><span class="br0">&#93;</span>=<span class="br0">&#40;</span>pooperty, value<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; @controller.<span class="me1">instance_variable_set</span><span class="br0">&#40;</span><span class="st0">&quot;@#{pooperty}&quot;</span>, value<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">end</span></p>
<p>&nbsp; <span class="kw1">def</span> initialize<span class="br0">&#40;</span>view<span class="br0">&#41;</span><br />
&nbsp; &nbsp; @view = view<br />
&nbsp; <span class="kw1">end</span></p>
<p>&nbsp; <span class="kw1">def</span> render<span class="br0">&#40;</span>template<span class="br0">&#41;</span><br />
&nbsp; &nbsp; ctx = Johnson::Context.<span class="me1">new</span><br />
&nbsp; &nbsp; ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'Johnson.<span class="kw3">require</span><span class="br0">&#40;</span><span class="st0">&quot;johnson/template&quot;</span><span class="br0">&#41;</span>;'<span class="br0">&#41;</span><br />
&nbsp; &nbsp; ctx<span class="br0">&#91;</span>'template'<span class="br0">&#93;</span> = template.<span class="me1">source</span><br />
&nbsp; &nbsp; ctx<span class="br0">&#91;</span>'controller'<span class="br0">&#93;</span> = @view.<span class="me1">controller</span><br />
&nbsp; &nbsp; ctx<span class="br0">&#91;</span>'at'<span class="br0">&#93;</span> = EJSProxy.<span class="me1">new</span><span class="br0">&#40;</span>@view.<span class="me1">controller</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'Johnson.<span class="me1">templatize</span><span class="br0">&#40;</span>template<span class="br0">&#41;</span>.<span class="me1">call</span><span class="br0">&#40;</span>at<span class="br0">&#41;</span>'<span class="br0">&#41;</span><br />
&nbsp; <span class="kw1">end</span><br />
<span class="kw1">end</span></p>
<p>ActionView::Template.<span class="me1">register_template_handler</span><span class="br0">&#40;</span><span class="st0">&quot;ejs&quot;</span>, EJSHandler<span class="br0">&#41;</span></div>
</div>
<p>When the template gets rendered (the render method), I wrap the controller with an EJS proxy, then compile the template into a javascript function, and call that function.  The "at" variable is set to the EJSProxy before executing the template, and all property accessing on the "at" variable is passed along to fetching instance variables from the controller.</p>
<p>Server side javascript coding in rails.  Weird, eh?</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/05/06/write-your-rails-view-in-javascript/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Take it to the limit one more time</title>
		<link>http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/</link>
		<comments>http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 18:22:29 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[computadora]]></category>

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

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

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

		<guid isPermaLink="false">http://tenderlovemaking.com/?p=138</guid>
		<description><![CDATA[Sup bros.  I need to post in this thing more often.  Yesterday, someone tipped over my scooter again.  I'm getting kind of tired of that.
Anyway, its time for me to write about this.  RKelly is pretty much dead.  For the past few months, John and I have been working on [...]]]></description>
			<content:encoded><![CDATA[<p>Sup bros.  I need to post in this thing more often.  Yesterday, someone tipped over <a href="http://flickr.com/photos/aaronp/150189237/" onclick="javascript:urchinTracker ('/outbound/article/flickr.com');">my scooter</a> again.  I'm getting kind of tired of that.</p>
<p>Anyway, its time for me to write about this.  <a href="http://rubyforge.org/projects/rkelly/" onclick="javascript:urchinTracker ('/outbound/article/rubyforge.org');">RKelly</a> is pretty much dead.  For the past few months, <a href="http://geeksomnia.com/" onclick="javascript:urchinTracker ('/outbound/article/geeksomnia.com');">John</a> and I have been working on RKelly's replacement called <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">Johnson</a>.  Basically we're now putting a ruby wrapper around <a href="http://www.mozilla.org/js/spidermonkey/" onclick="javascript:urchinTracker ('/outbound/article/www.mozilla.org');">Mozilla's Spidermonkey</a>.  The project is coming along quite nicely.  Ruby objects can be passed in to javascript land, and javascript objects can be passed back in to ruby land.</p>
<p>For example, we can define an alert function in our javascript context:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'johnson'</p>
<p>ctx = Johnson::Context.<span class="me1">new</span><br />
ctx<span class="br0">&#91;</span>'alert'<span class="br0">&#93;</span> = <span class="kw3">lambda</span> <span class="br0">&#123;</span> |x| <span class="kw3">puts</span> x <span class="br0">&#125;</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'alert<span class="br0">&#40;</span><span class="st0">&quot;Hello world!&quot;</span><span class="br0">&#41;</span>;'<span class="br0">&#41;</span></div>
</div>
<p>Johnson::Context#evaluate will also return the last statement evaluated.  We can evaluate an expression, and manipulate that expression in ruby land.  For example, I'll create an object in javascript, return it to ruby land, then access a property of the javascript object:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="kw3">require</span> 'johnson'</p>
<p>ctx = Johnson::Context.<span class="me1">new</span><br />
obj = ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'var foo = <span class="br0">&#123;</span> x: <span class="st0">&quot;hello world&quot;</span> <span class="br0">&#125;</span>; foo'<span class="br0">&#41;</span><br />
<span class="kw3">puts</span> obj.<span class="me1">x</span>&nbsp; <span class="co1"># =&gt; 'hello world' </span></div>
</div>
<p>We can even do the reverse by stuffing ruby objects in to the context:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">A = Struct.<span class="me1">new</span><span class="br0">&#40;</span>:foo<span class="br0">&#41;</span></p>
<p>ctx = Johnson::Context.<span class="me1">new</span><br />
ctx<span class="br0">&#91;</span>'alert'<span class="br0">&#93;</span> = <span class="kw3">lambda</span> <span class="br0">&#123;</span> |x| <span class="kw3">puts</span> x <span class="br0">&#125;</span><br />
ctx<span class="br0">&#91;</span>'a'<span class="br0">&#93;</span> = A.<span class="me1">new</span><span class="br0">&#40;</span><span class="st0">&quot;bar&quot;</span><span class="br0">&#41;</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'alert<span class="br0">&#40;</span>a.<span class="me1">foo</span><span class="br0">&#41;</span>;'<span class="br0">&#41;</span> <span class="co1"># =&gt; 'bar' </span></div>
</div>
<p>But it gets better.  We added a top level variable called "Ruby" that lets you access constants and globals from Ruby land.  We can rewrite the previous example completely in javascript:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ctx = Johnson::Context.<span class="me1">new</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span><span class="st0">&quot;var x = new (new Ruby.Struct(Johnson.symbolize('foo')));&quot;</span><span class="br0">&#41;</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span><span class="st0">&quot;x.foo = 'bar'&quot;</span><span class="br0">&#41;</span><br />
<span class="kw3">puts</span> ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'x'<span class="br0">&#41;</span>.<span class="me1">foo</span> <span class="co1"># =&gt; 'bar'</span><br />
<span class="kw3">puts</span> ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>'x'<span class="br0">&#41;</span>.<span class="kw1">class</span> <span class="co1"># =&gt; #&lt;Class:0x49714&gt; </span></div>
</div>
<p>Since the 'Ruby' constant delegates to Object, you can access any constant.  Including ones you've defined yourself.  We could, for example, look up a bunch of User records through rails:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ctx = Johnson::Context.<span class="me1">new</span><br />
ctx<span class="br0">&#91;</span>'alert'<span class="br0">&#93;</span> = <span class="kw3">lambda</span> <span class="br0">&#123;</span> |x| <span class="kw3">puts</span> x <span class="br0">&#125;</span><br />
ctx.<span class="me1">evaluate</span><span class="br0">&#40;</span>&lt;&lt;-<span class="kw1">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">for</span><span class="br0">&#40;</span>var user <span class="kw1">in</span> Ruby.<span class="me1">User</span>.<span class="me1">find</span><span class="br0">&#40;</span>Johnson.<span class="me1">symbolize</span><span class="br0">&#40;</span>'all'<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;alert<span class="br0">&#40;</span>user.<span class="me1">first_name</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#41;</span></div>
</div>
<p>You might be wondering what this Johnson.symbolize business is about.  Since Javascript doesn't have a concept of a symbol, we've created a helper to "mark" a string as a symbol and pass it back in to ruby land.</p>
<p>To conclude this update about my Johnson, I'd like to show off an interactive shell for Johnson (thanks to <a href="http://www.yehudakatz.com/" onclick="javascript:urchinTracker ('/outbound/article/www.yehudakatz.com');">Brohuda Katz</a>).  Johnson has an interactive shell that lets you try things out in javascript land or ruby land, and let you quickly switch between the two.  Typing 'js' will put in you the javascript shell, 'rb' will switch you to the ruby shell.  In the ruby shell, you can use the 'cx' variable to get ahold of you javascript context:</p>
<div class="codesnip-container" >$ ruby -I lib bin/johnson<br />
js> var x = { foo: 'bar', hello: function() { return 'world' } };<br />
=> nil<br />
js> rb<br />
rb> cx['x'].foo<br />
=> "bar"<br />
rb> cx['x'].hello()<br />
=> "world"<br />
rb></div>
<p>We aren't quite ready for a release yet, but if you'd like to play around with Johnson, you can pull it down from github <a href="http://github.com/jbarnette/johnson/tree/master" onclick="javascript:urchinTracker ('/outbound/article/github.com');">here</a>.  Just run 'rake', and you should have it compiled and running!</p>
<p>My next Johnson related post will be about Javascript parse trees and Javascript code generation.</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/04/23/take-it-to-the-limit-one-more-time/feed/</wfw:commentRss>
		</item>
		<item>
		<title>New Ruby Implementation - Brobinius</title>
		<link>http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/</link>
		<comments>http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 22:00:51 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[computadora]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/</guid>
		<description><![CDATA[Brobinius version 1.0.0 has been released!

http://brobinius.org/
http://tenderlovemaking.com/
&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;

I am happy to annouce the first release of my new fork of Ruby called
Brobinius.  The goal of Brobinius is to implement new language features
that I have noticed to be completely missing.
For example, Object#tase!  The tase method is featured in many other languages
but is sadly missing from Ruby. [...]]]></description>
			<content:encoded><![CDATA[<p>Brobinius version 1.0.0 has been released!</p>
<ul>
<li><a href="http://brobinius.org/" onclick="javascript:urchinTracker ('/outbound/article/brobinius.org');">http://brobinius.org/</a></li>
<li><a href="http://tenderlovemaking.com/" >http://tenderlovemaking.com/</a></li>
<li><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;:&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;">&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;</a></li>
</ul>
<p>I am happy to annouce the first release of my new fork of Ruby called<br />
Brobinius.  The goal of Brobinius is to implement new language features<br />
that I have noticed to be completely missing.</p>
<p>For example, Object#tase!  The tase method is featured in many other languages<br />
but is sadly missing from Ruby.  Brobinius has a fully implemented tase! method.</p>
<div class="codesnip-container" >>> x = Class.new<br />
  => #&lt;Class:0x3632ec><br />
  >> x.tase!<br />
  RuntimeError: Don't tase me bro<br />
    from (irb):2:in `tase!'<br />
    from (irb):6<br />
  >></div>
<p>Brobinius also has fully serializable kittenuations.  You can create and<br />
serialize your kittenuations, then pick up your snuggling where you left off.<br />
For example:</p>
<div class="codesnip-container" >>> lol = Kittenuation.new {<br />
  ?> look_cute<br />
  >> throw :yarn<br />
  >> look_cute<br />
  >> }<br />
  => #&lt;Kittenuation:0x366244><br />
  >> lol.snuggle<br />
  >> Marshal.load(Marshal.dump(lol)).snuggle</div>
<p>Since Brobinius's kittenuations are serializable, you can share them over the<br />
network with friends!</p>
<p>Brobinius also features screencasts with automatic YouTube uploads.  All you<br />
have to do write your program, then pass the --screencast option to Brobinius.<br />
Brobinius will automatically create a screencast of your program and upload it<br />
to YouTube:</p>
<div class="codesnip-container" >$ brobinius --screencast my_code.rb</div>
<p>You can even add the --geoff flag to create screencasts with Geoffrey<br />
Grosenbach doing the voice over.</p>
<ul>
<li><a href="http://brobinius.org/" onclick="javascript:urchinTracker ('/outbound/article/brobinius.org');">http://brobinius.org/</a></li>
<li><a href="http://tenderlovemaking.com/" >http://tenderlovemaking.com/</a></li>
<li><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;:&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;">&#97;&#x61;&#114;&#x6f;&#110;&#x40;&#116;&#x65;n&#100;&#x65;&#114;&#x6c;&#111;&#x76;&#101;&#x6d;&#x61;&#107;&#x69;&#110;&#x67;&#46;&#x63;o&#109;</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/04/01/new-ruby-implementation-brobinius/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Laser Etch My Macbook Air</title>
		<link>http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/</link>
		<comments>http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/#comments</comments>
		<pubDate>Thu, 20 Mar 2008 22:03:03 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[computadora]]></category>

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

		<category><![CDATA[macbook air]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/</guid>
		<description><![CDATA[Dear Lazyweb,
I would really like to Laser Etch my Macbook Air with Martha Stewart's face.  Where can I get that done?  How much would it cost?
]]></description>
			<content:encoded><![CDATA[<p>Dear Lazyweb,</p>
<p>I would really like to <a href="http://blog.makezine.com/archive/2008/02/macbook_air_yes_it_can_be.html" onclick="javascript:urchinTracker ('/outbound/article/blog.makezine.com');">Laser Etch</a> my Macbook Air with <a href="http://blogs1.marthastewart.com/martha/2008/03/my-new-macbook.html" onclick="javascript:urchinTracker ('/outbound/article/blogs1.marthastewart.com');">Martha Stewart's</a> face.  Where can I get that done?  How much would it cost?</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/03/20/laser-etch-my-macbook-air/feed/</wfw:commentRss>
		</item>
		<item>
		<title>mechanize version 0.7.5 has been released!</title>
		<link>http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/</link>
		<comments>http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 17:19:47 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[life]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/</guid>
		<description><![CDATA[The Mechanize library is used for automating interaction with websites.
Mechanize automatically stores and sends cookies, follows redirects,
can follow links, and submit forms.  Form fields can be populated and
submitted.  Mechanize also keeps track of the sites that you have visited as
a history.
Changes:
# Mechanize CHANGELOG
## 0.7.5


Fixed a bug when fetching files and not pages.  [...]]]></description>
			<content:encoded><![CDATA[<p>The Mechanize library is used for automating interaction with websites.<br />
Mechanize automatically stores and sends cookies, follows redirects,<br />
can follow links, and submit forms.  Form fields can be populated and<br />
submitted.  Mechanize also keeps track of the sites that you have visited as<br />
a history.</p>
<p>Changes:</p>
<p># Mechanize CHANGELOG</p>
<p>## 0.7.5</p>
<ul>
<li>
<p>Fixed a bug when fetching files and not pages.  Thanks Mat Schaffer!</p>
</li>
<li>
<p><a href="http://mechanize.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/mechanize.rubyforge.org');">http://mechanize.rubyforge.org/</a></p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/03/15/mechanize-version-075-has-been-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Profiling Database Queries in Rails</title>
		<link>http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/</link>
		<comments>http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 21:16:37 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[computadora]]></category>

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

		<guid isPermaLink="false">http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/</guid>
		<description><![CDATA[Despite the recent Ruby webserver speed contests, most of the slowness at my job results from slow (or too many) database queries.
To help keep database queries down, I added a stats to every page that shows the number of queries vs. cache hits, the number of rows returned, and the amount of data transferred from [...]]]></description>
			<content:encoded><![CDATA[<p>Despite the recent Ruby webserver <a href="http://www.rubyinside.com/ebb-web-framework-http-server-786.html" onclick="javascript:urchinTracker ('/outbound/article/www.rubyinside.com');">speed contests</a>, most of the slowness at <a href="http://adready.com/" onclick="javascript:urchinTracker ('/outbound/article/adready.com');">my job</a> results from slow (or too many) database queries.</p>
<p>To help keep database queries down, I added a stats to every page that shows the number of queries vs. cache hits, the number of rows returned, and the amount of data transferred from the database.  In this screenshot I'm using the "live" environment, 3 cache hits, 169 misses, 577 rows returned, and 458.9k data transferred.  Clicking the box hides it, and clicking "Super Hide!" hides the box and sets a cookie so that the box doesn't show up again for a while.</p>
<p><a href="http://www.flickr.com/photos/aaronp/2331927606/" title="Debug Window by fakebeard, on Flickr" onclick="javascript:urchinTracker ('/outbound/article/www.flickr.com');"><img src="http://farm3.static.flickr.com/2106/2331927606_46cc9fa937.jpg" width="500" height="187" alt="Debug Window" /></a></p>
<p>To get this working, first I monkey patch the MysqlAdapter to collect database stats:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ActiveRecord::ConnectionAdapters::MysqlAdapter.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; @@stats_queries = @@stats_bytes = @@stats_rows = <span class="nu0">0</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">get_stats</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> :queries =&gt; @@stats_queries,<br />
&nbsp; &nbsp; &nbsp; &nbsp; :rows =&gt; @@stats_rows,<br />
&nbsp; &nbsp; &nbsp; &nbsp; :bytes =&gt; @@stats_bytes <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">reset_stats</span><br />
&nbsp; &nbsp; &nbsp; @@stats_queries = @@stats_bytes = @@stats_rows = <span class="nu0">0</span><br />
&nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> select_with_stats<span class="br0">&#40;</span>sql, name<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; bytes = <span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; rows = select_without_stats<span class="br0">&#40;</span>sql, name<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; rows.<span class="me1">each</span> <span class="kw1">do</span> |row|<br />
&nbsp; &nbsp; &nbsp; &nbsp; row.<span class="me1">each</span> <span class="kw1">do</span> |key, value|<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes += key.<span class="me1">length</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bytes += value.<span class="me1">length</span> <span class="kw1">if</span> value<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; @@stats_queries += <span class="nu0">1</span><br />
&nbsp; &nbsp; &nbsp; @@stats_rows += rows.<span class="me1">length</span><br />
&nbsp; &nbsp; &nbsp; @@stats_bytes += bytes<br />
&nbsp; &nbsp; &nbsp; rows<br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; alias_method_chain :<span class="kw3">select</span>, :stats<br />
&nbsp; <span class="kw1">end</span></div>
</div>
<p>Next I patched the QueryCache to keep track of hits and misses:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ActiveRecord::ConnectionAdapters::QueryCache.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; @@hits = @@misses = <span class="nu0">0</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">get_stats</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> :hits =&gt; @@hits,<br />
&nbsp; &nbsp; &nbsp; &nbsp; :misses =&gt; @@misses <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">reset_stats</span><br />
&nbsp; &nbsp; &nbsp; @@hits = @@misses = <span class="nu0">0</span><br />
&nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> cache_sql_with_stats<span class="br0">&#40;</span>sql, &amp;block<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">if</span> @query_cache.<span class="me1">has_key</span>?<span class="br0">&#40;</span>sql<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @@hits += <span class="nu0">1</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @@misses += <span class="nu0">1</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; &nbsp; cache_sql_without_stats<span class="br0">&#40;</span>sql, &amp;block<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; &nbsp; alias_method_chain :cache_sql, :stats<br />
&nbsp; <span class="kw1">end</span></div>
</div>
<p>Then modify ActionController to reset stats for each request:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;">ActionController::Base.<span class="me1">module_eval</span> <span class="kw1">do</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> perform_action_with_reset<br />
&nbsp; &nbsp; &nbsp; ActiveRecord::ConnectionAdapters::MysqlAdapter::reset_stats<br />
&nbsp; &nbsp; &nbsp; ActiveRecord::ConnectionAdapters::QueryCache::reset_stats<br />
&nbsp; &nbsp; &nbsp; perform_action_without_reset<br />
&nbsp; &nbsp; <span class="kw1">end</span></p>
<p>&nbsp; &nbsp; alias_method_chain :perform_action, :reset</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> active_record_runtime<span class="br0">&#40;</span>runtime<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; stats = ActiveRecord::ConnectionAdapters::MysqlAdapter::get_stats<br />
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;#{super} #{sprintf(&quot;</span>%.1fk<span class="st0">&quot;, stats[:bytes].to_f / 1024)} queries: #{stats[:queries]}&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">end</span><br />
&nbsp; <span class="kw1">end</span></div>
</div>
<p>Just drop all that inside the after_initialize in your development.rb and you'll get the nice stats.  After that, just create a partial that displays the stats and include the partial at the bottom of your layout.  Our partial looks like this:</p>
<div class="codesnip-container" >
<div class="codesnip" style="font-family: monospace;"><span class="sc2">&lt;% unless %w<span class="br0">&#40;</span>production test<span class="br0">&#41;</span>.include?<span class="br0">&#40;</span>RAILS_ENV<span class="br0">&#41;</span> -%<span class="kw2">&gt;</span></span><br />
&nbsp; <span class="sc2"><a href="http://december.com/html/4/element/h4.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;h4</span></a> <span class="kw3">id</span>=<span class="st0">&quot;debug&quot;</span> <span class="kw3">onclick</span>=<span class="st0">&quot;$(this).remove()&quot;</span> <span class="kw3">style</span>=<span class="st0">&quot;background:pink;text-align:center;position:absolute;top:16px;left:35%;padding:0.5em;border: 2px solid red;&quot;</span><span class="kw2">&gt;</span></span><br />
&nbsp; <span class="sc2">&lt;%= RAILS_ENV %<span class="kw2">&gt;</span></span><br />
&nbsp; <span class="sc2"><a href="http://december.com/html/4/element/br.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;br</span></a> /<span class="kw2">&gt;</span></span><br />
&nbsp; <span class="sc2">&lt;% if ActiveRecord::ConnectionAdapters::QueryCache.respond_to?<span class="br0">&#40;</span>:get_stats<span class="br0">&#41;</span> %<span class="kw2">&gt;</span></span><br />
&nbsp; &nbsp; <span class="sc2">&lt;% stats = ActiveRecord::ConnectionAdapters::QueryCache.get_stats %<span class="kw2">&gt;</span></span><br />
&nbsp; &nbsp; Queries: <span class="sc2">&lt;%= stats<span class="br0">&#91;</span>:hits<span class="br0">&#93;</span> %<span class="kw2">&gt;</span></span> / <span class="sc2">&lt;%= stats<span class="br0">&#91;</span>:misses<span class="br0">&#93;</span> %<span class="kw2">&gt;</span></span> /<br />
&nbsp; &nbsp; <span class="sc2">&lt;%= number_to_percentage<span class="br0">&#40;</span><span class="br0">&#40;</span>stats<span class="br0">&#91;</span>:hits<span class="br0">&#93;</span>.to_f / <span class="br0">&#40;</span>stats<span class="br0">&#91;</span>:hits<span class="br0">&#93;</span> + stats<span class="br0">&#91;</span>:misses<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> * <span class="nu0">100</span>, :precision =<span class="kw2">&gt;</span></span> 0) %&gt;<br />
&nbsp; &nbsp; |<br />
&nbsp; <span class="sc2">&lt;% end %<span class="kw2">&gt;</span></span><br />
&nbsp; <span class="sc2">&lt;% if ActiveRecord::ConnectionAdapters::MysqlAdapter.respond_to?<span class="br0">&#40;</span>:get_stats<span class="br0">&#41;</span> %<span class="kw2">&gt;</span></span><br />
&nbsp; &nbsp; <span class="sc2">&lt;% stats = ActiveRecord::ConnectionAdapters::MysqlAdapter.get_stats %<span class="kw2">&gt;</span></span><br />
&nbsp; &nbsp; Rows: <span class="sc2">&lt;%= stats<span class="br0">&#91;</span>:<span class="kw3">rows</span><span class="br0">&#93;</span> %<span class="kw2">&gt;</span></span> |<br />
&nbsp; &nbsp; Transfer: <span class="sc2">&lt;%= sprintf<span class="br0">&#40;</span><span class="st0">&quot;%.1fk&quot;</span>, stats<span class="br0">&#91;</span>:bytes<span class="br0">&#93;</span>.to_f / <span class="nu0">1024</span><span class="br0">&#41;</span> %<span class="kw2">&gt;</span></span><br />
&nbsp; <span class="sc2">&lt;% end %<span class="kw2">&gt;</span></span><br />
&nbsp; <span class="sc2"><a href="http://december.com/html/4/element/p.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;p</span></a> <span class="kw3">style</span>=<span class="st0">&quot;margin:0&quot;</span><span class="kw2">&gt;</span></span><br />
&nbsp; &nbsp; <span class="sc2"><a href="http://december.com/html/4/element/a.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;a</span></a> <span class="kw3">style</span>=<span class="st0">&quot;color:magenta&quot;</span> <span class="kw3">href</span>=<span class="st0">&quot;#&quot;</span> <span class="kw3">onclick</span>=<span class="st0">&quot;superHide()&quot;</span><span class="kw2">&gt;</span></span>super hide!<span class="sc2"><span class="kw2">&lt;/a&gt;</span></span><br />
&nbsp; <span class="sc2"><span class="kw2">&lt;/p&gt;</span></span><br />
&nbsp; <span class="sc2"><span class="kw2">&lt;/h4&gt;</span></span><br />
&nbsp; <span class="sc2"><a href="http://december.com/html/4/element/script.html" onclick="javascript:urchinTracker ('/outbound/article/december.com');"><span class="kw2">&lt;script</span></a> <span class="kw3">type</span>=<span class="st0">&quot;text/javascript&quot;</span><span class="kw2">&gt;</span></span><br />
&nbsp; &nbsp; function superHide() {<br />
&nbsp; &nbsp; &nbsp; document.cookie = 'debug=hidden; path=/; domain=<span class="sc2">&lt;%= request.host %<span class="kw2">&gt;</span></span>; max-age=14400';<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; if(document.cookie.indexOf('debug=hidden') != -1) {<br />
&nbsp; &nbsp; &nbsp; $('debug').hide();<br />
&nbsp; &nbsp; }<br />
&nbsp; <span class="sc2"><span class="kw2">&lt;/script&gt;</span></span><br />
<span class="sc2">&lt;% end -%<span class="kw2">&gt;</span></span></div>
</div>
<p>It's a little work, but it helps keep my mind on reducing the queries.  With enough work, one of these days the speed of the webserver will matter to me.  Thanks to <a href="http://gurge.com/blog/2006/11/09/rails-sql-logging-improvements/" onclick="javascript:urchinTracker ('/outbound/article/gurge.com');">Adam Doppelt</a> for the basis of this monkey patch.  Any bugs are mine, not his!</p>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/03/13/profiling-database-queries-in-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>mechanize version 0.7.1 has been released!</title>
		<link>http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/</link>
		<comments>http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 03:42:26 +0000</pubDate>
		<dc:creator>Aaron Patterson</dc:creator>
		
		<category><![CDATA[life]]></category>

		<guid isPermaLink="false">http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/</guid>
		<description><![CDATA[The Mechanize library is used for automating interaction with websites.
Mechanize automatically stores and sends cookies, follows redirects,
can follow links, and submit forms.  Form fields can be populated and
submitted.  Mechanize also keeps track of the sites that you have visited as
a history.
Changes:
# Mechanize CHANGELOG
## 0.7.1

Added iPhone to the user agent aliases. [#17572]
Fixed a bug [...]]]></description>
			<content:encoded><![CDATA[<p>The Mechanize library is used for automating interaction with websites.<br />
Mechanize automatically stores and sends cookies, follows redirects,<br />
can follow links, and submit forms.  Form fields can be populated and<br />
submitted.  Mechanize also keeps track of the sites that you have visited as<br />
a history.</p>
<p>Changes:</p>
<p># Mechanize CHANGELOG</p>
<p>## 0.7.1</p>
<ul>
<li>Added iPhone to the user agent aliases. [#17572]</li>
<li>Fixed a bug with EOF errors in net/http.  [#17570]</li>
<li>
<p>Handling 0 length gzipped responses. [#17471]</p>
</li>
<li>
<p><a href="http://mechanize.rubyforge.org/" onclick="javascript:urchinTracker ('/outbound/article/mechanize.rubyforge.org');">http://mechanize.rubyforge.org/</a></p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tenderlovemaking.com/2008/03/04/mechanize-version-071-has-been-released/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
