<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Off the Line - Home</title>
  <id>tag:offtheline.net,2008:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.2">Mephisto Noh-Varr</generator>
  <link href="http://offtheline.net/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://offtheline.net/" rel="alternate" type="text/html"/>
  <updated>2008-04-01T04:05:16Z</updated>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2008-04-01:142</id>
    <published>2008-04-01T04:05:00Z</published>
    <updated>2008-04-01T04:05:16Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2008/4/1/rails-plugin-acts_as_fu" rel="alternate" type="text/html"/>
    <title>Rails Plugin: acts_as_fu</title>
<content type="html">
            &lt;p&gt;We&#8217;ve all seen the job listings. We know what they&#8217;re looking for. &lt;strong&gt;Rockstars.&lt;/strong&gt; &lt;em&gt;Code Monkeys.&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Rails Ninjas.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;And you&#8217;re left thinking, &#8220;But I&#8217;m just a programmer.&#8221; Well, not anymore. Today, you become a &lt;strong&gt;Rails Kung-Fu Master!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;&#8220;Not me,&#8221; you say. &#8220;I&#8217;ve already tried using all the acts_as_something plugins and all the something_fu plugins; and I&#8217;m still not a Rockstar &lt;em&gt;or&lt;/em&gt; a Ninja. I&#8217;m barely a Code Simian!&#8221;&lt;/p&gt;


	&lt;p&gt;Sounds like you&#8217;ve tried the rest &#8211; now try the best! That&#8217;s right: it&#8217;s the new and improved &lt;strong&gt;ActsAsFu&lt;/strong&gt; Rails plugin!&lt;/p&gt;


	&lt;h2&gt;Three Easy Steps to Becoming a Rails Kung-Fu Master:&lt;/h2&gt;


	&lt;h3&gt;1. Stop web server&lt;/h3&gt;


&lt;pre&gt;&lt;code&gt;mongrel_rails stop&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;2. Install Plugin&lt;/h3&gt;


&lt;pre&gt;&lt;code&gt;./script/plugin install http://svn.offtheline.net/plugins/acts_as_fu&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;3. Start web server&lt;/h3&gt;


&lt;pre&gt;&lt;code&gt;mongrel_rails start&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;(note: if you&#8217;re using mongrel_cluster, thin, piston, or anything like that, these instructions don&#8217;t apply to you &#8211; you figure it out yourself, you Rockstar Ninja!)&lt;/p&gt;


	&lt;p&gt;Now you&#8217;re on your way to programming stardom! Catch ya on fame&#8217;s backside, my friend!&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Bonus Round:&lt;/em&gt; If you work on a team, don&#8217;t forget to check this awesome plugin into your repository (or as the ninjas say, &lt;em&gt;svn ci -m &#8216;added l33t skillz&#8217;&lt;/em&gt;). Your teammates will undoubtedly be very impressed by your jujitsu karate haxxing abilities. If you push it up to your production server, your boss &lt;em&gt;might even give you a raise!&lt;/em&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2008-03-13:138</id>
    <published>2008-03-13T06:00:00Z</published>
    <updated>2008-03-17T14:29:15Z</updated>
    <category term="Development"/>
    <category term="Javascript"/>
    <link href="http://offtheline.net/2008/3/13/moveablemap-or-anything-else-in-a-viewport" rel="alternate" type="text/html"/>
    <title>MoveableMap (or anything else in a 'viewport')</title>
<content type="html">
            &amp;lt;style type=&quot;text/css&quot;&gt;
    #map_holder { width: 256px; height: 256px; overflow: hidden; padding:0px; position:relative; border: 3px dotted #990; }
    #the_map { border:3px solid #550; width: 512px; height: 512px;left:-128px; top:-128px; position:relative; }
&amp;lt;/style&gt;

&lt;div&gt;
  &lt;div&gt;
     &amp;lt;!- just empty to give us a div with a image background&#8212;&gt;
  &lt;/div&gt;
&lt;/div&gt;

	&lt;p&gt;MoveableMap is a javascript library that allows you to turn any block of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; into a draggable, moveable entity within a viewport. Similar to the behavior of Google Maps, but hopefully very easy to implement. On the right here, you can see a real simple example; it&#8217;s just a &lt;em&gt;div&lt;/em&gt; block with an &lt;em&gt;img&lt;/em&gt; element in the middle of it.&lt;/p&gt;


	&lt;p&gt;How simple is the code for this example? The moveableMap library is built on top of the &lt;a href=&quot;http://prototypejs.org&quot;&gt;fantastic prototype.js library&lt;/a&gt;, the &lt;a href=&quot;http://script.aculo.us&quot;&gt;slick scriptaculous library&lt;/a&gt;, and the &lt;a href=&quot;http://lowpro.stikipad.com/home/&quot;&gt;enlightening Low Pro library&lt;/a&gt;. It takes just a little &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; magic and a little unobtrusive javascript to get the behavior you see here.&lt;/p&gt;


	&lt;p&gt;We need two elements: the &#8220;container&#8221; block, and the block inside the viewport. In this example, they&#8217;ll both be &lt;em&gt;divs&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Our &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; sets us up:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;#map_holder {    /* the 'container' */&lt;tt&gt;
&lt;/tt&gt;  width: 256px; height: 256px;            /* size of the viewable area */&lt;tt&gt;
&lt;/tt&gt;  overflow: hidden; position:relative;    /* necessary to make the whole thing work */&lt;tt&gt;
&lt;/tt&gt;  padding:0px; border: 3px dotted #990;   /* aesthetics */&lt;tt&gt;
&lt;/tt&gt;}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;#the_map {   /* the inner block */&lt;tt&gt;
&lt;/tt&gt;  width: 512px; height: 512px;   /* defining the size keeps us from getting squashed */&lt;tt&gt;
&lt;/tt&gt;  left:-128px; top:-128px;       /* the starting offset - always negative */&lt;tt&gt;
&lt;/tt&gt;  position:relative;             /* better believe it, you need it */&lt;tt&gt;
&lt;/tt&gt;  border:3px solid #550;         /* so we can see the edge of the map */&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;A little javascript to create the MoveableMap object and apply some behaviors:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;// we don't attempt anything until the DOM is loaded&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;Event.observe(&lt;span class=&quot;pt&quot;&gt;window&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// create a new MoveableMap object and pass in the two elements we need&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// I'm using the prototype shortcut $('my_html_id') to represent an element:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  mainMap = new MoveableMap($(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;the_map&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;), $(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;map_holder&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;));&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// here's the Low Pro unobtrusive helper:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  Event.addBehavior({&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// specify the CSS selector for the inner block and &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// apply the MapDrag behavior to it (specifying the MoveableMap object)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;#the_map&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; : MapDrag(mainMap)&lt;tt&gt;
&lt;/tt&gt;  });&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;And the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, which is pretty trim:&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;map_holder&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;id&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;the_map&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;style&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;background: url(/examples/map/images/fakemap.jpg)&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;     &lt;span class=&quot;er&quot;&gt;&amp;lt;&lt;/span&gt;!- just empty to give us a div with a image background --&lt;span class=&quot;er&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
Notice the lack of onclick, onmousedown, onmouseup in the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;? That&#8217;s the unobtrusive bit, baby. All that stuff is handled by the MoveableMap library (as Behaviors a la Low Pro). 
&lt;/p&gt;

