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

<channel>
	<title>jeremyweiland.com &#187; Blogroll</title>
	<atom:link href="http://jeremyweiland.com/category/blogroll/feed" rel="self" type="application/rss+xml" />
	<link>http://jeremyweiland.com</link>
	<description>The home page of Jeremy Weiland</description>
	<lastBuildDate>Tue, 08 Jun 2010 19:32:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Latest Ruby blog posts</title>
		<link>http://jeremyweiland.com/archives/96</link>
		<comments>http://jeremyweiland.com/archives/96#comments</comments>
		<pubDate>Tue, 08 Jun 2010 19:32:00 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://jeremyweiland.com/?p=96</guid>
		<description><![CDATA[Since I launched my new main blog, I haven&#8217;t hooked up the syndication to bring over posts yet. So if you&#8217;re looking for anything ruby-related, here&#8217;s a list of what I&#8217;ve written lately:

RailsConf Dispatches

Rescue Missions: Tammer Saleh on parachuting into disaster codebases
Test Always? How not thinking carefully about your test suite can hold you back


GridFS [...]]]></description>
			<content:encoded><![CDATA[<p>Since I launched my new main blog, I haven&#8217;t hooked up the syndication to bring over posts yet. So if you&#8217;re looking for anything ruby-related, here&#8217;s a list of what I&#8217;ve written lately:</p>
<ul>
<li>RailsConf Dispatches
<ul>
<li><a href="http://socialmemorycomplex.net/2010/06/07/railsconf-dispatch-rescue-missions/">Rescue Missions: Tammer Saleh on parachuting into disaster codebases</a></li>
<li><a href="http://socialmemorycomplex.net/2010/06/08/railsconf-dispatch-test-always/">Test Always? How not thinking carefully about your test suite can hold you back</a></li>
</ul>
</li>
<li><a href="http://socialmemorycomplex.net/2010/06/02/gridfs-with-mongoid-and-carrierwave-on-rails-3/">GridFS with Mongoid and CarrierWave on Rails 3</a></li>
<li><a href="http://socialmemorycomplex.net/2010/04/14/add-sound-to-autotest/">Add Sound to Autotest on OS X</a></li>
<li><a href="http://socialmemorycomplex.net/2010/02/04/creative-destruction-in-software-development/">Creative Destruction in Software Development</a></li>
<li><a href="http://socialmemorycomplex.net/2010/01/11/need-git-aliases/">Need git aliases?</a></li>
<li><a href="http://socialmemorycomplex.net/2009/12/24/acts-as-enumerated/">acts_as_enumerated Blowing Up Your Testing Spot?</a></li>
</ul>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/96/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The New House</title>
		<link>http://jeremyweiland.com/archives/76</link>
		<comments>http://jeremyweiland.com/archives/76#comments</comments>
		<pubDate>Sat, 28 Mar 2009 17:44:42 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1435</guid>
		<description><![CDATA[Yes, the rumors you&#8217;ve been hearing are all true: we closed on our first home Thursday evening!  It&#8217;s been a long road, and we almost didn&#8217;t get there (Bank of America, you were awful).  But we got a great interest rate and a deal on a home that should have cost twice as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.6thdensity.net/wp-content/uploads/2009/03/p1010387.jpg" style="float: left;  margin: 0 10px 10px 0;"><img src="http://blog.6thdensity.net/wp-content/uploads/2009/03/p1010387-300x225.jpg" alt="Another view of Schloss McWeiland" title="Another view of Schloss McWeiland" width="300" height="225" class="size-medium wp-image-1436" /></a>Yes, the rumors you&#8217;ve been hearing are all true: we closed on our first home Thursday evening!  It&#8217;s been a long road, and we almost didn&#8217;t get there (Bank of America, you were awful).  But we got a great interest rate and a deal on a home that should have cost twice as much.</p>
<p>And you know whom we have to thank?  My late Grandma Chappell, who left us just enough money for a modest down payment in her will.  Thanks, Grandma, for your wonderful gift and being a great grandparent for so long!</p>
<p style="clear: both;">Here&#8217;s a breakdown of the positive points about the house:
<ul>
<li>Built in 1910, but completely stripped down and replumbed, rewired, with all new appliances, room, and heat pump (need to replace the refrigerator, though). Original moldings and panel doors, though!</li>
<li>A block from <a href="http://www.jamesriverpark.org/">James River Park</a>, with lots of water and rocks for Tela and beautiful Belle Isle accessible by paw.</li>
<li>A five minute drive from my office.  It&#8217;s actually quicker to walk than to take the bus!</li>
<li>Two bedrooms and an office</li>
<li><em>Huge</em> living room and dining room, with a great kitchen.</li>
<li>Utility room with room for Tasha&#8217;s kiln.</li>
<li>A garage with a separate shed, all cleaned out and ready for Tasha to wire up and turn into a studio.</li>
</ul>
<p><a href="http://blog.6thdensity.net/wp-content/uploads/2009/03/p1010412.jpg" style="float: right; margin: 10px 0 10px 10px;"><img src="http://blog.6thdensity.net/wp-content/uploads/2009/03/p1010412-225x300.jpg" alt="Our new house in the March Snow" title="Our new house in the March Snow" width="225" height="300" class="size-medium wp-image-1438" /></a>Here&#8217;s what we need to do:
<ul>
<li>Fence in the front yard first, then the backyard, for Tela.</li>
<li>Put a gutter on the roof.</li>
<li>Buy a new refrigerator.</li>
<li>Put a new roof on the shed and generally turn the garage into a studio with wiring.</li>
<li>Paint the downstairs rooms.</li>
<li>Move in!</li>
</ul>
<p>So our lease at our current place ends April 30, giving us <em>plenty</em> of time to get the place ready and move in.  We&#8217;ll let you know when the housewarming party is, but until then just wanted to share the next phase of our lives with ya!</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/76/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quote of the Day</title>
		<link>http://jeremyweiland.com/archives/75</link>
		<comments>http://jeremyweiland.com/archives/75#comments</comments>
		<pubDate>Tue, 24 Feb 2009 16:25:44 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1380</guid>
		<description><![CDATA[I know it&#8217;s been a while.  Sorry.  Anyway, this is great:
Jesse Helms and his ilk inject a bit of fresh blood into art which, for a moment, can imagine itself an insurrectionary force. The sad irony is that Helms really believes art can change the world.  The NEA liberals think that all [...]]]></description>
			<content:encoded><![CDATA[<p>I know it&#8217;s been a while.  Sorry.  Anyway, this is great:</p>
<blockquote><p>Jesse Helms and his ilk inject a bit of fresh blood into art which, for a moment, can imagine itself an insurrectionary force. The sad irony is that Helms really believes art can change the world.  The NEA liberals think that all art should be permitted because, after all, it&#8217;s only art.</p></blockquote>
<p align=right>- from the TAZ show, Feb 6 1993</p>
<p>Watch the whole thing <a href="http://www.youtube.com/watch?v=V3FzEVRSOw0">here</a>, it&#8217;s a hoot.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/75/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tela in heaven</title>
		<link>http://jeremyweiland.com/archives/64</link>
		<comments>http://jeremyweiland.com/archives/64#comments</comments>
		<pubDate>Fri, 06 Feb 2009 14:28:51 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1360</guid>
		<description><![CDATA[My first real YouTube upload with my new iFlip camcorder:

]]></description>
			<content:encoded><![CDATA[<p>My first real YouTube upload with my new iFlip camcorder:</p>
<div align=center><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/9R0CVfYfb90&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/9R0CVfYfb90&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/64/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reprocessing attachment_fu images with RMagick</title>
		<link>http://jeremyweiland.com/archives/65</link>
		<comments>http://jeremyweiland.com/archives/65#comments</comments>
		<pubDate>Thu, 05 Feb 2009 21:57:43 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1347</guid>
		<description><![CDATA[Attachment_fu is the shit, no doubt.  But sometimes you want to do more than upload, resize, and thumbnail.  Designers often have a specific vision that dictates a more complex workflow for incoming images.  For these tasks, it may be necessary to reprocess the saved images &#8211; something you don&#8217;t necessarily need to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/technoweenie/attachment_fu/tree/master">Attachment_fu</a> is the shit, no doubt.  But sometimes you want to do more than upload, resize, and thumbnail.  Designers often have a specific vision that dictates a more complex workflow for incoming images.  For these tasks, it may be necessary to reprocess the saved images &#8211; something you don&#8217;t necessarily need to hack attachment_fu to accomplish.</p>
<p>For example, my latest Rails project included a gallery page with a pretty standard layout: a series of thumbnails and an area to display the full size version of the selected thumbnail.  However, the static mockup delivered by the designer had thumbnails that were black and white with a blueish tint, only turning color when you moused over them.  On top of that, the thumbnails were often made from a manually defined cropping of the image.  This meant that in addition to an administrative backend to allow uploading and management, I needed to provide a tool for selecting an area within the image for a custom thumbnail, not to mention figuring out where and how to do the tinting.</p>
<p><span id="more-1347"></span>So here&#8217;s how I approached it:  I created two STI models deriving from a common GalleryImage model, all of which are related to the GalleryItem that encapsulates the item name, description, etc:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> GalleryItem <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  <span style="color:#5A0A0A; font-weight:bold;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:full_image</span>, <span style="color:#ff3333; font-weight:bold;">:class_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'GalleryMainImage'</span>, 
                          <span style="color:#ff3333; font-weight:bold;">:foreign_key</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'full_image_id'</span>, 
                          <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:destroy</span>
&nbsp;
  <span style="color:#5A0A0A; font-weight:bold;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:custom_thumbnail</span>, 
                    <span style="color:#ff3333; font-weight:bold;">:class_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'GalleryThumbnail'</span>,
                    <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:destroy</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GalleryImage <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GalleryMainImage <span style="color:#006600; font-weight:bold;">&lt;</span> GalleryImage
  <span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:gallery_item</span>, <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:destroy</span>
  has_attachment <span style="color:#ff3333; font-weight:bold;">:content_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:image</span>, 
                 <span style="color:#ff3333; font-weight:bold;">:storage</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:file_system</span>, 
                 <span style="color:#ff3333; font-weight:bold;">:max_size</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 50.<span style="color:#9900CC;">megabytes</span>,
                 <span style="color:#ff3333; font-weight:bold;">:resize_to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'457&gt;'</span>,
                 <span style="color:#ff3333; font-weight:bold;">:thumbnails</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:default_thumbnail</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'68x68!'</span>,
                                  <span style="color:#ff3333; font-weight:bold;">:gray_thumbnail</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'68x68!'</span> <span style="color:#006600; font-weight:bold;">&#125;</span>,
                 <span style="color:#ff3333; font-weight:bold;">:path_prefix</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'public/gallery'</span>,
                 <span style="color:#ff3333; font-weight:bold;">:thumbnail_class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;GalleryThumbnail&quot;</span>
&nbsp;
  validates_as_attachment
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> GalleryThumbnail <span style="color:#006600; font-weight:bold;">&lt;</span> GalleryImage
  <span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:gallery_item</span>, <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:destroy</span>
  has_attachment <span style="color:#ff3333; font-weight:bold;">:content_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:image</span>, 
                 <span style="color:#ff3333; font-weight:bold;">:storage</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:file_system</span>, 
                 <span style="color:#ff3333; font-weight:bold;">:max_size</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 1.<span style="color:#9900CC;">megabyte</span>,
                 <span style="color:#ff3333; font-weight:bold;">:resize_to</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'68x68'</span>,
                 <span style="color:#ff3333; font-weight:bold;">:thumbnails</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:gray_thumbnail</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'68x68'</span> <span style="color:#006600; font-weight:bold;">&#125;</span>,
                 <span style="color:#ff3333; font-weight:bold;">:path_prefix</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'public/gallery'</span>
&nbsp;
  validates_as_attachment
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So, the important takeaways here are the following:
<ul>
<li>All thumbnails would be of class &#8220;GalleryThumbnail&#8221;.</li>
<li>An item has one GalleryMainImage with it&#8217;s own attachment_fu-generated thumbnails.  These thumbnails are the &#8220;uncropped&#8221; thumbnails.</li>
<li>An item can have two more custom cropped thumbnails associated with it &#8211; a color one and a gray one.</li>
</ul>
<p>Is it clunky the way attachment_fu generates thumbnails given how we&#8217;re setting this up (why does GalleryThumbnail have thumbnails?)?  Yes.  But note especially that the specific settings in the &#8220;has_attachment&#8221; line (such as resizing and thumbnail generation) are only applied to a <em>full</em> attachment model.  Therefore, only the objects associated with &#8220;item.full_image&#8221; and &#8220;item.custom_thumbnail&#8221; go through the full swath of attachment_fu processing.  In other words, just because a full image generates thumbnails of class GalleryThumbnail does not mean each of those GalleryThumbnail objects gets their own thumbnails &#8211; obviously, that would be stupid.  It&#8217;s better to not think about the generated images attachment_fu delivers as &#8220;thumbnails&#8221; so much as different versions of the attachment.</p>
<p>The next step is doing the grayscaling.  I determined the path forward on this first by consulting the designer who delivered the mockup.  He went back into Photoshop and gave me an idea of what filters and processes were applied to the thumbnails he had created.  Basically, he created a grayscaled version of the thumbnail and then applied a gradient map that mapped black to a shade of blue.  It gave it a very interesting effect:</p>
<div align=center><img src="http://blog.6thdensity.net/wp-content/uploads/2009/02/141744150_e76e7e0aed_default_thumbnail.jpg" alt="141744150_e76e7e0aed_default_thumbnail" title="Original color thumbnail" width="68" height="68" style="margin: 1em;" /><img src="http://blog.6thdensity.net/wp-content/uploads/2009/02/bandw.jpg" alt="bandw" title="Grayscaled copy" width="68" height="68" style="margin: 1em;" /><img src="http://blog.6thdensity.net/wp-content/uploads/2009/02/141744150_e76e7e0aed_gray_thumbnail.jpg" alt="141744150_e76e7e0aed_gray_thumbnail" title="Using level_colors to gradient map black to blue" width="68" height="68" style="margin: 1em;" /></div>
<p>It took a lot of digging, but I was able to find two RMagick methods that could reproduce this effect: <a href="http://www.imagemagick.org/RMagick/doc/image3.html#quantize">quantize</a> and <a href="http://www.imagemagick.org/RMagick/doc/image2.html#level_colors">level_colors</a>.  Now it was just a matter of finding out how to integrate them into the thumbnailing process. I was surprised that simple callbacks basically did the trick.  I put a method in the base class for the images:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> PortfolioImage <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
protected
  <span style="color:#9966CC; font-weight:bold;">def</span> update_gray_thumbnail!  
    <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#9966CC; font-weight:bold;">unless</span> thumbnail.<span style="color:#9900CC;">blank</span>? <span style="color:#008000; font-style:italic;"># only perform this on a custom thumbnail or an original image</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># the code below looks dumb, but I think the trick is that RMagick</span>
    <span style="color:#008000; font-style:italic;"># can only perform one operation per file load.  I don't get it.</span>
    thumb = thumbnails.<span style="color:#9900CC;">find_by_thumbnail</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;gray_thumbnail&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">Magick::Image</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>thumb.<span style="color:#9900CC;">full_filename</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#5A0A0A; font-weight:bold;">first</span>.<span style="color:#9900CC;">quantize</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">256</span>,<span style="color:#6666ff; font-weight:bold;">Magick::GRAYColorspace</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>thumb.<span style="color:#9900CC;">full_filename</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">Magick::Image</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>thumb.<span style="color:#9900CC;">full_filename</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#5A0A0A; font-weight:bold;">first</span>.<span style="color:#9900CC;">level_colors</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#201000&quot;</span>, <span style="color:#996600;">&quot;#f7f7f7&quot;</span>, <span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>thumb.<span style="color:#9900CC;">full_filename</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Remember: in our modeling, everything is a GalleryImage.  What makes a given GalleryImage a thumbnail according to attachment_fu is that it has a non-nil response to the &#8220;thumbnail&#8221; message (if this were our gray_thumbnail, it would return &#8220;gray_thumbnail&#8221; in response to the &#8220;thumbnail&#8221; message).  So by proceeding only if thumbnail returns a blank response, we guarantee that we work with a main attachment like a MainImage or custom thumbnail, and that we don&#8217;t work on any of their associated images.</p>
<p>So look at how we generate thumbnails for a GalleryThumbnail and GalleryMainImage: there&#8217;s a default_thumbnail and a gray_thumbnail.  If you&#8217;re using attachment_fu with &#8220;:storage => :file_system&#8221;, then you have physical files in the project that you can modify to your heart&#8217;s content.  The above method changes the actual file associated with the &#8220;gray_thumbnail&#8221;, which is initially saved as a color thumbnail.  So if you put a hook in your GalleryMainImage and GalleryThumbnail models to make this alteration on saving the model, you should be money:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#5A0A0A; font-weight:bold;">after_save</span> <span style="color:#ff3333; font-weight:bold;">:update_gray_thumbnail</span>!</pre></div></div>

<p>Attachment_fu regenerates thumbnails on every model save, so it&#8217;s important we reapply the RMagick processing each time.</p>
<p>So what about the custom cropping?  Well, you&#8217;ll need a controller that can generate a new GalleryThumbnail to be associated with the GalleryItem.  All I&#8217;ll say on that count is that you should look at some javascript cropping utilities; I&#8217;m using jquery so I used <a href="http://odyniec.net/projects/imgareaselect/">imgAreaSelect</a>.  Following <a href="http://www.webmotionuk.co.uk/php-jquery-image-upload-and-crop-v11/">this example</a> I was able to create a tool letting the user drag a box over with previewing of the resulting thumbnail, passing the coordinates for cropping to the controller via a form submission.  Then it was just a matter of cropping the image, which once again is merely a matter of manipulating the actual full-size image file saved in the public directory after the fact:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"> <span style="color:#9966CC; font-weight:bold;">def</span> create
    item = GalleryItem.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:portfolio_item_id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    crop = item.<span style="color:#9900CC;">full_image</span>.<span style="color:#9900CC;">crop</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:x1</span><span style="color:#006600; font-weight:bold;">&#93;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:y1</span><span style="color:#006600; font-weight:bold;">&#93;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:w</span><span style="color:#006600; font-weight:bold;">&#93;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:h</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    thumb = GalleryThumbnail.<span style="color:#5A0A0A; font-weight:bold;">new</span>
    thumb.<span style="color:#9900CC;">uploaded_data</span> = crop
    thumb.<span style="color:#5A0A0A; font-weight:bold;">save</span>    
    item.<span style="color:#9900CC;">portfolio_thumbnail</span> = thumb
    <span style="color:#9966CC; font-weight:bold;">if</span> item.<span style="color:#5A0A0A; font-weight:bold;">save</span>
      <span style="color:#5A0A0A; font-weight:bold;">flash</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Cropped custom thumbnail saved.&quot;</span>
      <span style="color:#5A0A0A; font-weight:bold;">redirect_to</span> admin_gallery_item_path<span style="color:#006600; font-weight:bold;">&#40;</span>item<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#5A0A0A; font-weight:bold;">flash</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:error</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Error resizing&quot;</span>
      <span style="color:#5A0A0A; font-weight:bold;">render</span> <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'new'</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>I have a &#8220;crop&#8221; method on GalleryMainImage defined thusly:</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> crop<span style="color:#006600; font-weight:bold;">&#40;</span>x, y, width,height<span style="color:#006600; font-weight:bold;">&#41;</span>
    blob = <span style="color:#CC00FF; font-weight:bold;">StringIO</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Magick::Image</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>full_filename<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#5A0A0A; font-weight:bold;">first</span>.<span style="color:#9900CC;">crop</span><span style="color:#006600; font-weight:bold;">&#40;</span>x.<span style="color:#5A0A0A; font-weight:bold;">to_i</span>, y.<span style="color:#5A0A0A; font-weight:bold;">to_i</span>, width.<span style="color:#5A0A0A; font-weight:bold;">to_i</span>, height.<span style="color:#5A0A0A; font-weight:bold;">to_i</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_blob</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">'tempfile'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> blob,
     <span style="color:#996600;">'content_type'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;image/#{filename.split('.').last}&quot;</span>,
     <span style="color:#996600;">'filename'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;custom_#{filename}&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The use of StringIO and returning a hash is just tricks to get attachment_fu to accept our cropped image as a parameter for &#8220;uploaded_data=&#8221;.  And once the cropped image is passed into &#8220;uploaded_data=&#8221; and object is saved, the thumbnail will be generated using the cropped image &#8211; and grayscaled appropriately!</p>
<p>That&#8217;s pretty much it &#8211; I know this is really complicated, but I hope it helps somebody out there.  Feel free to ask questions, and be advised that I may revisit this article to word things differently.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/65/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Duckpin bowling on Wednesday</title>
		<link>http://jeremyweiland.com/archives/66</link>
		<comments>http://jeremyweiland.com/archives/66#comments</comments>
		<pubDate>Mon, 02 Feb 2009 16:17:04 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1345</guid>
		<description><![CDATA[In case you don&#8217;t get the Facebook invite, feel free to join Tasha and me for duckpin bowling at Plaza Bowl (523 E Southside Plz) on Wednesday at 6:30pm to celebrate my 30th birthday!
]]></description>
			<content:encoded><![CDATA[<p>In case you don&#8217;t get the Facebook invite, feel free to join Tasha and me for duckpin bowling at Plaza Bowl (523 E Southside Plz) on Wednesday at 6:30pm to celebrate my 30th birthday!</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/66/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An RJS Redirect Matcher for rspec</title>
		<link>http://jeremyweiland.com/archives/67</link>
		<comments>http://jeremyweiland.com/archives/67#comments</comments>
		<pubDate>Thu, 29 Jan 2009 16:10:46 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1333</guid>
		<description><![CDATA[You know what&#8217;s stupid?  Clumsily checking for a javascript redirect in your RJS with this kind of shit:

it &#34;should redirect to the collaborative quote screen&#34; do
  xhr :post, 'attach', :attachment_id =&#62; '4023'
  response.body.should =~ /window\.location\.href = \&#34;/collabquote\&#34;;&#34;
end

Not only is this ugly, but it ties your test to a particular route, rather than [...]]]></description>
			<content:encoded><![CDATA[<p>You know what&#8217;s stupid?  Clumsily checking for a javascript redirect in your RJS with this kind of shit:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">&quot;should redirect to the collaborative quote screen&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  xhr <span style="color:#ff3333; font-weight:bold;">:post</span>, <span style="color:#996600;">'attach'</span>, <span style="color:#ff3333; font-weight:bold;">:attachment_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'4023'</span>
  response.<span style="color:#9900CC;">body</span>.<span style="color:#9900CC;">should</span> =~ <span style="color:#006600; font-weight:bold;">/</span>window\.<span style="color:#9900CC;">location</span>\.<span style="color:#9900CC;">href</span> = \<span style="color:#996600;">&quot;/collabquote<span style="color:#000099;">\&quot;</span>;&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Not only is this ugly, but it ties your test to a particular route, rather than allowing you to use your named route.  So I whipped up a custom RJS redirect matcher in about 10 minutes following the guidelines in <a href="http://www.sameshirteveryday.com/2007/09/15/rspec-custom-expectation-matcher-example/">this post</a>, and I was surprised how easy it was.<span id="more-1333"></span>  It should be pretty self explanatory.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> RedirectViaRjsToMatcher  
  <span style="color:#9966CC; font-weight:bold;">class</span> RedirectViaRjsTo  
    <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>expected<span style="color:#006600; font-weight:bold;">&#41;</span>  
      <span style="color:#0066ff; font-weight:bold;">@expected</span> = expected  
    <span style="color:#9966CC; font-weight:bold;">end</span>  
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> matches?<span style="color:#006600; font-weight:bold;">&#40;</span>target<span style="color:#006600; font-weight:bold;">&#41;</span>  
      <span style="color:#0066ff; font-weight:bold;">@target</span> = target
      <span style="color:#0066ff; font-weight:bold;">@url</span> = target.<span style="color:#9900CC;">body</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'&quot;'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@target</span>.<span style="color:#9900CC;">body</span> == <span style="color:#996600;">&quot;window.location.href = <span style="color:#000099;">\&quot;</span>#{@expected}<span style="color:#000099;">\&quot;</span>;&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>  
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> failure_message  
      <span style="color:#996600;">&quot;expected redirect via rjs to #{@expected}, redirected instead to #{@url}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>  
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> negative_failure_message  
      <span style="color:#996600;">&quot;unexpected redirect via rjs to #{@expected}&quot;</span>  
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Actual matcher that is exposed </span>
  <span style="color:#9966CC; font-weight:bold;">def</span> redirect_via_rjs_to<span style="color:#006600; font-weight:bold;">&#40;</span>expected<span style="color:#006600; font-weight:bold;">&#41;</span>  
    RedirectViaRjsTo.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>expected<span style="color:#006600; font-weight:bold;">&#41;</span>  
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>All you need to do is save this file in /spec/custom/redirect_via_rjs_to.rb and include it in /spec/spec_helper.rb like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'spec/be_the_same_as'</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">Spec::Runner</span>.<span style="color:#9900CC;">configure</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span>  
  config.<span style="color:#9966CC; font-weight:bold;">include</span><span style="color:#006600; font-weight:bold;">&#40;</span>RedirectViaRjsToMatcher<span style="color:#006600; font-weight:bold;">&#41;</span>  
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Voilla!  It really is that easy, and turns that first spec into something a bit more readable and reusable:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">&quot;should redirect to the collaborative quote screen&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  xhr <span style="color:#ff3333; font-weight:bold;">:post</span>, <span style="color:#996600;">'attach'</span>, <span style="color:#ff3333; font-weight:bold;">:attachment_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'4023'</span>
  response.<span style="color:#9900CC;">should</span> redirect_via_rjs_to quote_path<span style="color:#006600; font-weight:bold;">&#40;</span>@quote<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p><strong>UPDATE:</strong> <a href="http://someguysblog.com/">Jim</a> clued me into <a href="http://apidock.com/rspec/Spec/Matchers/simple_matcher">simple_matcher</a>, which appears to be yet another very easy way to create custom matchers.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/67/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Behind the scenes at Richmond’s unbowling destination</title>
		<link>http://jeremyweiland.com/archives/68</link>
		<comments>http://jeremyweiland.com/archives/68#comments</comments>
		<pubDate>Sat, 17 Jan 2009 18:59:43 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1295</guid>
		<description><![CDATA[So Matt O., I, and our wives rolled over to Plaza Bowl and Duckpins this past Thursday to duckpin bowl and drink PBR pitchers. We had a great time and ended up talking to the owner (it was a slow night). He asked us about any ideas we had for better marketing the place and [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.6thdensity.net/wp-content/uploads/2009/01/plazabowl004-300x225.jpg" alt="plazabowl004" title="plazabowl004" width="300" height="225" class="alignleft size-medium wp-image-1308" />So Matt O., I, and our wives rolled over to <a href="http://www.myspace.com/plazabowlrva" title="Plaza Bowl and Duckpins, LLC">Plaza Bowl and Duckpins</a> this past Thursday to <a href="http://www.ndbc.org/">duckpin bowl</a> and drink PBR pitchers. We had a great time and ended up talking to the owner (it was a slow night). He asked us about any ideas we had for better marketing the place and we had a great conversation that really explored our love for the place. </p>
<p>Plaza Bowl is really just an incredibly fun destination &#8211; it&#8217;s laid back, and you don&#8217;t feel pressure to bowl 300. There&#8217;s now a stage where some of the lanes used to be, and bands play regularly. It&#8217;s got a great retro feel since none of the equipment has been manufactured for decades, and the owner maintains it himself.</p>
<p>In fact, we were thrilled that he invited us behind the scenes to observe the 1950s era machinery that runs the lanes, and I snapped some pictures on my iPhone. As programmers Matt and I were amazed at this complex mechanical state machine, and there&#8217;s an aesthetic to the vintage gears, chains, and conveyor belts that adds to the appeal. A steampunk&#8217;s dream!</p>
<p>I highly recommend that you check Plaza Bowl and Duckpins out. It&#8217;s difficult to communicate how awesome this place is, but I guarantee you&#8217;ll have a good time and be back. We want to keep this place in town, so show your love!</p>
<div style="text-align: center;"><img src="http://blog.6thdensity.net/wp-content/uploads/2009/01/plazabowl002-300x225.jpg" alt="plazabowl002" title="plazabowl002" width="300" height="225" style="margin: 30px;" /><img src="http://blog.6thdensity.net/wp-content/uploads/2009/01/plazabowl005-300x235.jpg" alt="plazabowl005" title="plazabowl005" width="300" height="235"  style="margin: 30px;"  /><img src="http://blog.6thdensity.net/wp-content/uploads/2009/01/plazabowl001-247x300.jpg" alt="plazabowl001" title="plazabowl001" width="247" height="300"  style="margin: 30px;" /><img src="http://blog.6thdensity.net/wp-content/uploads/2009/01/plazabowl003-181x300.jpg" alt="plazabowl003" title="plazabowl003" width="181" height="300"  style="margin: 30px;" /></div>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/68/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happy Holidays</title>
		<link>http://jeremyweiland.com/archives/69</link>
		<comments>http://jeremyweiland.com/archives/69#comments</comments>
		<pubDate>Thu, 25 Dec 2008 16:34:57 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1239</guid>
		<description><![CDATA[Here&#8217;s a photo montage Tasha put together to express our wishes for the season.  Enjoy your days of mirth!

]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a photo montage Tasha put together to express our wishes for the season.  Enjoy your days of mirth!</p>
<div align=center><img alt="Happy Holidays" src="http://farm4.static.flickr.com/3097/3134820393_bd3d032f86_b.jpg" title="Happy Holidays from the McWeilands" class="aligncenter" width="701" height="1024" /></div>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/69/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>All hail the Amen Break!</title>
		<link>http://jeremyweiland.com/archives/70</link>
		<comments>http://jeremyweiland.com/archives/70#comments</comments>
		<pubDate>Wed, 24 Dec 2008 14:11:11 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Blogroll]]></category>

		<guid isPermaLink="false">http://blog.6thdensity.net/?p=1235</guid>
		<description><![CDATA[Since I used to produce amateur electronic music, mostly drum and bass / jungle (you can sample some of my work here) I&#8217;m very familiar with the prevalence and importance of the Amen break.  So it&#8217;s cool to see a short documentary that can chronicle its adventures and tie it into free culture and [...]]]></description>
			<content:encoded><![CDATA[<p>Since I used to produce amateur electronic music, mostly drum and bass / jungle (you can sample some of my work <a href="http://significator.net">here</a>) I&#8217;m very familiar with the prevalence and importance of the Amen break.  So it&#8217;s cool to see a short documentary that can chronicle its adventures and tie it into free culture and the tyranny of intellectual property law.</p>
<div align=center><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/5SaFTm2bcac&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/5SaFTm2bcac&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://jeremyweiland.com/archives/70/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.392 seconds -->