&lt;p&gt;
Let&#8217;s see some more impressive examples. Here&#8217;s something similar to what&#8217;s on the page here, but with a compass in the corner that you can click on to slide the map in that direction. Double-click to slide all the way to the edge. Take note of the fake &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; attribute called &#8216;mapdir&#8217; inside each compass direction. &lt;br /&gt;
Check it: &lt;a href=&quot;http://offtheline.net/examples/map/simplemap.html&quot;&gt;Old World Map with Compass&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
That was fun. What else you got? Here&#8217;s a (crudely drawn) map of Aethora. The &#8216;compass&#8217; from the previous example has been placed around the edges of the map to give the viewer a feeling of clicking on the sides of the map to make it scroll. Additionally, you can see a list of cities below the map &#8211; click on any city to make the map slide to that location. In reality, the &#8216;cities&#8217; are positioned &lt;em&gt;div&lt;/em&gt; elements. The clickable element has a fake &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; attribute, targetelement, which names the id of the element you want to center the map on. &lt;br /&gt;
Peep: &lt;a href=&quot;http://offtheline.net/examples/map/worldmap.html&quot;&gt;Fantasy map with clickable city names&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
This last map is more of the same really, but the big deal is that the inner block of code is a table. It&#8217;s basically here to prove to you that you can put some pretty complex stuff on the inside (not just a jpg of a street map) and still move the map around. This example is closer to the actual purpose I created this library for (&lt;a href=&quot;http://aethora.com&quot;&gt;Aethora&lt;/a&gt;, my &lt;span class=&quot;caps&quot;&gt;RPG&lt;/span&gt; written in Ruby on Rails and javascript).&lt;br /&gt;
Observe: &lt;a href=&quot;http://offtheline.net/examples/map/tablemap.html&quot;&gt;Tiled (table-based) &#8216;battle field&#8217;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Here&#8217;s the &lt;a href=&quot;/javascripts/moveablemap.js&quot;&gt;MoveableMap js file&lt;/a&gt;. You&#8217;ll need to load prototype, the scriptaculous effects.js library, Low Pro, MoveableMap, and then your own javascript in that order. Check out the source code of those examples above for more details. The code seems to work well in Firefox, &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;, and &lt;span class=&quot;caps&quot;&gt;IE7&lt;/span&gt;. In Opera, it seems to do a slight, 3-4 pixel detour before getting on track when using the compass movement. If anyone can tell me how to fix it, I&#8217;ll buy you a beer/coffee (I had to sell my soul just to get it to work in IE). I haven&#8217;t had a chance to test it in Safari or anything else, but I&#8217;d love to hear how it works out.&lt;/p&gt;

&lt;p&gt;So enjoy &#8211; and let me know if you find any bugs. And definitely let me know if you find it useful!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; Here&#8217;s a great example, this one provided Kahil, who is the developer of a browser-based game called &lt;span class=&quot;caps&quot;&gt;WMD &lt;/span&gt;Tank Battle: 
&lt;a href=&quot;http://www.wmdtb.com/atmt/scroller/spyplane.html&quot;&gt;Vertical Scrolling a la old school arcade shooters&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2008-02-28:133</id>
    <published>2008-02-28T01:00:00Z</published>
    <updated>2008-02-28T01:02:14Z</updated>
    <category term="Development"/>
    <category term="Javascript"/>
    <link href="http://offtheline.net/2008/2/28/parallax-animation-with-css-js" rel="alternate" type="text/html"/>
    <title>Parallax Animation with CSS/JS</title>
<content type="html">
            &lt;p&gt;I just read an &lt;a href=&quot;http://www.thinkvitamin.com/features/design/how-to-recreate-silverbacks-parallax&quot;&gt;article on ThinkVitamin&lt;/a&gt; about creating some nifty &lt;a href=&quot;http://en.wikipedia.org/wiki/Parallax_scrolling&quot;&gt;parallax scrolling style animation&lt;/a&gt; by using multiple layers of images that shrink at various proportions when you resize the browser window. A few of the comments noted that it&#8217;s unfortunate that the animation is only apparent when resizing the window, and something that would go fairly unnoticed by most people.&lt;/p&gt;


	&lt;p&gt;Being a lover of all video games, old and new, I thought this trick that I&#8217;ve seen in so many side scrollers was brilliant. My first thought was how to combine this with &lt;a href=&quot;http://script.aculo.us&quot;&gt;Script.aculo.us&#8217;s&lt;/a&gt; Morph effect so that you can see the animation without actually resizing the browser window. Turns out it wasn&#8217;t that hard &#8211; &lt;a href=&quot;http://offtheline.net/examples/parallax/&quot;&gt;check it out!&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Apologies for: (a) stealing the images from Paul&#8217;s example on the ThinkVitamin site for demonstration purposes and (b) for using onclick (I should be practicing unobtrusive javascript, but this is a really simple example that I wanted to crank out).&lt;/p&gt;


	&lt;p&gt;Pretty slick. Now I&#8217;m determined to find a need to use this trick in &lt;a href=&quot;http://aethora.com&quot;&gt;Aethora&lt;/a&gt;....&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2008-02-24:132</id>
    <published>2008-02-24T17:12:00Z</published>
    <updated>2008-02-24T17:35:11Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2008/2/24/rake-and-truncated-task-descriptions" rel="alternate" type="text/html"/>
    <title>rake and truncated task descriptions</title>
<content type="html">
            &lt;p&gt;Has anyone noticed that the newer rake (as of 8.0) truncates task descriptions a lot shorter than the old rake (7.3)? Here&#8217;s what I mean:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;jason@old-box:~/dev/some_app$ rake --version
rake, version 0.7.3
jason@old-box:~/dev/some_app$ rake -T rails
(in /home/jason/dev/some_app)
rake doc:clobber_rails         # Remove rdoc products
rake doc:rails                 # Build the rails HTML Files
rake doc:rerails               # Force a rebuild of the RDOC files
rake rails:freeze:edge         # Lock to latest Edge Rails or a specific revision with REVISION=X (ex: REVISION=4021) or a tag with TAG=Y (ex: TAG=rel_1-1-0)
(etc...)&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;jason@new-box:~/dev/some_app$ rake --version
rake, version 0.8.1
jason@new-box:~/dev/some_app$ rake -T rails
(in /home/jason/dev/some_app)
rake doc:clobber_rails         # Remove rdoc products
rake doc:rails                 # Build the rails HTML Files
rake doc:rerails               # Force a rebuild of the RDOC files
rake rails:freeze:edge         # Lock to latest Edge Rails or a specific re...
(etc...)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you dig into the rake 8.0/8.1 gems, you might notice that the task list output is being truncated to 80 columns. This change was the result of a suggestion to make the task list more condensed, while at the same time adding a -D option for full descriptions (&lt;a href=&quot;http://rubyforge.org/forum/forum.php?forum_id=20061&quot;&gt;Rake 0.8.0 Released [rubyforge.org]&lt;/a&gt;):&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;jason@jason-4200:~/dev/phoenixmedia$ rake -D rails
(in /home/jason/dev/phoenixmedia)
rake doc:clobber_rails
    Remove rdoc products

rake doc:rails
    Build the rails HTML Files

rake doc:rerails
    Force a rebuild of the RDOC files

rake rails:freeze:edge
    Lock to latest Edge Rails or a specific revision with REVISION=X (ex: REVISION=4021) or a tag with TAG=Y (ex: TAG=rel_1-1-0)

(etc...)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;...but as you can see, the full-description version puts a bunch of line breaks in the output.&lt;/p&gt;


	&lt;p&gt;I liked it better the old way! I don&#8217;t doubt the change was made for the best (line-wrapped descriptions in a small window are not very nice to look at), but I&#8217;d really like the option to set my own column width. For now, I&#8217;ve resorted to dropping this rake task into my Rails apps (you can save this as something.rake under my_rails_app_root/lib/tasks):&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;NUMBER_OF_COLUMNS_TO_DISPLAY&lt;/span&gt; = &lt;span class=&quot;i&quot;&gt;180&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;task &lt;span class=&quot;sy&quot;&gt;:t&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:p&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |t, args|&lt;tt&gt;
&lt;/tt&gt;  pattern = args.p || &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  displayable_tasks = &lt;span class=&quot;co&quot;&gt;Rake&lt;/span&gt;.application.tasks.select { |t|&lt;tt&gt;
&lt;/tt&gt;    t.comment &amp;amp;&amp;amp; t.name =~ &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;pattern&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  width = displayable_tasks.collect { |t| t.name_with_args.length }.max || &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  cols = &lt;span class=&quot;co&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;RAKE_DESC_COLS&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] ? &lt;span class=&quot;co&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;RAKE_DESC_COLS&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].to_i : &lt;span class=&quot;co&quot;&gt;NUMBER_OF_COLUMNS_TO_DISPLAY&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  max_column = cols - &lt;span class=&quot;co&quot;&gt;Rake&lt;/span&gt;.application.name.size - width - &lt;span class=&quot;i&quot;&gt;7&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  displayable_tasks.each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |t|&lt;tt&gt;
&lt;/tt&gt;    printf &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Rake&lt;/span&gt;.application.name&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; %-&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;width&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;s  # %s&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;      t.name_with_args, truncate(t.comment, max_column)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;truncate&lt;/span&gt;(string, width)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; string.nil?&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; string.length &amp;lt;= width&lt;tt&gt;
&lt;/tt&gt;    string&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    string[&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;, width&lt;span class=&quot;i&quot;&gt;-3&lt;/span&gt;] + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Note that this uses the new rake 8.x feature of &lt;a href=&quot;http://rubyforge.org/pipermail/rake-devel/2007-December/000352.html&quot;&gt;allowing for command-line arguments&lt;/a&gt; to get passed into a task, so we can pass in a &#8216;pattern&#8217; to search on without using an environment variable. Now I can do this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;jason@new-box:~/dev/some_app$ rake t[rails]
(in /home/jason/dev/some_app)
rake doc:clobber_rails         # Remove rdoc products
rake doc:rails                 # Build the rails HTML Files
rake doc:rerails               # Force a rebuild of the RDOC files
rake rails:freeze:edge         # Lock to latest Edge Rails or a specific revision with REVISION=X (ex: REVISION=4021) or a tag with TAG=Y (ex: TAG=rel_1-1-0)
(etc...)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I set the default number of columns at 180 because that&#8217;s just right for a maximized terminal window with the Monospace font (default in Ubuntu) at 9pt on my 1280&#215;1024 display. Of course, I left an option to easily change the number of columns via an environment variable. For example, on my &lt;a href=&quot;http://eeepc.asus.com/global/&quot;&gt;EeePC&lt;/a&gt;, 110 is about right:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;jason@eeePC:~/dev/some_app$ export RAKE_DESC_COLS=110
jason@eeePC:~/dev/some_app$ rake t[rails] 
(in /home/jason/dev/some_app)
(in /home/jason/dev/phoenixmedia)
rake doc:clobber_rails         # Remove rdoc products
rake doc:rails                 # Build the rails HTML Files
rake doc:rerails               # Force a rebuild of the RDOC files
rake rails:freeze:edge         # Lock to latest Edge Rails or a specific revision with REVISION=X (ex: RE...
(etc...)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Hey, I can actually read the descriptions again!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2008-02-17:129</id>
    <published>2008-02-17T21:16:00Z</published>
    <updated>2008-02-18T20:15:17Z</updated>
    <category term="Development"/>
    <category term="Javascript"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2008/2/17/unobtrusive-image-rollovers-with-low-pro" rel="alternate" type="text/html"/>
    <title>Unobtrusive Image Rollovers with Low Pro</title>
<content type="html">
            &lt;p&gt;This week I finally broke down and decided to find out what this &lt;a href=&quot;http://en.wikipedia.org/wiki/Unobtrusive_JavaScript&quot;&gt;Unobtrusive Javascript&lt;/a&gt; thing is all about. First, I got really excited about trying out the &lt;span class=&quot;caps&quot;&gt;UJS&lt;/span&gt; plugin for Rails. I&#8217;m not linking to it, because after a couple of hours of digging around, Googling for the errors I was getting and finally digging into the source to find out it was breaking the tag_options helper in Rails 2, I discovered it&#8217;s &lt;a href=&quot;http://www.danwebb.net/2007/6/16/the-state-and-future-of-the-ujs-plugin&quot;&gt;no longer a supported plugin&lt;/a&gt;. Dan Webb, the original author, came to the conclusion that the unobtrusive message was not getting through to the typical Rails developer who picked up the plugin for it&#8217;s shortcuts. He pulled the lowpro.js library out of the plugin and ditched the Rails bits. I think it was a good move (I just wish someone would update ujs4rails.com to say something to that effect &#8211; it&#8217;s still the same page it was over a year ago, and it really sells the plugin well&#8230;)&lt;/p&gt;


	&lt;p&gt;There&#8217;s not really a lot of documentation for Low Pro out there, but to be honest, once you start using it I think you find there really isn&#8217;t a lot to it. Built on &lt;a href=&quot;http://prototypejs.org&quot;&gt;prototype&lt;/a&gt;, the lowpro.js file is only 300 or so lines of code, including some helpful comments. There are some links on the &lt;a href=&quot;http://lowpro.stikipad.com/home/&quot;&gt;lowpro wiki&lt;/a&gt; to a couple blog posts with examples. In particular I found &lt;a href=&quot;http://jlaine.net/2007/8/6/from-rails-ajax-helpers-to-low-pro-part-2&quot;&gt;Jarkko Laine&#8217;s article&lt;/a&gt; very helpful and of course &lt;a href=&quot;http://www.danwebb.net/lowpro&quot;&gt;Dan&#8217;s blog&lt;/a&gt; is worth a read. Unfortunately, due to the speed of technology, some of Dan&#8217;s examples are a little dated (thanks to improvements he&#8217;s made to the code).&lt;/p&gt;


	&lt;p&gt;So I figure, how’s about another example? One key concept behind unobtrusive javascripting is yanking those obnoxious mouse events out of your anchor tags; Onmouseover, onmouseout, etc – they’ve got to go. So how can we use Low Pro to add a rollover behavior to some images?&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;note: at the time of this writing, Low Pro is version 0.5 and requires prototype version 1.6.x&lt;/em&gt;&lt;/p&gt;


	&lt;h3&gt;Step 1: Plain &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;Let’s start with the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;. Imagine a menu that’s just a column of images; no javascript yet, just plain ol images (and of course styled with &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; in another file):&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;main_menu&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/pages/home&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;home.gif&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;alt&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Home&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/pages/about&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;about.gif&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;alt&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;About&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;ta&quot;&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;href&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/pages/contact&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;contact.gif&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;an&quot;&gt;alt&lt;/span&gt;=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Contact&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;ta&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Very simple. Probably everyone knows the mechanics of a rollover by now: what we want is for the img src attribute to change to a different value when the mouse cursor is placed over the image. The effect is getting a different image to display in place of the current image. And of course, when the cursor leaves the area of the image, we want the src to switch back. So how do we do that without using our tried and true &#8220;onmouseover/onmouseout&#8221; &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; attributes?&lt;/p&gt;


	&lt;h3&gt;Step 2: Create a Behavior&lt;/h3&gt;


	&lt;p&gt;We want to define a Behavior to describe the effect certain mouse events have on a particular image object. Low Pro makes this nice and clean, using the Class module baked into prototype to give us an object-oriented feel.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;var&lt;/span&gt; ImageRollover = Behavior.create({&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// define some attributes for this new Behavior (mmmm, OOP...)&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  orig_name: &lt;span class=&quot;pc&quot;&gt;null&lt;/span&gt;,    &lt;span class=&quot;c&quot;&gt;// the filename without extension&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  image_ext: &lt;span class=&quot;pc&quot;&gt;null&lt;/span&gt;,    &lt;span class=&quot;c&quot;&gt;// jpg, gif, etc, plus any ?123 nonsense at the end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  roll_suffix: &lt;span class=&quot;pc&quot;&gt;null&lt;/span&gt;,  &lt;span class=&quot;c&quot;&gt;// whatever we want to stick on the end of the image name&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// one of these instances of ImageRollover will be created for each image &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// when we set them up, we'll need to know the &amp;quot;suffix&amp;quot; of the rolled over image&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// for example, home.gif might be our image and home_on.gif might be our &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// rollover, making '_on' our suffix&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  initialize: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;(roll_suffix) {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.roll_suffix = roll_suffix&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// here comes some lovely regex&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// image.src example: http://example.com/images/something.gif?1234567890&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// we need to chop that up into: &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// 'http://example.com/images/something' and '.gif?1234567890' &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    matches = &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.element.src.&lt;span class=&quot;fu&quot;&gt;match&lt;/span&gt;(/(.*)((?:.gif|.jpg|.png).*)/);&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.orig_name = matches[1]; &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.image_ext = matches[2];&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;// this function will get called on mouseover&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  onmouseover: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// we're just stapling the pieces back together with the suffix between &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// the file name and the file extension &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.element.src = &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.orig_name + &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.roll_suffix + &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.image_ext&lt;tt&gt;
&lt;/tt&gt;  },&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  onmouseout: &lt;span class=&quot;r&quot;&gt;function&lt;/span&gt;() {&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;c&quot;&gt;// back to the original, no suffix&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.element.src = &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.orig_name + &lt;span class=&quot;pc&quot;&gt;this&lt;/span&gt;.image_ext&lt;tt&gt;
&lt;/tt&gt;  }&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;So there&#8217;s our behavior. It&#8217;s nice and generic &#8211; we could apply it to any image element. I&#8217;m not great with regex, but this will work for any image that ends with .gif, .jpg, or .png and optionally if it has an asset timestamp at the end following a question mark (&lt;a href=&quot;http://rubyonrails.org&quot;&gt;Ruby on Rails&lt;/a&gt; likes to stick these on the end of assets to trick browsers into reloading cached image, css, and js files that might have changed when code has been updated). I recently came across this great testing tool for regex expressions: &lt;a href=&quot;http://www.rubular.com/&quot;&gt;http://www.rubular.com/&lt;/a&gt;. Of course, the &lt;a href=&quot;http://www.getfirebug.com&quot;&gt;Firebug&lt;/a&gt; console is also great for this type of thing as well. &lt;del&gt;For some reason my regular expression yields a third, unnecessary match (just the file extension with no timestamp) and I can&#8217;t quite nail it down. It doesn&#8217;t affect anything, but hey &#8211; let me know if you have a suggestion.&lt;/del&gt; &lt;strong&gt;Edit:&lt;/strong&gt; Andy (in the comments) points out where the extra match comes from and how to ignore it. I updated the regex and it works.&lt;/p&gt;


	&lt;h3&gt;Step 3: Assign Behavior&lt;/h3&gt;


	&lt;p&gt;Finally, we can assign our ImageRollover behavior to some images. The magic of &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; selectors makes it easy to assign a behavior to a whole group.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Event.addBehavior({&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.main_menu img&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: ImageRollover(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_on&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;});&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The addBehavior method takes a hash where every key is a &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; selector and the value is a behavior. In this example, we can see that the &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; selector is saying &#8220;look for elements of the &lt;em&gt;main_menu&lt;/em&gt; class and collect any of their children that have the &lt;em&gt;img&lt;/em&gt; tag&#8221;. We also have to pass a value to ImageRollover that designates the rollover image suffix needed by the initialize method of the ImageRollover class.&lt;/p&gt;


	&lt;p&gt;Want proof that it works? See it &lt;a href=&quot;http://offtheline.net/examples/lowpro_image_rollover/index.html&quot;&gt;in action&lt;/a&gt; (warning: extremely bad graphics that I cranked out in 5 minutes).&lt;/p&gt;


	&lt;p&gt;So there you have it. If anyone who knows Low Pro has any feedback on improving this example, I&#8217;d love to hear it.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2008-02-14:127</id>
    <published>2008-02-14T04:01:00Z</published>
    <updated>2008-02-14T04:04:36Z</updated>
    <category term="Linux"/>
    <category term="Ruby and RoR"/>
    <category term="Sysadmin"/>
    <link href="http://offtheline.net/2008/2/14/receiving-email-with-rails" rel="alternate" type="text/html"/>
    <title>receiving email with Rails</title>
<content type="html">
            &lt;p&gt;Craig Ambrose writes about how he came up with a way to &lt;a href=&quot;http://blog.craigambrose.com/past/2008/2/9/respond_toemail_or_how_to_handle/&quot;&gt;receive mail RESTfully in Rails&lt;/a&gt;. Basically, he makes the point that the method for processing email described in the &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/HowToReceiveEmailsWithActionMailer&quot;&gt;Rails wiki&lt;/a&gt; is a little scary, as it can lead to the loading of the full Rails stack on every email you want to process. Craig speculates that this method could be problematic in terms of memory usage, and I tend to agree with him. He comes up with a pretty clever hack to basically redirect each incoming email at his actual running web application by grabbing it from postfix and posting it to his site via the use of Ruby&#8217;s net/http library. After that, it&#8217;s up to the Rails controller to handle the request.&lt;/p&gt;


	&lt;p&gt;While I like the cleverness of the solution, I can&#8217;t help but feel like it&#8217;s somehow asking for trouble. As some comments on the post point out, there doesn&#8217;t seem to be an elegant way to handle the mail if the web server happens to be down. Another concern is hammering the web server with too many requests in the case of multiple emails or text messages coming in, as each incoming email takes a up an http connection and occupies a mongrel server (or whatever) for however long it is needed (it&#8217;s no worse than submitting form data, but I think the concern is that there is potential for more volume).&lt;/p&gt;


	&lt;p&gt;I&#8217;ve been thinking about a way to handle incoming mail myself, and here&#8217;s the solution I&#8217;ve come up with. I have not had time to implement it, and maybe it&#8217;s been done before (please let me know if it has and has been documented).&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Postfix accepts incoming mail and stores the mail as a file somewhere on the server. A simple procmail recipe would probably be useful here to identify where to store incoming mail depending on it&#8217;s address, contents, day of the week, or whatever. &lt;/li&gt;
		&lt;li&gt;A &lt;a href=&quot;http://backgroundrb.rubyforge.org/&quot;&gt;backgroundrb&lt;/a&gt; worker hangs around and processes the mail files on a periodic basis, by reading files in a specified directory one at a time, parsing each message with TMail, and doing any other Rails stuff you need it to do with each message. Remove each file after the message has been processed.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Backgroundrb has a great built-in scheduling system, so there&#8217;s no need to think &lt;em&gt;cron&lt;/em&gt; in this setup. Backgroundrb will load the whole rails stack &lt;em&gt;once&lt;/em&gt;. The workers sit in a separate process. Backgroundrb won&#8217;t run itself over: if you set the schedule to process mail every 2 minutes and the mail takes more than 2 minutes to process, backgroundrb will queue it&#8217;s jobs up. In this scenario, a worker is just looking in one directory, so once all the mail is processed, it gets deleted. If no new mail comes in by the next time the worker looks at the directory, it can see there&#8217;s nothing to do and go back to sleep. Knowing the expected volume of email coming in is important, but I&#8217;m willing to bet in most cases you could ask backgroundrb to run your mail-processing worker once a minute.&lt;/p&gt;


	&lt;p&gt;This method doesn&#8217;t get to claim the label RESTful, but to be honest I don&#8217;t think regurgitating incoming mail out to your web server is really in the spirit of &#8220;REST&#8221; either. If you stay true to the skinny controller, fat model mantra, handling email via model methods (all accessible via backgroundrb) or even module/other non-model class methods in a backgroundrb worker should be as easy as (if not easier than) doing so from within a controller.&lt;/p&gt;


&lt;p&gt; &lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-12-11:90</id>
    <published>2007-12-11T21:37:00Z</published>
    <updated>2007-12-11T21:38:25Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2007/12/11/netbeans-6-0-cheat-sheet" rel="alternate" type="text/html"/>
    <title>NetBeans 6.0 Cheat Sheet</title>
<content type="html">
            &lt;div&gt;&lt;img src=&quot;/assets/2007/12/11/cheatsheet-thumb.gif&quot;&gt;&lt;/a&gt;&lt;/div&gt;

	&lt;p&gt;I stitched together a cheat sheet for &lt;a href=&quot;http://netbeans.org&quot;&gt;NetBeans 6.0&lt;/a&gt;, boiling it down to what I find are the most useful shortcuts for Ruby and Rails stuff.&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;NetBeans 6.0 Cheat Sheets:&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; &lt;span class=&quot;caps&quot;&gt;PC &lt;/span&gt;(Linux/Windows/etc) &lt;/td&gt;
			&lt;td&gt;[&lt;a href=&quot;/assets/2007/12/11/netbeans_ror.pdf&quot;&gt;PDF&lt;/a&gt;] &lt;/td&gt;
			&lt;td&gt;[&lt;a href=&quot;/assets/2007/12/11/netbeans_ror.odt&quot;&gt;ODT&lt;/a&gt;] &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Mac (OS X) &lt;/td&gt;
			&lt;td&gt;[&lt;a href=&quot;/assets/2007/12/11/netbeans_ror_mac.pdf&quot;&gt;PDF&lt;/a&gt;] &lt;/td&gt;
			&lt;td&gt;[&lt;a href=&quot;/assets/2007/12/11/netbeans_ror_mac.odt&quot;&gt;ODT&lt;/a&gt;] &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;I&#8217;ve been using &lt;span class=&quot;caps&quot;&gt;NB6&lt;/span&gt; for a couple of weeks and I&#8217;m starting to feel good about it. A couple of tweaks after the initial install (of the Ruby flavor of &lt;span class=&quot;caps&quot;&gt;NB6&lt;/span&gt;) that I have to make before I&#8217;m really happy:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Go to Tools, Plugins, and install Extra Ruby Color Themes, Ruby Extra Hints, and Ruby RSpec Support&lt;/li&gt;
		&lt;li&gt;Go to Options, Fonts &#38; Colors, change &#8220;Profile&#8221; to &#8220;Ruby Dark Pastels&#8221; (this is the TextMate-like color scheme, I guess)&lt;/li&gt;
		&lt;li&gt;A couple of things bug me about the color scheme &#8211; most notably, under Syntax Highlighting, Ruby, I have to change &lt;em&gt;Mark Occurrences&lt;/em&gt; to the Inherited background (otherwise, whenever your cursor is in a variable, it and all it&#8217;s occurrences will light up on the page, which I find very distracting). I also like to change the color of the highlighted row under the Highlighting tab on that page (the default background is too bright for me).&lt;/li&gt;
		&lt;li&gt;AutoComplete drives me crazy. I&#8217;ve always hated it &#8211; I feel like it slows my computer down and sometimes it even seems to derail me in the middle of typing something because the window comes up and somehow snags focus. I turn it off under Options, Editor, General (uncheck Auto Popup Completion Window).&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Most of the TextMate snippets have been imported into NetBeans 6. I didn&#8217;t squeeze all of these into the cheat sheet because there are so many, and personally, I don&#8217;t use &#8216;em (there&#8217;s probably some irony in the fact that I&#8217;m too lazy to learn a shortcut). You can peep the list of default &lt;a href=&quot;http://ruby.netbeans.org/codetemplates-ruby.html&quot;&gt;ruby snippets&lt;/a&gt; and &lt;a href=&quot;http://ruby.netbeans.org/codetemplates-rhtml.html&quot;&gt;rhtml snippets&lt;/a&gt; or just go &lt;a href=&quot;http://www.google.com/search?q=textmate+cheat+sheet+ruby&quot;&gt;search for a TextMate cheat sheet&lt;/a&gt;.&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href=&quot;/assets/2007/12/11/NetBeansIDE6-1.png&quot;&gt;&lt;img src=&quot;/assets/2007/12/11/NetBeansIDE6-1-t.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;&lt;a href=&quot;/assets/2007/12/11/NetBeansIDE6-2.png&quot;&gt;&lt;img src=&quot;/assets/2007/12/11/NetBeansIDE6-2-t.jpg&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;em&gt;click thumbnail for larger image&lt;/em&gt;&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;For a no-cost, cross-platform &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;, NetBeans 6 may be hard to beat. I still feel like there are some minor stability issues, but for the most part it hums right along on my Ubuntu desktop and laptop (both Gutsy-AMD64 installs) and even works fairly well on my &lt;a href=&quot;http://eeepc.asus.com/&quot;&gt;ASUS EeePC&lt;/a&gt; (running the pre-installed custom build of Xandros).&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-12-06:89</id>
    <published>2007-12-06T19:23:00Z</published>
    <updated>2007-12-06T19:24:25Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2007/12/6/really-breaking-up-an-array" rel="alternate" type="text/html"/>
    <title>really breaking up an array</title>
<content type="html">
            &lt;p&gt;Last time I tried to &lt;a href=&quot;/2007/10/13/breaking-up-an-array&quot;&gt;break up an array&lt;/a&gt;, I learned about &lt;a href=&quot;http://www.ruby-doc.org/core/classes/Enumerable.html#M003161&quot;&gt;enumerable&#8217;s partition method&lt;/a&gt;. This time, I&#8217;m taking it one step further and returning multiple arrays rather than just two:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Array&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;group_by&lt;/span&gt;(attribute = &lt;span class=&quot;pc&quot;&gt;nil&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    arrays = {}&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;r&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;...size&lt;tt&gt;
&lt;/tt&gt;      object = &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;[i]&lt;tt&gt;
&lt;/tt&gt;      value = attribute ? object.send(attribute.to_sym) : &lt;span class=&quot;r&quot;&gt;yield&lt;/span&gt;(object)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; arrays[value.to_s]&lt;tt&gt;
&lt;/tt&gt;        arrays[value.to_s] &amp;lt;&amp;lt; object&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        arrays[value.to_s] = [object]&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; arrays.values&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;And, the examples:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;gt;&amp;gt; &lt;span class=&quot;c&quot;&gt;# you can group by attribute name&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; my_array = [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dogs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;elephants&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;computers&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;1001&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dogs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;elephants&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;computers&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;1001&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; my_array.group_by &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;elephants&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;computers&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dogs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;1001&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; &lt;span class=&quot;c&quot;&gt;# also can take a block - equal evaluation of the block determines grouping&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; my_array.group_by { |a| a[&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;] }&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;things&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cats&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;computers&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;cars&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;1001&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;dogs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;elephants&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; [&lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;500&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;fl&quot;&gt;4.5&lt;/span&gt;].group_by { |a| a.is_a? &lt;span class=&quot;co&quot;&gt;Integer&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;500&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;fl&quot;&gt;4.5&lt;/span&gt;]]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; [&lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;500&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;fl&quot;&gt;4.5&lt;/span&gt;].group_by { |a| a.to_s.size }&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;500&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;fl&quot;&gt;4.5&lt;/span&gt;]]&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;
Again, I find this method useful for grouping ActiveRecord sets based on different attributes. It's especially handy when constructing views where records need to be grouped under different headings or in different tables. 
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-10-13:80</id>
    <published>2007-10-13T19:15:00Z</published>
    <updated>2007-10-13T19:16:10Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2007/10/13/breaking-up-an-array" rel="alternate" type="text/html"/>
    <title>breaking up an array</title>
<content type="html">
            &lt;p&gt;There&#8217;s probably a better way to name this, but whattayagonna do?&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Array&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# split an array based on block&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;divorce&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    mom = []&lt;tt&gt;
&lt;/tt&gt;    dad = []&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;r&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;...size&lt;tt&gt;
&lt;/tt&gt;      value = &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;[i]&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;yield&lt;/span&gt;(value)&lt;tt&gt;
&lt;/tt&gt;        mom &amp;lt;&amp;lt; value&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        dad &amp;lt;&amp;lt; value&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;return&lt;/span&gt; [mom, dad]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Examples:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;gt;&amp;gt; strings, non_strings = [&lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;,&lt;span class=&quot;i&quot;&gt;6&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;aaa&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;7&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ccc&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].divorce { |element| element.is_a? &lt;span class=&quot;co&quot;&gt;String&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;aaa&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ccc&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;6&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;7&lt;/span&gt;]]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; longs, shorts = [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Hello.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Hi, how are you today?&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Great!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].divorce { |st| st.size &amp;gt; &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Hi, how are you today?&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Hello.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Great!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]]&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; mults_of_3, non_mults_of_3 = (&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;..&lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;).to_a.divorce { |n| n % &lt;span class=&quot;i&quot;&gt;3&lt;/span&gt; == &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;i&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;6&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;9&lt;/span&gt;], [&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;7&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;]]&lt;tt&gt;
&lt;/tt&gt;&amp;gt;&amp;gt; mults_of_2, non_mults_of_2_or_3 = non_mults_of_3.divorce { |n| n % &lt;span class=&quot;i&quot;&gt;2&lt;/span&gt; == &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [[&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;], [&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;7&lt;/span&gt;]]&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;I use it mostly for breaking up collections of ActiveRecord objects, where I want to process them differently depending on some attribute, but don't want to make multiple database/find calls or select/detect calls. &lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-09-16:75</id>
    <published>2007-09-16T15:26:00Z</published>
    <updated>2007-09-16T15:27:05Z</updated>
    <category term="Linux"/>
    <category term="misc"/>
    <category term="Ruby and RoR"/>
    <category term="Sysadmin"/>
    <link href="http://offtheline.net/2007/9/16/ruby-for-batching" rel="alternate" type="text/html"/>
    <title>Ruby for Batching</title>
<content type="html">
            &lt;p&gt;The other day I wanted to resize a bunch of images using &lt;a href=&quot;http://www.imagemagick.org/script/index.php&quot;&gt;ImageMagick&#8217;s&lt;/a&gt; convert command-line utility. I wanted to both resize and change their names from image_name.png to image_name-sm.png, but I couldn&#8217;t figure out how to guide &#8216;convert&#8217; to use part of the original name in the new name. The next obvious tactic would be to use some common shell utilities like &#8216;for&#8217; and &#8216;do&#8217;. My shell-fu is rusty however, and I still couldn&#8217;t get things quite the way I wanted them. Then I think to myself, this would be much easier to do with Ruby.&lt;/p&gt;


	&lt;p&gt;First, I use &#8216;puts&#8217; to see if the syntax will come out right:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;irb(main):&lt;span class=&quot;i&quot;&gt;017&lt;/span&gt;:&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&amp;gt; &lt;span class=&quot;co&quot;&gt;Dir&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].each { |f| puts &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;convert &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;f&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -resize 400x400 &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;f[&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;..&lt;span class=&quot;i&quot;&gt;-5&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-sm.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;convert character_creation.png -resize &lt;span class=&quot;i&quot;&gt;400&lt;/span&gt;x400 character_creation-sm.png&lt;tt&gt;
&lt;/tt&gt;convert battle-mountain_pass.png -resize &lt;span class=&quot;i&quot;&gt;400&lt;/span&gt;x400 battle-mountain_pass-sm.png&lt;tt&gt;
&lt;/tt&gt;convert loot-drag_and_drop.png -resize &lt;span class=&quot;i&quot;&gt;400&lt;/span&gt;x400 loot-drag_and_drop-sm.png&lt;tt&gt;
&lt;/tt&gt;convert market.png -resize &lt;span class=&quot;i&quot;&gt;400&lt;/span&gt;x400 market-sm.png&lt;tt&gt;
&lt;/tt&gt;...(etc)...&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Then I just run the same line with &lt;em&gt;system&lt;/em&gt; instead of &lt;em&gt;puts&lt;/em&gt;:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;Dir&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].each { |f| system &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;convert &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;f&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -resize 400x400 &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;f[&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;..&lt;span class=&quot;i&quot;&gt;-5&lt;/span&gt;]&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-sm.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;With a little practice, this can be done on the command line - who needs shell scripting?&lt;/p&gt;

&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# run from the shell prompt:&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;ruby -e &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Dir[&amp;quot;*.png&amp;quot;].each { |f| system &amp;quot;convert #{f} -resize 400x400 #{f[0..-5]}-sm.png&amp;quot; }&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;br /&gt;&lt;br /&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-08-30:74</id>
    <published>2007-08-30T17:24:00Z</published>
    <updated>2007-09-16T15:27:23Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2007/8/30/handling-ie6-incompatibilities" rel="alternate" type="text/html"/>
    <title>Handling IE6 Incompatibilities</title>
<content type="html">
            &lt;p&gt;While developing my &lt;a href=&quot;http://aethora.com&quot;&gt;browser-based game&lt;/a&gt;, I&#8217;m always using Firefox and periodically testing in Internet Explorer 7. A few months ago, I set up a &lt;a href=&quot;http://wiki.aethora.com&quot;&gt;wiki for the game&lt;/a&gt; and asked players to contribute to the documentation. One helpful player posted some screenshots of the game in Internet Explorer 6 and I was horrified. I knew there were transparency issues with png graphics in &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;, as well as some &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; incompatibilities, and I gave a disclaimer to say so, but coming face to face with what the site actually looked like in &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt; was quite revealing. I checked out my &lt;a href=&quot;https://www.google.com/analytics/&quot;&gt;Google Analytics&lt;/a&gt; page and I could see that my visitors are split almost half and half between Firefox and IE. When I looked at the IE breakdown, I saw that it&#8217;s pretty close to half &lt;span class=&quot;caps&quot;&gt;IE7&lt;/span&gt; and half &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;. This means 25% of my visitors are still using &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;. I decided I didn&#8217;t want to rely 100% on a disclaimer to push &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt; out of mind; I needed to do do some fixin&#8217;.&lt;/p&gt;


	&lt;p&gt;My first problem was alpha transparency in png graphics. As many web designers know, these graphics end up with solid background colors in &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;. In most cases, it ends up &lt;a href=&quot;http://wiki.aethora.com/images/f/fd/BattleBegin.JPG&quot;&gt;looking like crap&lt;/a&gt;. I initially thought, am I going to have to change all my &lt;span class=&quot;caps&quot;&gt;PNG&lt;/span&gt; graphics to the inferior &lt;span class=&quot;caps&quot;&gt;GIF&lt;/span&gt; format just so it won&#8217;t look so bad in &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;? There are javascript hacks out there that will force transparencies to mostly work on &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;. I decided instead I wanted to create a copy of every png image as a gif and serve up the gifs to &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt; users and give pngs to everyone else. This way I wouldn&#8217;t have to worry about any problems in &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;, and my disclaimer still applies &#8211; the graphics look slightly better in Firefox, Opera, &lt;span class=&quot;caps&quot;&gt;IE7&lt;/span&gt;, or Safari than they do in &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;To accomplish this task in Rails, I created an &#8216;images_ie6&#8217; directory alongside my &#8216;images&#8217; directory in &#8216;public&#8217;. I used &lt;a href=&quot;http://www.imagemagick.org/script/command-line-processing.php&quot;&gt;ImageMagick&#8217;s &#8216;convert&#8217; command-line tool&lt;/a&gt; to convert all the pngs into gifs and placed them in the same folder structure, but in the base &#8216;images_ie6&#8217; directory. Then I rewrote image_tag to detect the user agent and change the images path to &#8216;images_ie6&#8217;, and change .png to .gif if it&#8217;s &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# in app/helpers/application_helper.rb &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# override image tag to point IE6 users to a different directory with GIFs instead of PNGs&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ActionView::Helpers::AssetTagHelper&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  alias_method(&lt;span class=&quot;sy&quot;&gt;:orig_image_tag&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:image_tag&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;unless&lt;/span&gt; method_defined?(&lt;span class=&quot;sy&quot;&gt;:orig_image_tag&lt;/span&gt;) &lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;image_tag&lt;/span&gt;(path, options = {})&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; request.env[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;HTTP_USER_AGENT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] &lt;span class=&quot;r&quot;&gt;and&lt;/span&gt; request.env[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;HTTP_USER_AGENT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].include? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;MSIE 6.0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;      path.gsub! &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.gif&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      path.gsub! &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/images/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      path = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/images_ie6/&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt;path&lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    orig_image_tag(path, options)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Notice that I need to check to see if the environment variable for &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt;_USER_AGENT is set before checking to see if it contains &#8220;MSIE 6.0&#8221;. For some reason, the test environment sets some variables in request.env, but leaves out the user agent string. The extra check keeps tests from failing.&lt;/p&gt;


	&lt;p&gt;Aside from the image_tag hack, I had to deal with the problems that some images were referenced from &lt;span class=&quot;caps&quot;&gt;CSS &lt;/span&gt;(background properties for example), and there were other &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;-related issues (IE6 has trouble with the min-height and min-width properties). So to handle those problems, I&#8217;m loading an extra ie6fixes.css file if the user agent indicates &lt;span class=&quot;caps&quot;&gt;IE6&lt;/span&gt;. These styles overwrite only the necessary elements defined in the normal stylesheets.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;# in app/views/layouts/application.html  &lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;stylesheet_link_tag &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ie6fixes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; request.env[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;HTTP_USER_AGENT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;] &lt;span class=&quot;r&quot;&gt;and&lt;/span&gt; request.env[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;HTTP_USER_AGENT&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].include? &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;MSIE 6.0&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;Standard disclaimer about trusting user agent strings applies. Frankly, I'm of the opinion (like many) that if a visitor messes with their user agent string, they're on their own.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-06-14:37</id>
    <published>2007-06-14T18:41:00Z</published>
    <updated>2007-06-14T18:42:57Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2007/6/14/acts-as-stripped-auto-stripping-html-from-a-field" rel="alternate" type="text/html"/>
    <title>acts_as_stripped: auto-stripping HTML from a field</title>
<content type="html">
            &lt;p&gt;I have been using &lt;a href=&quot;http://errtheblog.com/post/14&quot;&gt;Err&#8217;s acts_as_textiled plugin&lt;/a&gt; for making certain fields of an ActiveRecord model always display with textile formatting. It&#8217;s smart enough to know that when used in a input field, the data should be displayed unformatted. The nice thing about textiling a field is not worrying about bad &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; polluting your page or attempts at &lt;acronym title=&quot;cross site scripting&quot;&gt;XSS&lt;/acronym&gt;.&lt;/p&gt;


	&lt;p&gt;Being that the acts_as_textiled plugin saves me from accidentally displaying a field without &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; stripping (like when I forget to use the handy &amp;lt;%=h erb shortcut), I started using it on fields all over the place. Sometimes, where not really appropriate.&lt;/p&gt;


	&lt;p&gt;For example, let&#8217;s say you have a User model and one of the attributes is &#8220;display_name&#8221;. Now if someone picks a name like &#8220;I&#42;am&#42;the&#42;greatest&#42;ever!&#8221;, I don&#8217;t care that they are using non-alpha-numeric characters. I just don&#8217;t want it to show up like &#8220;I&lt;strong&gt;am&lt;/strong&gt;the&lt;strong&gt;greatest&lt;/strong&gt;ever!&#8221;&lt;/p&gt;


	&lt;p&gt;The problem was, I had been relying on acts_as_textiled to save me from bad &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; in that field, so now if I turn it off, someone can make their display_name &#8220;Run &amp;lt;script blah blah blah &amp;gt; or something&#8221; and I have all these places in my views where I left out the &lt;em&gt;h&lt;/em&gt; in &amp;lt;%=h so I&#8217;m screwed. I needed another way to strip &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; without using textiled, but I wanted to be able to auto-strip where appropriate by setting up a model the same way acts_as_textiled does.&lt;/p&gt;


	&lt;p&gt;Enter: &lt;strong&gt;acts_as_stripped&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;From the &lt;a href=&quot;http://svn.offtheline.net/plugins/acts_as_stripped/README&quot;&gt;README&lt;/a&gt;:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;Strips HTML out of an attribute whenever it's displayed - even if it's in a form 
input box/textarea (for the purposes of this plugin, I'm considering HTML evil 
in the specified fields, no matter what). 
NOTE: no stripping happens when the attribute is written, only read.
NOTE: value is converted to string; so for example if you errantly list an integer 
attribute in the attribute list it's going to come back as a string.

Inspired by Err's acts_as_textiled, but I needed some attributes to be displayed 
without textile messing with underscores and asterisks. 

And I don't trust myself to sanitize HTML in views 100% of the time. 

Use like so: 

class SomeModel &amp;lt; ActiveRecord::Base
  acts_as_stripped :name, :description

    # ...
end

If you need to get the unstripped value, you can always use: 
your_model.attributes[&quot;att_name&quot;]&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Install with:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;./script/plugin install http://svn.offtheline.net/plugins/acts_as_stripped/&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;(or just use svn or piston to import into your vendor/plugins directory)&lt;/p&gt;


	&lt;p&gt;Any feedback? Questions? Criticism? All welcome and appreciated.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-06-06:36</id>
    <published>2007-06-06T21:45:00Z</published>
    <updated>2007-06-11T14:08:38Z</updated>
    <category term="Linux"/>
    <category term="Sysadmin"/>
    <link href="http://offtheline.net/2007/6/6/yahoo-com-mail-and-421-message-temporarily-deferred" rel="alternate" type="text/html"/>
    <title>yahoo.com mail and "421 Message temporarily deferred"</title>
<content type="html">
            &lt;p&gt;One of my servers has a registration page that sends an activation code via email, and if someone signs up with a yahoo account, my logs were showing:&lt;/p&gt;


&lt;code&gt;host f.mx.mail.yahoo.com[68.142.202.247] said: 421 Message temporarily deferred - 4.16.51. Please refer to http://help.yahoo.com/help/us/mail/defer/defer-06.html (in reply to end of DATA command) &lt;/code&gt;

	&lt;p&gt;The help page is decidedly unhelpful (I filled out a form and got an email back from yahoo that pointed me to the same page that the error message points to). After some googling, it seems to be the best way to get around this yahoo deferring problem is to set up DomainKeys (notice there is no mention of DomainKeys on that yahoo &#8216;help&#8217; page). Now it seems there are several different ways of implementing DomainKeys or one of the alternative methods of signing outgoing mail. In the end, I went with &lt;span class=&quot;caps&quot;&gt;DKIM &lt;/span&gt;Proxy.&lt;/p&gt;


	&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;DKIM &lt;/span&gt;Proxy is written in perl. It&#8217;s designed to sit on your mail server, open a couple ports, and let your mail server pass messages in and out of it. On the outgoing side, it applies a DomainKey signature (actually two &#8211; it applies both the &lt;a href=&quot;http://www.dkim.org/&quot; title=&quot;DKIM&quot;&gt;Domain Keys Identified Mail&lt;/a&gt; standard and the older &lt;a href=&quot;http://antispam.yahoo.com/domainkeys&quot;&gt;Yahoo! DomainKeys&lt;/a&gt; standard). On the incoming side, it reads signatures and verifies their integrity.&lt;/p&gt;


	&lt;p&gt;As the &lt;a href=&quot;http://jason.long.name/dkimproxy/&quot;&gt;DKIM Proxy page&lt;/a&gt; notes, if you&#8217;re already using something like SpamAssassin, you&#8217;ve already got &lt;span class=&quot;caps&quot;&gt;DKIM&lt;/span&gt; checking on your incoming mail. If you want to be able to manage spam, I&#8217;d highly recommend using SpamAssassin.&lt;/p&gt;


	&lt;p&gt;I only needed &lt;span class=&quot;caps&quot;&gt;DKIM &lt;/span&gt;Proxy for outgoing mail. The &lt;a href=&quot;http://jason.long.name/dkimproxy/&quot;&gt;DKIM Proxy page&lt;/a&gt; has fairly decent instructions, but I ran into a few snags, so hopefully this will help someone.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Before you even get started:&lt;/em&gt; some things you need to know.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;You need to have perl on your system (I don&#8217;t know of any distros that don&#8217;t come with perl) and you need to be able to install perl modules. &lt;/li&gt;
		&lt;li&gt;You&#8217;ll need the &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; dev packages for your distro installed for these perl modules to install correctly (for example: apt-get install libssl-dev )&lt;/li&gt;
		&lt;li&gt;You need to be able to edit your mail server&#8217;s configuration file &#8211; if you&#8217;re using postfix, there&#8217;s an example provided. &lt;/li&gt;
		&lt;li&gt;You need to be able to add a sub-domain to your &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; listing for your domain.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;First up is perl. There are a bunch of modules you need to get the Mail::DKIM module installed, and then you can install &lt;span class=&quot;caps&quot;&gt;DKIM &lt;/span&gt;Proxy. The required modules are listed on the &lt;span class=&quot;caps&quot;&gt;DKIM &lt;/span&gt;Proxy site &#8211; here is the easy way to get them installed (make sure you are superuser/root):&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Note 1:&lt;/strong&gt; If you&#8217;re using Debian or Ubuntu, you should be able to skip this step by installing the libmail-dkim-perl and libnet-server-perl packages. I believe that will get your perl install all the necessary modules and you can go on to installing &lt;span class=&quot;caps&quot;&gt;DKIM&lt;/span&gt;-Proxy.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; If you&#8217;ve never run &lt;span class=&quot;caps&quot;&gt;CPAN&lt;/span&gt; before, it&#8217;s going to ask you to do a manual configuration right off the bat &#8211; I usually say &#8216;no&#8217; to that question and let it attempt autoconfiguration. If you don&#8217;t need to set up any proxies or anything, autoconfigure should work.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Note 3:&lt;/strong&gt; Some of these modules have their own dependencies. If it asks you: &#8220;Shall I follow them and prepend them to the queue
of modules we are processing right now?&#8221; Just hit Enter to take the default answer of [Yes].&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;Crypt::OpenSSL::RSA&quot;)'
perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;Digest::SHA&quot;)'
perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;Digest::SHA1&quot;)'
perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;Error&quot;)'
perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;Mail::Address&quot;)'
perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;MIME::Base64&quot;)'
perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;Net::DNS&quot;)'
perl -MCPAN -e'CPAN::Shell-&gt;install(&quot;Net::Server&quot;)'&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Once your perl modules are installed, you can install dkimproxy. I won&#8217;t go into detail &#8211; this part is pretty straightforward (follow the &lt;a href=&quot;http://jason.long.name/dkimproxy/&quot;&gt;instructions on the site&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;If you&#8217;ve got dkimproxy installed now, the instructions tell you how to generate a private/public key pair and then set up your &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; record. You have to put the public key in the actual &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; record, and this means removing the line breaks and white space.&lt;/p&gt;


	&lt;p&gt;Before you go any further, reload bind/named (on most systems: /etc/init.d/named restart   &lt;em&gt;or&lt;/em&gt;  /etc/init.d/bind9 restart) and make sure you see your big long public key when you do the following command:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;dig selector1._domainkey.my-domain-name.com TXT&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you don&#8217;t see your public key there in a big long string, then you did something wrong in &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt;. Go back and fix it before you try anything else &#8211; trust me. You&#8217;ll just end up in circles if your &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; is wrong. I had misspelled something and wasted about 20 minutes trying to figure out what was wrong with &lt;span class=&quot;caps&quot;&gt;DKIM &lt;/span&gt;Proxy when it was my &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; entry that was the problem all along.&lt;/p&gt;


	&lt;p&gt;At this point, if you haven&#8217;t already, you should probably create a user and group called &#8216;dkfilter&#8217; (or something similar).&lt;/p&gt;


	&lt;p&gt;The instructions give you an example of how the &#8216;dkimproxy.out&#8217; script could be run. There is also a file in the root of the dkimproxy archive called &lt;em&gt;sample-dkim-init-script.sh&lt;/em&gt;. This script is the easiest way to get dkimproxy running as a daemon. Edit the vars at the top of the script to meet your needs &#8211; if you used the default selector name of &lt;em&gt;selector1&lt;/em&gt; and the user name &lt;em&gt;dkfilter&lt;/em&gt; you probably don&#8217;t need to change anything. I changed the domain line to read: &lt;span class=&quot;caps&quot;&gt;DOMAIN&lt;/span&gt;=my-domain1.com,my-domain2.com,my-domain3.com&lt;/p&gt;


	&lt;p&gt;(note: if you are doing this for multiple domains, I hope you remembered to add the &lt;span class=&quot;caps&quot;&gt;TXT DNS&lt;/span&gt; record to each domain&#8217;s zone file &#8211; and verify with dig!)&lt;/p&gt;


	&lt;p&gt;If the init script works good, copy it to /etc/init.d or wherever your init scripts live, and set it up to start at boot time (distro-dependent; it&#8217;s something I do rarely enough that I always have to look it up).&lt;/p&gt;


	&lt;p&gt;For the last part, you need to set up your mail server to direct it&#8217;s outgoing messages at dkimproxy for signing before they head out. Hopefully, you&#8217;re using postifx, because there is a cut-and-paste &lt;a href=&quot;http://jason.long.name/dkimproxy/postfix-outbound-howto.html&quot;&gt;example for the postfix master.cf&lt;/a&gt; on the &lt;span class=&quot;caps&quot;&gt;DKIM &lt;/span&gt;Proxy site. Don&#8217;t forget to do a postfix reload.&lt;/p&gt;


	&lt;p&gt;Once postfix is set up, they have a couple of test mail addresses you can use. Watch your maillog to see if things are working right. I still got a few delays from Yahoo at first, but now they seem to be flowing normally.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-05-23:29</id>
    <published>2007-05-23T18:05:00Z</published>
    <updated>2007-05-24T20:05:56Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2007/5/23/reversing-an-svn-export" rel="alternate" type="text/html"/>
    <title>reversing svn externals</title>
<content type="html">
            &lt;p&gt;Generally when you install a plugin in a Rails app that is under version control with subversion, it&#8217;s recommended you use the &amp;ndash;x switch to export the plugin to your directory. The &amp;ndash;x just uses &lt;del&gt;the &lt;strong&gt;svn export&lt;/strong&gt; command&lt;/del&gt; &lt;a href=&quot;http://svnbook.red-bean.com/nightly/en/svn.advanced.externals.html&quot;&gt;the &lt;strong&gt;svn externals&lt;/strong&gt; definition&lt;/a&gt;. I&#8217;ve happily installed many a plugin this way. It&#8217;s a great way to stay up to date &#8211; if the plugin ever gets updated, the changes get pulled in with &lt;strong&gt;svn update&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Recently, I found myself wanting to do some cleanup on an app however, and I had a couple plugins in there that I tried out at some point but I wasn&#8217;t using any more. I tried to use &lt;strong&gt;svn rm vendor/plugins/plugin_x&lt;/strong&gt; , and it appeared to work (showed those files as marked with a D) but it didn&#8217;t actually remove them. Or rather, it had removed them, but they came right back when I did &lt;strong&gt;svn update&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Now I love subversion, but I didn&#8217;t even know where to look to figure out how to unhook these external plugins from my app. Eventually I figured out I need to check on the &lt;em&gt;svn properties&lt;/em&gt; of the plugin directory.&lt;/p&gt;


&lt;div class=&quot;term&quot;&gt;&lt;pre&gt;
jason@jwl-dev:~/dev/rails_app$ svn proplist vendor/plugins/
Properties on 'vendor/plugins':
  svn:externals
&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Ah, there we go. Let&#8217;s see what&#8217;s actually set in the svn:externals property.&lt;/p&gt;


&lt;div class=&quot;term&quot;&gt;&lt;pre&gt;
jason@jwl-dev:~/dev/rails_app$ svn propget svn:externals vendor/plugins/
acts_as_versioned       http://svn.techno-weenie.net/projects/plugins/acts_as_versioned
unwanted_plugin         http://blahblahblah/plugins/unwanted_plugin
&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;In order to remove the unwanted plugin, I just needed to use &lt;strong&gt;svn propedit svn:externals vendor/plugins&lt;/strong&gt; and delete that line. After that, the unwanted plugin was no longer under version control and I could just delete the whole &#8216;unwanted_plugin&#8217; directory (didn&#8217;t even have to use &lt;strong&gt;svn rm&lt;/strong&gt;).&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://offtheline.net/">
    <author>
      <name>Jason</name>
    </author>
    <id>tag:offtheline.net,2007-04-30:28</id>
    <published>2007-04-30T22:37:00Z</published>
    <updated>2007-04-30T22:41:12Z</updated>
    <category term="Development"/>
    <category term="Ruby and RoR"/>
    <link href="http://offtheline.net/2007/4/30/rails-deprecated-page" rel="alternate" type="text/html"/>
    <title>Observer is Deprecated</title>
<content type="html">
            &lt;p&gt;So if you&#8217;ve seen deprecation warnings in your tests, you&#8217;ve probably been to http://www.rubyonrails.org/deprecation &#8211; for months, this page was just blank. I noticed today that it was updated, but it&#8217;s still pretty flimsy, sadly.&lt;/p&gt;


	&lt;p&gt;In one of my apps, I was using acts_as_authenticated from way back, and I&#8217;d been ignoring the error:&lt;/p&gt;


	&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;DEPRECATION WARNING&lt;/span&gt;: observer is deprecated and will be removed from Rails 2.0  See http://www.rubyonrails.org/deprecation for details. (called from /home/jason/dev/myapp/config/../app/controllers/account_controller.rb:2)&lt;/p&gt;


	&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;DEPRECATION WARNING&lt;/span&gt;: depend_on is deprecated and will be removed from Rails 2.0  See http://www.rubyonrails.org/deprecation for details. (called from observer_without_deprecation at /usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/deprecated_dependencies.rb:29)&lt;/p&gt;


	&lt;p&gt;This particular deprecation is not yet mentioned on the deprecation page, but I managed to track it down. What&#8217;s deprecated is calling &#8216;observer&#8217; from a controller. Instead, you need to set it in your config/environment.rb file:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;        config.active_record.observers = &lt;span class=&quot;sy&quot;&gt;:user_observer&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;That&#8217;s it.&lt;/p&gt;
          </content>  </entry>
</feed>
