<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.thewebfellas.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.thewebfellas.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>TheWebFellas - Ruby on Rails Development Specialists UK - Blog</title>
  <id>tag:thewebfellas.com,2008:mephisto/blog</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  
  <link href="http://thewebfellas.com/blog" rel="alternate" type="text/html" />
  <updated>2008-11-18T11:24:56Z</updated>
  <geo:lat>50.848928</geo:lat><geo:long>-1.165624</geo:long><link rel="self" href="http://feeds.thewebfellas.com/thewebfellas/blog" type="application/atom+xml" /><entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Chris Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-11-18:2390</id>
    <published>2008-11-18T11:23:00Z</published>
    <updated>2008-11-18T11:24:56Z</updated>
    <category term="Blog" />
    <category term="amazon" />
    <category term="aws" />
    <category term="caching" />
    <category term="cdn" />
    <category term="cloudfront" />
    <category term="content" />
    <category term="content delivery" />
    <category term="s3" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/457081947/amazon-launches-their-cdn-cloudfront" rel="alternate" type="text/html" />
    <title>Amazon launches their CDN - CloudFront</title>
<summary type="html">&lt;p&gt;Amazon have now launched their Content Delivery Network - &lt;a href="http://aws.amazon.com/cloudfront/" title="CloudFront"&gt;CloudFront&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In line with the other offerings from Amazon Web Services then the product is based around Usage Based Charging - with the prices varying between Edge locations&lt;/p&gt;
&lt;p&gt;There are Edge servers located in the United States, Europe, Hong Kong and Japan.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Amazon have now launched their Content Delivery Network - &lt;a href="http://aws.amazon.com/cloudfront/" title="CloudFront"&gt;CloudFront&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In line with the other offerings from Amazon Web Services then the product is based around Usage Based Charging - with the prices varying between Edge locations&lt;/p&gt;
&lt;p&gt;There are Edge servers located in the United States, Europe, Hong Kong and Japan.&lt;/p&gt;
&lt;h3&gt;What is it?&lt;/h3&gt;
&lt;p&gt;From the Amazon blurb:&lt;/p&gt;
&lt;blockquote&gt;Amazon CloudFront is a web service that gives businesses and software developers an easy and cost effective way to distribute popular content with low latency and high data transfer speeds. Like all AWS Infrastructure Services, Amazon CloudFront is a self-service, pay-per-use offering, requiring no long term commitments or minimum fees. With CloudFront, your files are delivered to end-users using a global network of edge locations. Amazon CloudFront works seamlessly with Amazon Simple Storage Service (Amazon S3), which durably stores the original, definitive versions of your files.&lt;/blockquote&gt;

&lt;h3&gt;How does it work?&lt;/h3&gt;
&lt;p&gt;The CloudFront service is backed by usage of S3. You store your content in an S3 bucket and register the bucket with the CloudFront service. This creates a 'distribution' of the content you have registered. A distribution has a unique domain name associated with it you can access your cached content - you can also map your own name to this via a CNAME record.&lt;/p&gt;
&lt;p&gt;When users request content via this distribution, they will be automatically routed to the nearest Edge location to retrieve the content.&lt;/p&gt;

&lt;h3&gt;The API&lt;/h3&gt;
&lt;p&gt;As with the other AWS tools then you will need to &lt;a href="http://aws.amazon.com/cloudfront" title="Sign-up to CloudFront"&gt;add it to your account&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/GettingStartedGuide/" title="CloudFront Getting Started Guide"&gt;Getting Started Guide&lt;/a&gt; and &lt;a href="http://docs.amazonwebservices.com/AmazonCloudFront/2008-06-30/DeveloperGuide/" title="CloudFront Developer Guide"&gt;Developer Guide&lt;/a&gt; give you all the details you need to use the service via the API.&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/457081947" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/11/18/amazon-launches-their-cdn-cloudfront</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-11-02:2250</id>
    <published>2008-11-02T10:40:00Z</published>
    <updated>2008-11-25T08:47:04Z</updated>
    <category term="Blog" />
    <category term="attachments" />
    <category term="attachment_fu" />
    <category term="imagemagick" />
    <category term="mp3" />
    <category term="paperclip" />
    <category term="plugins" />
    <category term="rails" />
    <category term="rails development" />
    <category term="uploads" />
    <category term="validation" />
    <category term="windows" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/439865559/goodbye-attachment_fu-hello-paperclip" rel="alternate" type="text/html" />
    <title>Goodbye attachment_fu, hello Paperclip</title>
<summary type="html">&lt;p&gt;For well over a year now &lt;a href="http://github.com/technoweenie/attachment_fu/wikis" title="See attachment_fu on Github"&gt;attachment_fu&lt;/a&gt; has been my plugin of choice for adding file uploads to our Rails applications, but recently my fellow WebFellas have been raving about &lt;a href="http://www.thoughtbot.com/projects/paperclip/" title="See Paperclip on Github"&gt;Paperclip&lt;/a&gt; from the clever guys at &lt;a href="http://www.thoughtbot.com/" title="Visit thoughbot"&gt;thoughtbot&lt;/a&gt;. As I’ve just started yet another new project I figured it was time to take Paperclip for a spin.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;For well over a year now &lt;a href="http://github.com/technoweenie/attachment_fu/wikis" title="See attachment_fu on Github"&gt;attachment_fu&lt;/a&gt; has been my plugin of choice for adding file uploads to our Rails applications, but recently my fellow WebFellas have been raving about &lt;a href="http://www.thoughtbot.com/projects/paperclip/" title="See Paperclip on Github"&gt;Paperclip&lt;/a&gt; from the clever guys at &lt;a href="http://www.thoughtbot.com/" title="Visit thoughbot"&gt;thoughtbot&lt;/a&gt;. As I’ve just started yet another new project I figured it was time to take Paperclip for a spin.&lt;/p&gt;
&lt;h3&gt;The obligatory special instructions for Windows&lt;/h3&gt;
&lt;p&gt;If, like me, you’re a long-suffering Rails developer using Windows (those &lt;a href="http://www.apple.com/macbook/" title="Get a Mac"&gt;new Macbooks&lt;/a&gt; are looking very tempting!) then you won’t be surprised to learn that getting Paperclip up and running needs a few special steps.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;h4&gt;Install the plugin&lt;/h4&gt;
    &lt;p&gt;You can install Paperclip as a regular Rails plugin from GitHub from a command prompt window like this:&lt;/p&gt;
    &lt;pre&gt;&lt;kbd&gt;ruby script/plugin install git://github.com/thoughtbot/paperclip.git&lt;/kbd&gt;&lt;/pre&gt;
    &lt;p&gt;You’ll obviously need a working copy of &lt;a href="http://code.google.com/p/msysgit/" title="Git for Windows"&gt;Git&lt;/a&gt;: thoughtbot &lt;a href="http://giantrobots.thoughtbot.com/2008/10/29/we-ve-turned-our-subversion-server-off" title="Read the announcement"&gt;switched off their SVN repository this week&lt;/a&gt; and the gemified version of Paperclip on &lt;a href="http://rubyforge.org/projects/paperclip/" title="See the Paperclip Gem"&gt;RubyForge&lt;/a&gt; is quite old now and probably shouldn’t be used (gems via GitHub are not currently available).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;h4&gt;Download ImageMagick&lt;/h4&gt;
    &lt;p&gt;Paperclip uses &lt;a href="http://www.imagemagick.org/script/index.php" title="Read about ImageMagick"&gt;ImageMagick&lt;/a&gt; to perform image processing, which is thankfully much easier to install on Windows than &lt;a href="/blog/2007/12/2/imagescience-and-rubyinline-on-windows" title="Read my blog about ImageScience on Windows"&gt;ImageScience&lt;/a&gt; was for attachment_fu!&lt;/p&gt;
    &lt;p&gt;You’ve got two options:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;
        &lt;h5&gt;Use the RMagick gem&lt;/h5&gt;
        &lt;p&gt;Although Paperclip doesn’t use the &lt;a href="http://rmagick.rubyforge.org/" title="Find out about RMagick"&gt;RMagick&lt;/a&gt; gem, if you think you’re ever likely to then you should download the latest gem from &lt;a href="http://rubyforge.org/frs/?group_id=12&amp;amp;amp;release_id=26026" title="Download the Gem"&gt;RubyForge&lt;/a&gt; and use the version of ImageMagick that is bundled with it (see the &lt;kbd&gt;Readme.html&lt;/kbd&gt; file included in the download for installation instructions).&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;h5&gt;Download the latest version of ImageMagick&lt;/h5&gt;
        &lt;p&gt;If you’re not bothered about RMagick support then download and install the &lt;a href="http://www.imagemagick.org/script/binary-releases.php#windows" title="Download the installer"&gt;ImageMagick installer&lt;/a&gt; (I used the 16 bits per pixel dynamic library without any problems).&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;Whichever installation method you choose make sure you select the ‘Update executable search path’ option in the ImageMagick installer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;h4&gt;Patch the Tempfile class&lt;/h4&gt;
    &lt;p&gt;&lt;ins datetime="20081122"&gt;&lt;strong&gt;Important:&lt;/strong&gt; after looking into this a bit more closely I’m no longer 100% convinced that patching Tempfile is necessary for Paperclip. I’d recommend you first try using it without this patch and if you start to see problems then try the patch (and it’d also be great if you could post a comment to let me know that you needed the patch).&lt;/ins&gt;&lt;/p&gt;
    &lt;p&gt;Paperclip makes extensive use of temporary files via the Ruby &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/tempfile/rdoc/index.html" title="See the Tempfile documentation"&gt;&lt;code&gt;Tempfile&lt;/code&gt;&lt;/a&gt; class. Unfortunately this can cause some strangeness in Windows where the file size is incorrectly reported as zero bytes (attachment_fu suffered with similar problems). The solution is to monkey-patch &lt;code&gt;Tempfile&lt;/code&gt; like this:&lt;/p&gt;
    &lt;pre&gt;&lt;code class="ruby"&gt;require 'tempfile'
class Tempfile
  def size
    if @tmpfile
      @tmpfile.fsync
      @tmpfile.flush
      @tmpfile.stat.size
    else
      0
    end
  end
end&lt;/code&gt;&lt;/pre&gt;
    &lt;p&gt;This code comes from &lt;a href="http://epirsch.blogspot.com/2008/01/fixing-attachmentfu-on-windows-like.html" title="Read Emmanuel’s blog"&gt;Emmanuel Pirsch&lt;/a&gt; and has worked well for me in several projects. I typically drop it into my &lt;kbd&gt;lib/patches&lt;/kbd&gt; folder and require it from an initializer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;h4&gt;Shutdown, close, reopen and restart&lt;/h4&gt;
    &lt;p&gt;Make sure you shutdown any running servers, close any console windows and then reopen and restart as needed: it’s important that your consoles and servers pick up the updated &lt;kbd&gt;PATH&lt;/kbd&gt; environment variable set by the installer as Paperclip calls ImageMagick using the command line (which is why it doesn’t need RMagick).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Where to begin&lt;/h3&gt;
&lt;p&gt;At this point you should be ready to start using the plugin. I won’t cover the basics of using Paperclip with Rails as they’ve already been explained on the &lt;a href="http://www.thoughtbot.com/projects/paperclip" title="Go to the project page"&gt;official project page&lt;/a&gt; as well as in Jim Neath’s &lt;a href="http://jimneath.org/2008/04/17/paperclip-attaching-files-in-rails/" title="Read the tutorial"&gt;excellent tutorial&lt;/a&gt;&lt;ins datetime="20081106"&gt; and more recently in a &lt;a href="http://railscasts.com/episodes/134-paperclip" title="Watch the RailsCast"&gt;RailsCast&lt;/a&gt; from Ryan Bates&lt;/ins&gt;. However there are some newer features and tips that you should know about to get the best out of Paperclip.&lt;/p&gt;
&lt;h3&gt;Protect your attributes&lt;/h3&gt;
&lt;p&gt;If you’ve used attachment_fu then you’re probably aware that older versions &lt;a href="/blog/2008/3/3/hackers-love-attachment_fu" title="Read about attachment_fu and attr_protected"&gt;didn’t like attr_protected&lt;/a&gt;. The good news is that not only has attachment_fu &lt;a href="http://github.com/technoweenie/attachment_fu/commit/9d754014744b039d82e3e55b3cc7f7c35c16ab08" title="See the commit on GitHub"&gt;recently been fixed&lt;/a&gt;, but Paperclip also plays nicely with both attr_protected and attr_accessible too. So to play it safe you should protect the &lt;code&gt;file_name&lt;/code&gt;, &lt;code&gt;content_type&lt;/code&gt; and &lt;code&gt;size&lt;/code&gt; attributes in your models, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;has_attached_file :logo
attr_protected :logo_file_name, :logo_content_type, :logo_size&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Attaching in migrations or the Rails console&lt;/h3&gt;
&lt;p&gt;Attaching a file to a model in a migration or when using the Rails console is much easier with Paperclip than it is with attachment_fu. All you need to do is open a File object and assign it to the attachment attribute of the model:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;user = User.first
File.open('path/to/image.png') { |photo_file| user.photo = photo_file }
user.save&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course that works on pretty much every operating system in the world &lt;em&gt;except&lt;/em&gt; Windows, where the assignment will cause an error like this to be output in the console window:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;identify: no decode delegate for this image format `C:/DOCUME~1/ROB~1.CML/LOCALS~1/Temp/stream.2692.0'.&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;In addition to this cryptic message, the file isn’t attached properly and no thumbnails are generated. Thankfully the solution is simple (although it did take me a few moments of head scratching to figure it out): set binary mode on the file to stop Windows treating it like a text file:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;user = User.first
File.open('path/to/image.png', 'rb') { |photo_file| user.photo = photo_file }
user.save&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Discarding an uploaded image&lt;/h3&gt;
&lt;p&gt;When an image file is uploaded Paperclip stores it using the &lt;code&gt;original&lt;/code&gt; style name. While it isn’t possible to tell Paperclip to simply discard the original image, it is possible to define your own &lt;code&gt;original&lt;/code&gt; style which Paperclip will then use. As an example, if your model contains the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;has_attached_file :photo, 
                  :styles =&gt; { :original =&gt; '250x250&gt;', 
                               :small =&gt; '50x50' }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then even if a huge photo (say 1600x1600) is uploaded, it won’t be stored on your server (or &lt;a href="http://aws.amazon.com/s3/" title="Not heard of S3? Where have you been?!"&gt;S3&lt;/a&gt; bucket). You will however still have an &lt;code&gt;original&lt;/code&gt; file but it will have been resized to 250x250, helping to reduce the amount of storage space needed for attachments.&lt;/p&gt;
&lt;h3&gt;Styles can be Procs too&lt;/h3&gt;
&lt;p&gt;Most of the time you’ll probably be passing &lt;a href="http://www.imagemagick.org/Magick++/Geometry.html" title="Find out about ImageMagick geometry strings"&gt;geometry strings&lt;/a&gt; for the &lt;code&gt;has_attached_file :styles&lt;/code&gt; option, but a very nice feature is the ability to also pass a &lt;code&gt;Proc&lt;/code&gt; to provide dynamic geometry string generation. For example, you might have a model that has &lt;code&gt;photo_width&lt;/code&gt; and &lt;code&gt;photo_height&lt;/code&gt; attributes that can be specified by the user and you want to generate a ‘custom’ thumbnail that uses these dimensions. Paperclip allows you to do this easily:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;has_attached_file :photo, 
                  :styles =&gt; { :original =&gt; '250x250&gt;', 
                               :small =&gt; '50x50', 
                               :custom =&gt; Proc.new { |instance| "#{instance.photo_width}x#{instance.photo_height}&gt;" } }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see the &lt;code&gt;Proc&lt;/code&gt; receives the object that the attachment is part of as a parameter and returns a geometry string generated using the &lt;code&gt;photo_width&lt;/code&gt; and &lt;code&gt;photo_height&lt;/code&gt; attributes. Adding a call to the &lt;a href="http://dev.thoughtbot.com/paperclip/classes/Paperclip/Attachment.html#M000053" title="Read the documentation"&gt;&lt;code&gt;reprocess!&lt;/code&gt;&lt;/a&gt; method of the attachment object in your model’s &lt;code&gt;before_save&lt;/code&gt; callback also allows you to regenerate the thumbnails if either of these attributes are updated.&lt;/p&gt;
&lt;h3&gt;Rename files on upload&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;has_attached_file :url&lt;/code&gt; and &lt;code&gt;:path&lt;/code&gt; options can be used to customise the name of your attachments: &lt;code&gt;:url&lt;/code&gt; defines the URL that will be used by things like &lt;code&gt;image_tag&lt;/code&gt; to access your image and allows you to either provide direct access to the image or to route access through a controller (to provide permission checking for example) and &lt;code&gt;:path&lt;/code&gt; determines where the image file is stored either on your server (for file system storage) or in an S3 bucket.&lt;/p&gt;
&lt;p&gt;Both options use interpolation, allowing you to use special tags that will be replaced with actual values at runtime (just like regular Ruby string interpolation). The default interpolations provided by the plugin are:&lt;/p&gt;
&amp;lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;:rails_root&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The path to the Rails application.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:rails_env&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The current environment (e.g. development, production)&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:class&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The class name of the model that the attachment is part of, underscored and pluralised for your convenience.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:basename&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The name of the originally uploaded file without its extension.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:extension&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The file extension of the originally uploaded file.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:id&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The ID of the model that the attachment is part of.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:id_partition&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The same as &lt;code&gt;:id&lt;/code&gt; but formatted as a string using &lt;a href="http://www.37signals.com/svn/archives2/id_partitioning.php" title="Read about ID partitioning"&gt;ID partitioning&lt;/a&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:attachment&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The name of the attachment attribute (defined in the call to &lt;code&gt;has_attached_file&lt;/code&gt;) downcased and pluralised for your enjoyment.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:style&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The current style of the attachment file being processed (e.g. in the ‘discarding an uploaded image‘ example above the &lt;code&gt;:style&lt;/code&gt; would be one of ‘original’ or ‘small’)&lt;/dd&gt;
&amp;lt;/dl&gt;
&lt;p&gt;The default &lt;code&gt;:url&lt;/code&gt; and &lt;code&gt;:path&lt;/code&gt; options for &lt;code&gt;has_attached_file&lt;/code&gt; are:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;:url =&gt; "/:attachment/:id/:style/:basename.:extension"
:path =&gt; ":rails_root/public/:attachment/:id/:style/:basename.:extension"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s say you’d prefer your users’ photos to be stored in a single ‘photos’ subdirectory of the &lt;kbd&gt;public/images&lt;/kbd&gt; folder on your server using the user ID and style as the base file name. Your model would need to contain something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;has_attached_file :photo,
                  :url =&gt; "/images/:attachment/:id_:style.:extension",
                  :path =&gt; ":rails_root/public/images/:attachment/:id_:style.:extension"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to hide images behind a controller do something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;has_attached_file :photo,
                  :url =&gt; "/:class/:id/:attachment/:style.:extension",
                  :path =&gt; ":rails_root/attachments/:class/:id/:attachment/:style.:extension"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example the URL points to a &lt;code&gt;PhotosController&lt;/code&gt; nested within the &lt;code&gt;User&lt;/code&gt; resource (an example URL would be &lt;kbd&gt;/users/2/photos/small.png&lt;/kbd&gt;) and the attachment files are stored outside of the public root in a subdirectory of an attachments folder (e.g. &lt;kbd&gt;RAILS_ROOT/attachments/users/2/photos/small.png&lt;/kbd&gt;). The show action of the &lt;code&gt;PhotosController&lt;/code&gt; would be responsible for returning the binary data of the appropriate file using the &lt;code&gt;:style&lt;/code&gt;, &lt;code&gt;:extension&lt;/code&gt; and &lt;code&gt;:user_id&lt;/code&gt; parameters.&lt;/p&gt;
&lt;h3&gt;Custom interpolations&lt;/h3&gt;
&lt;p&gt;In addition to the predefined interpolations described above, Paperclip makes it very easy to define your own. For example one of my models has a &lt;code&gt;symbol&lt;/code&gt; attribute that I want to use in the file name of images attached to it, so in a Rails initializer I add the following code:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;Paperclip::Attachment.interpolations[:symbol] = proc do |attachment, style|
  attachment.instance.symbol.downcase
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Interpolations are &lt;code&gt;Procs&lt;/code&gt; that take two parameters, the attachment object and the current style, and it is possible to access the model that the attachment is part of using the &lt;code&gt;instance&lt;/code&gt; attribute of the attachment object.&lt;/p&gt;
&lt;p&gt;After adding my custom interpolation I can then use it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;has_attached_file :logo,
                  :url =&gt; '/:attachment/:symbol/:style/:basename.:extension',
                  :path =&gt; ':rails_root/public/:attachment/:symbol/:style/:basename.:extension '&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Deleting an existing attachment&lt;/h3&gt;
&lt;p&gt;Deleting an existing attachment from a model is as simple as setting the attachment attribute to &lt;code&gt;nil&lt;/code&gt;. In a RESTful world you could do this from the &lt;code&gt;destroy&lt;/code&gt; action of a controller that maps to the attachment (for example using a &lt;samp&gt;DELETE&lt;/samp&gt; request on &lt;kbd&gt;/users/1/photos&lt;/kbd&gt;).&lt;/p&gt;
&lt;p&gt;You can also quite easily replace an existing attachment by POSTing a new file to your update action. Things get a little trickier if you want to be able to delete an existing attachment &lt;strong&gt;without&lt;/strong&gt; replacing it using an update action.&lt;/p&gt;
&lt;p&gt;The approach I’ve used is to add a checkbox to the edit form that when checked causes any existing attachment to be removed unless a new file has also been selected in the file upload box. Here’s the view code:&lt;/p&gt;
&lt;p&gt;&lt;ins datetime="20081123"&gt;&lt;a href="/about#chris-anderton" title="Chris at TheWebFellas"&gt;Chris&lt;/a&gt; has pointed out that this would be even cleaner if I used an instance variable with accessors, so I’ve updated the code to use this approach.&lt;/ins&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;&amp;lt;% form_for(user, :html =&amp;gt; { :multipart =&amp;gt; true }) do |f| %&amp;gt;
  &amp;lt;%# lots of exciting form fields %&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;%= f.label(:photo, 'Upload photo') %&amp;gt;
    &amp;lt;%= f.file_field(:photo) %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;%- unless user.new_record? || !user.photo? -%&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;%= f.label(:delete_photo, 'Delete photo') %&amp;gt;
      &amp;lt;%= image_tag(user.photo.url, :alt =&amp;gt; 'Photo', :title =&amp;gt; 'Current photo') %&amp;gt;
      &amp;lt;%= f.check_box(:delete_photo) %&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;%- end -%&amp;gt;
  &amp;lt;%# lots more exciting form fields %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This adds a checkbox, using an instance variable to track its value, if the user isn’t new and already has a photo. The instance variable is added to the model like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;
  def delete_photo=(value)
    @delete_photo = !value.to_i.zero?
  end
  
  def delete_photo
    !!@delete_photo
  end
  alias_method :delete_photo?, :delete_photo&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the update action in the controller looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;def update
  params[:user][:photo] = nil if params[:user][:photo].blank? &amp;amp;&amp;amp; delete_photo?

  if @user.update_attributes(params[:user])
    flash_and_redirect_to('User profile was saved successfully.', :notice, users_path(@user))
  else
    page_title.unshift('Edit user')
    render(:action =&gt; 'edit')
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first line forces the value of the photo attribute in the params hash to nil if no photo file has been uploaded and the checkbox was ticked. The call to update_attributes then works as normal, updating the photo attribute as appropriate, with Paperclip taking care of the rest.&lt;/p&gt;
&lt;p&gt;When I was trawling the interwebs to see if anybody else had some code to do this I didn’t find anything, so please let me know if you’ve come up with a better idea but haven’t yet had chance to share it with the world!&lt;/p&gt;
&lt;h3&gt;Getting clever with validations&lt;/h3&gt;
&lt;p&gt;&lt;ins datetime="20081106"&gt;I’ve added this section thanks to &lt;a href="#comment-2289" title="Skip to the comment"&gt;DMitry’s comment&lt;/a&gt;.&lt;/ins&gt;&lt;/p&gt;
&lt;p&gt;Paperclip allows you to validate the presence, content type and size of an attachment file using the &lt;a href="http://dev.thoughtbot.com/paperclip/classes/Paperclip/ClassMethods.html#M000007" title="Read the documentation"&gt;&lt;code&gt;validates_attachment_presence&lt;/code&gt;&lt;/a&gt;, &lt;a href="http://dev.thoughtbot.com/paperclip/classes/Paperclip/ClassMethods.html#M000008" title="Read the documentation"&gt;&lt;code&gt;validates_attachment_content_type&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://dev.thoughtbot.com/paperclip/classes/Paperclip/ClassMethods.html#M000005" title="Read the documentation"&gt;&lt;code&gt;validates_attachment_size&lt;/code&gt;&lt;/a&gt; methods.&lt;/p&gt;
&lt;p&gt;But what if you want to do something more advanced? For example let’s say we have a &lt;code&gt;Track&lt;/code&gt; model that represents uploaded MP3 files and, because we want to preserve the musical integrity of our site, we want to prevent files from certain ‘artists’ being uploaded. To do this we can use a custom validation method:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class Track &amp;lt; ActiveRecord::Base

  has_attached_file :mp3

  validates_attachment_presence :mp3
  validates_attachment_content_type :mp3, :content_type =&gt; [ 'application/mp3', 'application/x-mp3', 'audio/mpeg', 'audio/mp3' ]
  validates_attachment_size :mp3, :less_than =&gt; 10.megabytes

  validate :must_have_valid_artist_tag

  protected

    def must_have_valid_artist_tag
      Mp3Info.open(mp3.to_file.path) do |mp3info|
        errors.add(:mp3, 'must not be a Michael Bolton song (what are you thinking?!)') if mp3info.tag.artist == 'Michael Bolton'
      end if mp3?
    rescue Mp3InfoError =&gt; e
      errors.add(:mp3, "unable to process file (#{e.message})")
    end

end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This model makes use of the &lt;a href="http://ruby-mp3info.rubyforge.org/" title="Take a look at the ruby-mp3info gem"&gt;ruby-mp3info&lt;/a&gt; gem to access the ID3 tags: you’ll need to install it and set up the necessary &lt;code&gt;config.gem&lt;/code&gt; line in your &lt;kbd&gt;environment.rb&lt;/kbd&gt; file to get this example working.&lt;/p&gt;
&lt;p&gt;The first four lines of the model are straight calls to Paperclip methods: they setup the attachment and ensure it is validated for presence, content type and size. The model then contains a &lt;code&gt;validate&lt;/code&gt; callback for the &lt;code&gt;must_have_valid_artist_tag&lt;/code&gt; method: this is where the good stuff happens.&lt;/p&gt;
&lt;p&gt;Here’s a line-by-line breakdown:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;p&gt;If a new MP3 file has been attached then at the time of validation it won’t have been written to the correct location on the server (or S3 bucket). Fortunately the &lt;code&gt;to_file&lt;/code&gt; method means we don’t have to worry about this: it returns a &lt;code&gt;File&lt;/code&gt; object that will either refer to an existing attachment file or the new, temporary, uploaded file. The first line of the validation method passes the path name of this file to the &lt;code&gt;Mp3Info&lt;/code&gt; class so that it can process it.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;In this simple example the validation checks if the &lt;kbd&gt;artist&lt;/kbd&gt; tag of the MP3 file is set to a particular artist and flags an error as appropriate.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;Before doing any of the above it’s a good idea to check that a file was actually attached: Paperclip provides a simple way to do this by calling the &lt;code&gt;mp3?&lt;/code&gt; method which returns &lt;code&gt;true&lt;/code&gt; if a file has been attached. The name of this method is based on the name of your attachment, so for example if your model contains &lt;code&gt;has_attached_file :photo&lt;/code&gt; then the &lt;code&gt;photo?&lt;/code&gt; method will be used check for an attached file.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;The &lt;code&gt;Mp3Info&lt;/code&gt; class will raise an &lt;code&gt;Mp3InfoException&lt;/code&gt; if something goes wrong. We need to rescue it in case an invalid MP3 file is uploaded.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;To keep this example simple, if an exception occurs an error is added to the &lt;code&gt;mp3&lt;/code&gt; attribute containing the exception message: you could naturally do something more impressive here.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By providing you with direct access to the attachment file using the &lt;code&gt;to_file&lt;/code&gt; method, Paperclip enables you to do pretty much anything with the attachment, either in a validation like the one shown above or in a different model callback such as &lt;code&gt;before_save&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;What’s next?&lt;/h3&gt;
&lt;p&gt;Being hosted on GitHub naturally means that other developers are forking Paperclip and changing it to suit their needs. We’re no exception and Chris has recently been going &lt;a href="http://github.com/thewebfellas/paperclip_edge/tree/master" title="Take a look at TheWebFellas fork on GitHub"&gt;forking crazy&lt;/a&gt;, adding support for thumbnailing of video attachments amongst other things, so I’ll try and nudge him into blogging about his changes.&lt;/p&gt;
&lt;p&gt;Even though I’ve only been using Paperclip for a couple of days I really like its straightforward, flexible approach and I’ll definitely be using it for future projects (that is until something newer and shinier comes along). However my old friend attachment_fu is far from dead and so I’ll be keeping  watch on its development too.&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/439865559" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/11/2/goodbye-attachment_fu-hello-paperclip</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-09-13:1802</id>
    <published>2008-09-13T17:15:00Z</published>
    <updated>2008-10-30T08:37:41Z</updated>
    <category term="Blog" />
    <category term="ajax" />
    <category term="dates" />
    <category term="javascript" />
    <category term="json" />
    <category term="rails development" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/436713070/making-a-date-with-javascript-and-json" rel="alternate" type="text/html" />
    <title>Making a date with JavaScript and JSON</title>
<summary type="html">&lt;p&gt;I’ve always enjoyed a kind of love/hate relationship with JavaScript, something which I think stems from my early exposure to using it on Microsoft platforms in the late 90’s, using half-baked debuggers, inconsistent browsers and a huge degree of trial and error. It’s not that I can’t write clever things in JavaScript, just that it’s not my most favourite job: if I can delegate to someone else I usually will!&lt;/p&gt;
&lt;p&gt;Last week I was left with no choice but to roll up my sleeves and get coding: I was putting together a financial trading application prototype for one of our new clients and wanted to use JavaScript and &lt;a href="http://www.json.org/" title="Find out what JSON is (you don't know?!)"&gt;JSON&lt;/a&gt; to periodically update pricing information.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I’ve always enjoyed a kind of love/hate relationship with JavaScript, something which I think stems from my early exposure to using it on Microsoft platforms in the late 90’s, using half-baked debuggers, inconsistent browsers and a huge degree of trial and error. It’s not that I can’t write clever things in JavaScript, just that it’s not my most favourite job: if I can delegate to someone else I usually will!&lt;/p&gt;
&lt;p&gt;Last week I was left with no choice but to roll up my sleeves and get coding: I was putting together a financial trading application prototype for one of our new clients and wanted to use JavaScript and &lt;a href="http://www.json.org/" title="Find out what JSON is (you don't know?!)"&gt;JSON&lt;/a&gt; to periodically update pricing information.&lt;/p&gt;
&lt;p&gt;I decided to stick with the Rails default &lt;a href="http://www.prototypejs.org/" title="More about Prototype"&gt;Prototype&lt;/a&gt; library and use &lt;a href="http://script.aculo.us/" title="More about script.aculo.us"&gt;script.aculo.us&lt;/a&gt; for some snazzy effects. Our trendy UI designer friends up in London have a fondness for &lt;a href="http://mootools.net/" title="Find out about mootools"&gt;MooTools&lt;/a&gt;, so we’ve used that on the last couple of projects they’ve worked with us on. I figured it was time to brush up on the latest changes in Prototype as it’s been about 6 months since I last used it.&lt;/p&gt;
&lt;p&gt;After a couple of hours I was actually starting to feel better about the whole JavaScript thing: Prototype makes it a lot nicer to work with, the &lt;a href="http://getfirebug.com/" title="Get Firebug now, it will change your life!"&gt;Firebug&lt;/a&gt; extension for Firefox is fandabidozi, and Rails makes JSON output trivial. My price information was updating nicely without me getting even slightly stressed. And then it came to the task of showing the date and time of the last price update…&lt;/p&gt;
&lt;p&gt;My JSON output included the &lt;code&gt;updated_at&lt;/code&gt; date nicely formatted using &lt;a href="http://en.wikipedia.org/wiki/ISO_8601" title="Get the lowdown on ISO 8601"&gt;ISO 8601&lt;/a&gt;: “no problem” I naively thought, “I’m sure JS can handle that”. I figured the &lt;code&gt;Date&lt;/code&gt; class would parse it and then I could format it appropriately for display on the page. I soon discovered that it couldn’t: the &lt;code&gt;Date&lt;/code&gt; class just sat there mocking me, Prototype didn’t come to my aid and my attempt to find any mention in the documentation of how dates in JSON data should be handled ended in failure. My old hatred of all things JavaScript started to return.&lt;/p&gt;
&lt;p&gt;And then, just as I was about to give up, a random Google search stumbled upon &lt;a href="http://www.datejs.com/" title="Get Datejs now"&gt;Datejs&lt;/a&gt;. Either I’ve not been reading the right blogs or this library is the best kept secret in the JavaScript world. Behold the simplicity it brings to JSON date handling:&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;date = Date.parse(json_data.updated_at);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ISO 8601 is just one of the many date formats it can handle, but parsing dates is naturally not all it can do: comparison, validation, addition and subtraction and, perhaps most useful from the presentation point of view, formatting. The core &lt;a href="http://code.google.com/p/datejs/wiki/APIDocumentation#toString" title="See the documentation"&gt;&lt;code&gt;toString&lt;/code&gt;&lt;/a&gt; method provides a large number of format specifiers, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code class="javascript"&gt;date.toString("MMMM dd, yyyy HH:mm"); /* September 12, 2008 11:23 */
date.toString("M/d/yyyy");            /* 12-Sep-2008 */&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if that’s not enough the &lt;a href="http://code.google.com/p/datejs/source/browse/trunk/src/extras.js" title="Browse the source code"&gt;extras library&lt;/a&gt; provides a &lt;code&gt;format&lt;/code&gt; method that works just like the &lt;a href="http://ruby-doc.org/core/classes/Date.html#M000620" title="Ruby strftime RDoc"&gt;Ruby&lt;/a&gt; or &lt;a href="http://uk.php.net/manual/en/function.strftime.php" title="PHP strftime documentation"&gt;PHP strftime&lt;/a&gt; methods.&lt;/p&gt;
&lt;p&gt;To get started, take a look at the &lt;a href="http://www.datejs.com/2007/11/27/getting-started-with-datejs/" title="Read the blog post"&gt;introductory blog post&lt;/a&gt;, &lt;a href="http://code.google.com/p/datejs/source/browse/#svn/trunk" title="Browse the source code"&gt;download the code&lt;/a&gt; (ignore the Alpha 1.0 release as it is out of date), &lt;a href="http://code.google.com/p/datejs/wiki/APIDocumentation" title="Read the documentation"&gt;read the documentation&lt;/a&gt; and enjoy another step towards completely painless JavaScript development.&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/436713070" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/9/13/making-a-date-with-javascript-and-json</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Chris Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-09-01:1486</id>
    <published>2008-09-01T14:16:00Z</published>
    <updated>2008-09-01T19:10:13Z</updated>
    <category term="Blog" />
    <category term="ami" />
    <category term="convert" />
    <category term="ec2" />
    <category term="migrate" />
    <category term="vmdk" />
    <category term="vmware" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395054/creating-an-new-ec2-ami-from-within-vmware-or-from-vmdk-files" rel="alternate" type="text/html" />
    <title>Creating a new EC2 AMI from within VMware or from VMDK files</title>
<summary type="html">&lt;p&gt;I've used &lt;a href="http://www.vmware.com/" title="VMware"&gt;VMware&lt;/a&gt; for many years to allow me to test and develop various server configurations and distributions. It's where I played with &lt;a href="http://linux-vserver.org/" title="Linux-VServer"&gt;Linux-VServer&lt;/a&gt;, &lt;a href="http://user-mode-linux.sourceforge.net/" title="User Mode Linux"&gt;User Mode Linux (UML)&lt;/a&gt;, &lt;a href="http://kvm.qumranet.com/kvmwiki" title="Kernel Based Virtual Machine"&gt;Kernel Based Virtual Machine (KVM)&lt;/a&gt; and &lt;a href="http://www.xen.org/" title="Xen"&gt;Xen&lt;/a&gt;. The relevent part to EC2 here is obviously that EC2 is also Xen based.&lt;/p&gt;

&lt;p&gt;So far when using EC2 I've stood on the shoulders of giants and taken existing AMIs and used them as they are or &lt;a href="http://docs.amazonwebservices.com/AmazonEC2/dg/2006-06-26/creating-an-ami.html#ami-from-existing-image" title="Modifying an AMI"&gt;with modification&lt;/a&gt;. Always the control freak, I wanted to create my own AMI from scratch. Having slimmed down my hardware inventory (I got complaints about the various half built towers lying around!) then my only option was to either create an image in a loopback device on EC2 or return to my trusty steed of VMware.&lt;/p&gt;

&lt;p&gt;Creating the AMI from VMware was easier than I thought - but just in case anyone else is looking to do it then I thought it worthy of a blog post.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I've used &lt;a href="http://www.vmware.com/" title="VMware"&gt;VMware&lt;/a&gt; for many years to allow me to test and develop various server configurations and distributions. It's where I played with &lt;a href="http://linux-vserver.org/" title="Linux-VServer"&gt;Linux-VServer&lt;/a&gt;, &lt;a href="http://user-mode-linux.sourceforge.net/" title="User Mode Linux"&gt;User Mode Linux (UML)&lt;/a&gt;, &lt;a href="http://kvm.qumranet.com/kvmwiki" title="Kernel Based Virtual Machine"&gt;Kernel Based Virtual Machine (KVM)&lt;/a&gt; and &lt;a href="http://www.xen.org/" title="Xen"&gt;Xen&lt;/a&gt;. The relevent part to EC2 here is obviously that EC2 is also Xen based.&lt;/p&gt;

&lt;p&gt;So far when using EC2 I've stood on the shoulders of giants and taken existing AMIs and used them as they are or &lt;a href="http://docs.amazonwebservices.com/AmazonEC2/dg/2006-06-26/creating-an-ami.html#ami-from-existing-image" title="Modifying an AMI"&gt;with modification&lt;/a&gt;. Always the control freak, I wanted to create my own AMI from scratch. Having slimmed down my hardware inventory (I got complaints about the various half built towers lying around!) then my only option was to either create an image in a loopback device on EC2 or return to my trusty steed of VMware.&lt;/p&gt;

&lt;p&gt;Creating the AMI from VMware was easier than I thought - but just in case anyone else is looking to do it then I thought it worthy of a blog post.&lt;/p&gt;
&lt;p&gt;There are two options for migration - one is to create the image from within the running VMware machine, the other is to convert the &lt;a href="http://www.vmware.com/support/ws55/doc/ws_learning_files_in_a_vm.html" title="Files used in VMware"&gt;VMDK file&lt;/a&gt; into a RAW image.&lt;/p&gt;
&lt;p&gt;I plan to create some base 'clean' images from which I can then create specific appliances - for example a base Centos i386 and x64 install which I will then layer additional software on to create specific appliance images.&lt;/p&gt;
&lt;p&gt;My preferred method is to create the AMI from within the running VMware machine - the resulting AMI is much smaller in size (as I think that during conversion of a VMDK the resulting RAW image is the size of the volume rather than the data - although you can probably override this with options). I've given instructions for both methods so you can make your own mind up.&lt;/p&gt;
&lt;h2&gt;Converting VMDK files for use on EC2&lt;/h2&gt;
&lt;p&gt;Create your machine in VMware as usual and when ready shut it down. Then, grab yourself a copy of &lt;a href="http://bellard.org/qemu/" title="QEMU"&gt;QEMU&lt;/a&gt; as we need to use it to convert the VMDK files.&lt;/p&gt;
&lt;p&gt;Basic usage is:&lt;/p&gt;
&lt;kbd&gt;qemu-img convert -O raw input.vmdk output.raw&lt;/kbd&gt;
&lt;p&gt;The VMDK file will then be converted into a RAW file - we've specified the output format with the &lt;kbd&gt;-O&lt;/kbd&gt; tag and &lt;kbd&gt;qemu-img&lt;/kbd&gt; is intelligent enough to figure out the input format.&lt;/p&gt;
&lt;p&gt;Your image may span several VMDKs in which case you'll need to run a simple shell loop, for example:&lt;/p&gt;
&lt;pre&gt;&lt;kbd&gt;for file in `ls *[0-9].vmdk`; do
  qemu-img convert -O raw $file $file.raw
done
cat *.raw &gt;&gt; output.raw
&lt;/kbd&gt;&lt;/pre&gt;
&lt;p&gt;Depending on the number of files you have for your VMware image you might need to modify the &lt;kbd&gt;ls&lt;/kbd&gt; - my example is purely by way of demonstration.&lt;/p&gt;
&lt;p&gt;Either way, you should now have your VMware disk image in RAW format in the file &lt;kbd&gt;output.raw&lt;/kbd&gt;. Given this is a RAW image it should also be bootable by a local Xen, QEMU or KVM installation.&lt;/p&gt;
&lt;p&gt;The next step is to bundle this into an AMI using &lt;kbd&gt;ec2-bundle-image&lt;/kbd&gt;:&lt;/p&gt;
&lt;kbd&gt;ec2-bundle-image -i output.raw -r x86_64 -c ~/.amazon/cert.pem -k ~/.amazon/pk.pem --user &amp;lt;user id&amp;gt;&lt;/kbd&gt;
&lt;p&gt;The exact values for the &lt;kbd&gt;-c&lt;/kbd&gt;, &lt;kbd&gt;-k&lt;/kbd&gt; and &lt;kbd&gt;--user&lt;/kbd&gt; parameters will depend on the location of your certificate, private key and Amazon AWS account number respectively.&lt;/p&gt;
&lt;p&gt;You might also want to look closely at the documentation for the &lt;kbd&gt;--block-device-mapping&lt;/kbd&gt; parameter to ensure you get a bootable machine with a valid fstab.&lt;/p&gt;
&lt;p&gt;After the image has finished bundling it will (by default) be in your /tmp directory, so the next step is to upload it to an S3 bucket:&lt;/p&gt;
&lt;kbd&gt;ec2-upload-bundle -b &amp;lt;bucket name&amp;gt; -m /tmp/image.manifest.xml -a &amp;lt;access id&amp;gt; -s &amp;lt;secret access id&amp;gt;&lt;/kbd&gt;
&lt;p&gt;With the bundled image in S3 (it will take a while depending on your connection) then you can register the image:&lt;/p&gt;
&lt;kbd&gt;ec2-register &amp;lt;bucket name&amp;gt;/image.manifest.xml&lt;/kbd&gt;
&lt;p&gt;The AMI should then appear when you request a list of your images:&lt;/p&gt;
&lt;kbd&gt;ec2-describe-images&lt;/kbd&gt;
&lt;p&gt;The only remaining thing then is to start up an instance and give it a try!&lt;/p&gt;
&lt;h2&gt;Creating the EC2 AMI from within VMware&lt;/h2&gt;
&lt;p&gt;As mentioned, creating the AMI in this way seems to result in a smaller file - I prefer it as it's also quicker to complete as you don't need to convert and create bundle - you can just create the bundle.&lt;/p&gt;
&lt;p&gt;You'll need to boot your VMware machine and make sure you have the pre-requisites installed to run the EC2 and AMI tools - i.e. ruby, java &gt; 1.5, etc.&lt;/p&gt;
&lt;p&gt;For CentOS I needed to disable the MAC address being specified for my Ethernet device by commenting out the &lt;kbd&gt;HWADDRESS&lt;/kbd&gt; line of the network script.&lt;/p&gt;
&lt;p&gt;Check the amount of disk space you're using - for me it was 1.2Gb for my basic Centos 5.2 install.&lt;/p&gt;
&lt;p&gt;You're then ready to bundle your volume, making sure you specify a size big enough to fit your volumes into along with any software you might want to install in future:&lt;/p&gt;
&lt;kbd&gt;ec2-bundle-vol -c ~/.amazon/cert.pem -k ~/.amazon/pk.pem --user &amp;lt;user id&amp;gt; -d /image -e /image -r x86_64 -s 4096 --no-inherit&lt;/kbd&gt;
&lt;p&gt;Depending on your install you may also need to specify an alternative fstab to use via the &lt;kbd&gt;--fstab&lt;/kbd&gt; option. The &lt;kbd&gt;-s&lt;/kbd&gt; parameter specifies the size - 4Gb in this example - you can set this up to 10Gb which is the current limit imposed by EC2. The &lt;kbd&gt;--no-inherit&lt;/kbd&gt; parameter is required because we're not bundling from within an EC2 instance.&lt;/p&gt;
&lt;p&gt;After the image has finished bundling it will be in your /image directory (because we specified this in our command) - so the next step is to upload it to an S3 bucket:&lt;/p&gt;
&lt;kbd&gt;ec2-upload-bundle -b &amp;lt;bucket name&amp;gt; -m /image/image.manifest.xml -a &amp;lt;access id&amp;gt; -s &amp;lt;secret access id&amp;gt;&lt;/kbd&gt;
&lt;p&gt;With the bundled image in S3 (it will take a while depending on your connection) then you can register the image:&lt;/p&gt;
&lt;kbd&gt;ec2-register &amp;lt;bucket name&amp;gt;/image.manifest.xml&lt;/kbd&gt;
&lt;p&gt;The AMI should then appear when you request a list of your images:&lt;/p&gt;
&lt;kbd&gt;ec2-describe-images&lt;/kbd&gt;
&lt;p&gt;You can then launch an instance using your new AMI (the AMI id will have been provided on completion of the registration, or from the output of the describe command).&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395054" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/9/1/creating-an-new-ec2-ami-from-within-vmware-or-from-vmdk-files</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-08-24:1384</id>
    <published>2008-08-24T10:11:00Z</published>
    <updated>2008-08-27T09:54:54Z</updated>
    <category term="Blog" />
    <category term="actverecord" />
    <category term="aggregation" />
    <category term="composed_of" />
    <category term="patch" />
    <category term="rails development" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395055/giving-composed_of-some-much-needed-lovin" rel="alternate" type="text/html" />
    <title>Giving composed_of some much needed lovin’</title>
<summary type="html">&lt;p&gt;Did you know ActiveRecord includes support for &lt;a href="http://apidock.com/rails/ActiveRecord/Aggregations/ClassMethods" title="Read the documentation"&gt;aggregations&lt;/a&gt;? If you did, have you ever used them? Despite being part of Rails from the start &lt;code&gt;composed_of&lt;/code&gt; tends to lurk in the shadows while newer features like &lt;a href="http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/named_scope" title="Read the documentation"&gt;&lt;code&gt;named_scope&lt;/code&gt;&lt;/a&gt; steal the limelight. It’s time to give &lt;code&gt;composed_of&lt;/code&gt; some love again!&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Did you know ActiveRecord includes support for &lt;a href="http://apidock.com/rails/ActiveRecord/Aggregations/ClassMethods" title="Read the documentation"&gt;aggregations&lt;/a&gt;? If you did, have you ever used them? Despite being part of Rails from the start &lt;code&gt;composed_of&lt;/code&gt; tends to lurk in the shadows while newer features like &lt;a href="http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/named_scope" title="Read the documentation"&gt;&lt;code&gt;named_scope&lt;/code&gt;&lt;/a&gt; steal the limelight. It’s time to give &lt;code&gt;composed_of&lt;/code&gt; some love again!&lt;/p&gt;
&lt;p&gt;Aggregation helps to make your models richer: for example if you’re dealing with money why deal with integer and decimal attributes when you can use something like the &lt;a href="http://dist.leetsoft.com/api/money/" title="Find out about the Money gem"&gt;&lt;code&gt;Money&lt;/code&gt; class&lt;/a&gt;? Thanks to &lt;a href="http://opensoul.org/2006/11/16/making-code-composed_of-code-more-useful" title="Read about the conversion block patch"&gt;various&lt;/a&gt; &lt;a href="http://kinderman.net/articles/2008/01/03/plugin-to-support-composed_of-aggregations-in-activerecord-finder-methods" title="Read about the finder patch"&gt;patches&lt;/a&gt; the shortcomings of the original &lt;code&gt;composed_of&lt;/code&gt; implementation have been addressed, but there is still one that for some reason remains to be fixed: aggregate class constructors.&lt;/p&gt;
&lt;p&gt;The problem is simple: &lt;code&gt;composed_of&lt;/code&gt; assumes that the aggregate class can be instantiated using a simple &lt;code&gt;new&lt;/code&gt; constructor that accepts arguments in the order defined by the &lt;code&gt;:mapping&lt;/code&gt; option. In many cases this works, but if your aggregate class doesn’t conform then you’re left to manually initialise your aggregations (in an &lt;code&gt;after_initialize&lt;/code&gt; callback for example). Not very elegant.&lt;/p&gt;
&lt;p&gt;Here is an example from a recent project I’ve been working on:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class Visitor &amp;lt; ActiveRecord::Base

  composed_of :ip_addr,
              :class_name =&amp;gt; 'IPAddr',
              :mapping =&amp;gt; %w(ip to_i)

end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here the &lt;code&gt;composed_of&lt;/code&gt; aggregation maps the &lt;code&gt;ip&lt;/code&gt; attribute (an integer) to the &lt;a href="http://apidock.com/ruby/IPAddr" title="Read the documentation"&gt;&lt;code&gt;IPAddr&lt;/code&gt;&lt;/a&gt; class from the Ruby standard library. Much of the code that uses this attribute wants to treat it as an IP address rather than a raw integer so it makes sense to represent it as one in the model. Unfortunately this won’t work properly as the &lt;code&gt;IPAddr&lt;/code&gt; constructor requires a second parameter to be passed to the constructor as shown below:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;IPAddr.new(1024768100)
=&amp;gt; ArgumentError: unsupported address family

IPAddr.new(1024768100, Socket::AF_INET)
=&amp;gt; #&amp;lt;IPAddr: IPv4:61.20.184.100/255.255.255.255&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sadly &lt;a href="http://dev.rubyonrails.org/ticket/11122" title="See the 6 month old patch"&gt;previous&lt;/a&gt; &lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/212-add-alternate-constructor-support-to-aggregations" title="See the 3 month old patch"&gt;attempts&lt;/a&gt; to allow &lt;code&gt;composed_of&lt;/code&gt; to be more flexible with constructors have failed to make it into core. Personally I don’t think that too few people requesting an enhancement is a good enough reason not to apply it anyway. Perhaps if &lt;code&gt;composed_of&lt;/code&gt; was more flexible in the first place more people would use it!&lt;/p&gt;
&lt;p&gt;Hopefully though it’ll be third time lucky as I’ve just submitted &lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/892-composed_of-constructor-and-converter-options" title="See the patch"&gt;my own patch&lt;/a&gt; to improve &lt;code&gt;composed_of&lt;/code&gt;. If the core team still don’t feel motivated to apply it then I guess I’ll just release it as a plugin instead. It takes a slightly different approach then the previous patches:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;p&gt;It adds a new &lt;code&gt;:constructor&lt;/code&gt; option that takes a symbol or a proc that will be used to instantiate the aggregate object. It is optional and if not used then the existing behaviour of calling &lt;code&gt;new&lt;/code&gt; with the mapped attributes will be used.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;It deprecates the use of a block to provide a method of converting values assigned to the aggregate attribute. The use of a block didn’t feel particularly consistent with the rest of Rails where typically symbols or procs are passed as options (a good example being the &lt;code&gt;:if&lt;/code&gt; and &lt;code&gt;:unless&lt;/code&gt; options for validations). Of course passing a block will still function, so existing code won’t break, but it will raise a deprecation warning. This change leads on to…&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;It adds a new &lt;code&gt;:converter&lt;/code&gt; option that also takes a symbol or proc that will be used when the aggregate attribute is assigned a value that is not an instance of the aggregate class. This replaces the old block syntax and makes it easier to do things like calling &lt;code&gt;composed_of&lt;/code&gt; from within a &lt;code&gt;with_options&lt;/code&gt; block. If both the &lt;code&gt;:converter&lt;/code&gt; option and a block are passed to &lt;code&gt;composed_of&lt;/code&gt; then the &lt;code&gt;:converter&lt;/code&gt; option will take precedence.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s the IP address example from earlier updated to take advantage of the new options:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class Visitor &amp;lt; ActiveRecord::Base

  composed_of :ip_addr,
              :class_name =&amp;gt; 'IPAddr',
              :mapping =&amp;gt; %w(ip to_i),
              :constructor =&amp;gt; Proc.new { |value| IPAddr.new(value, Socket::AF_INET) },
              :converter =&amp;gt; Proc.new { |value| value.is_a?(Integer) ? IPAddr.new(value, Socket::AF_INET) : IPAddr.new(value.to_s) }

end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Passing a symbol to either the &lt;code&gt;:constructor&lt;/code&gt; or &lt;code&gt;:converter&lt;/code&gt; options provides an easy way to use a class where the constructor is not named &lt;code&gt;new&lt;/code&gt; but still expects arguments in the order defined by the &lt;code&gt;:mapping&lt;/code&gt; option. For example if your aggregate class uses a &lt;code&gt;parse&lt;/code&gt; method for instantiation you could do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class MyClass &amp;lt; ActiveRecord::Base

  composed_of :aggregate_value,
              :class_name =&amp;gt; 'AggregateClass',
              :mapping =&amp;gt; %w(value to_s),
              :constructor =&amp;gt; :parse,
              :converter =&gt; :parse

end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think these simple changes make aggregation with &lt;code&gt;composed_of&lt;/code&gt; much more powerful without breaking existing code. If you’d like to see &lt;code&gt;composed_of&lt;/code&gt; get the love it deserves, take a look at my &lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/892-composed_of-constructor-and-converter-options" title="See the patch"&gt;patch&lt;/a&gt; and give it your support.&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395055" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/8/24/giving-composed_of-some-much-needed-lovin</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Chris Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-08-21:1323</id>
    <published>2008-08-21T14:27:00Z</published>
    <updated>2008-08-21T14:28:14Z</updated>
    <category term="Blog" />
    <category term="amazon" />
    <category term="aws" />
    <category term="cloud" />
    <category term="ebs" />
    <category term="ec2" />
    <category term="elastic" />
    <category term="elastic block store" />
    <category term="persistent storage" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395056/cloud-computing-ec2-persistent-storage-elastic-block-store" rel="alternate" type="text/html" />
    <title>It's arrived - Amazon Elastic Block Store</title>
<content type="html">
            &lt;p&gt;The feature I've been waiting for on EC2 has arrived - persistent storage is now available on the public beta as per an email from the EC2 team:&lt;/p&gt;
&lt;blockquote&gt;We are pleased to announce the release of a significant new Amazon EC2 feature, Amazon Elastic Block Store (EBS), which provides persistent storage for your Amazon EC2 instances. With Amazon EBS, storage volumes can be programmatically created, attached to Amazon EC2 instances, and if even more durability is desired, can be backed with a snapshot to the Amazon Simple Storage Service (Amazon S3).&lt;/blockquote&gt;
&lt;p&gt;At a high level the features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Volumes from 1Gb to 1Tb&lt;/li&gt;
&lt;li&gt;Multiple volumes can be mounted from one AMI&lt;/li&gt;
&lt;li&gt;Implemented as block devices&lt;/li&gt;
&lt;li&gt;Live in an availability zone&lt;/li&gt;
&lt;li&gt;Automatically replicated within the availability zone&lt;/li&gt;
&lt;li&gt;Support snapshots&lt;/li&gt;
&lt;li&gt;Multiple volumes can be used and striped across to improve I/O&lt;/li&gt;
&lt;li&gt;$0.10/gb allocated per month and $0.10 per 1 million I/O requests&lt;/li&gt;
&lt;li&gt;Sample cost based on 100Gb storage and 100 I/O per second is $36/month&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm going to get playing with it and it will be interesting to see how it performs and also compare it on the cost front to some of the options I outlined in a &lt;a href="/blog/2008/6/12/ec2-persistent-storage-for-the-impatient" title="EC2 persistent storage for the impatient"&gt;previous post&lt;/a&gt; - in the meantime you can read more on the &lt;a href="http://www.amazon.com/gp/browse.html/ref=pe_2170_10160930?node=689343011" title="Elastic Block Store"&gt;Amazon Web Services&lt;/a&gt; site.&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395056" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/8/21/cloud-computing-ec2-persistent-storage-elastic-block-store</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Chris Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-08-11:1243</id>
    <published>2008-08-11T12:37:00Z</published>
    <updated>2008-08-11T12:41:14Z</updated>
    <category term="Blog" />
    <category term="development" />
    <category term="flickr" />
    <category term="flickr api" />
    <category term="flickr_fu" />
    <category term="git" />
    <category term="github" />
    <category term="rails" />
    <category term="ruby" />
    <category term="webfellas" />
    <category term="webfellows" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395057/rails-development-uploads-to-flickr-with-flickr_fu" rel="alternate" type="text/html" />
    <title>Fixed! Image uploads to Flickr with flickr_fu</title>
<content type="html">
            &lt;p&gt;One of the projects we’re working on needs to be able to publish images to &lt;a href="http://flickr.com" title="Flickr"&gt;Flickr&lt;/a&gt;. Rather than re-invent the wheel a quick search on &lt;a href="http://rubyforge.org/search/?type_of_search=soft&amp;amp;amp;words=flickr" title="Search for flickr on RubyForge"&gt;RubyForge&lt;/a&gt; and &lt;a href="http://github.com/search?q=flickr" title="Search for flickr on GitHub"&gt;GitHub&lt;/a&gt; turned up a number existing Flickr libraries for Ruby. After considering future requirements, we decided to go with &lt;a href="http://github.com/commonthread/flickr_fu/tree/master" title="flickr_fu"&gt;flickr_fu&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There was just one teeny tiny problem: uploads to Flickr within flickr_fu were broken, as we discovered when we looked at the comments in the &lt;code&gt;Flickr::Uploader&lt;/code&gt; class:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# NOT WORKING ... FILE UPLOADS IN NET::HTTP IS TEH SUCK &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A fork, a clone and a few tweaks later and we’ve got uploads working. The changes are currently in &lt;a href="http://github.com/thewebfellas/flickr_fu/tree/master" title="flickr_fu with working uploads"&gt;our fork&lt;/a&gt; but I’ll also be submitting them upstream after a little more testing.&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395057" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/8/11/rails-development-uploads-to-flickr-with-flickr_fu</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-08-06:1199</id>
    <published>2008-08-06T15:36:00Z</published>
    <updated>2008-08-06T15:37:08Z</updated>
    <category term="Blog" />
    <category term="development" />
    <category term="rails" />
    <category term="ruby" />
    <category term="survey" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395058/and-our-survey-says" rel="alternate" type="text/html" />
    <title>And our survey says…</title>
<content type="html">
            &lt;p&gt;There are currently a couple of web-based surveys being carried out that you may want to take a look at. First up is &lt;a href="http://www.alistapart.com/articles/survey2008" title="Go to the survey"&gt;the survey for people who make websites 2008&lt;/a&gt; aimed at anyone involved in web development from designers to Ruby coders from the guys at &lt;a href="http://www.alistapart.com/" title="Go to A List Apart"&gt;A List Apart&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.alistapart.com/articles/survey2008" title="Go to the survey" class="image-link"&gt;&lt;img title="Go to the survey" src="/assets/2008/8/3/alistapart-survey-2008.png" alt="A List Apart Survey Banner" /&gt;&lt;/a&gt; Nearly 33,000 people took part in &lt;a href="http://www.alistapart.com/articles/2007surveyresults" title="See last year’s results"&gt;2007&lt;/a&gt; and it will be interesting to see what has changed and what has remained the same in terms of salary, experience, education and working conditions over the last year.&lt;/p&gt;
&lt;p&gt;The second comes from &lt;a href="http://haml.hamptoncatlin.com/" title="Find out about HAML"&gt;HAML&lt;/a&gt; creator &lt;a href="http://rethink.unspace.ca/" title="See Hampton at unspace"&gt;Hampton Catlin&lt;/a&gt; in the form of the more Ruby-centric &lt;a href="http://survey.hamptoncatlin.com/" title="Go to the survey"&gt;Hampton’s Ruby Survey 2008&lt;/a&gt;. At the time of writing over 900 people have responded, so if you haven’t already, now’s the time to get your entry in.&lt;/p&gt;
&lt;p&gt;The survey covers Ruby and Javascript frameworks, testing, interpreters and in a bizarre twist ends with religious beliefs. It will certainly be interesting to discover if the Ruby community is big on new-age spirituality or is just a godless bunch of coders!&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395058" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/8/6/and-our-survey-says</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-08-03:1196</id>
    <published>2008-08-03T15:10:00Z</published>
    <updated>2008-10-29T22:03:43Z</updated>
    <category term="Blog" />
    <category term="css" />
    <category term="helper" />
    <category term="html" />
    <category term="rails" />
    <category term="renderer" />
    <category term="view" />
    <category term="will_paginate" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395059/roll-your-own-pagination-links-with-will_paginate" rel="alternate" type="text/html" />
    <title>Roll your own pagination links with will_paginate</title>
<summary type="html">&lt;p&gt;Mislav’s &lt;a href="http://github.com/mislav/will_paginate/tree/master" title="will_paginate on GitHub"&gt;will_paginate&lt;/a&gt; plugin (and Gem) has become the &lt;span&gt;de facto&lt;/span&gt; standard for pagination in Rails, replacing the often derided &lt;a href="http://rails-doc.org/rails/ActionController/Pagination" title="See how we used to live"&gt;classic pagination&lt;/a&gt; from the dark days before Rails 2.0. If you haven’t used will_paginate before then Ryan Bates’ &lt;a href="http://railscasts.com/episodes/51-will-paginate" title="See  RailsCast #51"&gt;RailsCast&lt;/a&gt; is a good introduction, although be warned that it is just over a year old and there have been a number of changes to the plugin in that time (the current version is &lt;del&gt;2.3.2&lt;/del&gt; &lt;ins&gt;2.3.6&lt;/ins&gt;).&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Mislav’s &lt;a href="http://github.com/mislav/will_paginate/tree/master" title="will_paginate on GitHub"&gt;will_paginate&lt;/a&gt; plugin (and Gem) has become the &lt;span&gt;de facto&lt;/span&gt; standard for pagination in Rails, replacing the often derided &lt;a href="http://rails-doc.org/rails/ActionController/Pagination" title="See how we used to live"&gt;classic pagination&lt;/a&gt; from the dark days before Rails 2.0. If you haven’t used will_paginate before then Ryan Bates’ &lt;a href="http://railscasts.com/episodes/51-will-paginate" title="See  RailsCast #51"&gt;RailsCast&lt;/a&gt; is a good introduction, although be warned that it is just over a year old and there have been a number of changes to the plugin in that time (the current version is &lt;del&gt;2.3.2&lt;/del&gt; &lt;ins&gt;2.3.6&lt;/ins&gt;).&lt;/p&gt;
&lt;h3&gt;The standard view helper&lt;/h3&gt;
&lt;p&gt;The plugin includes a helper, unsurprisingly named &lt;code&gt;will_paginate&lt;/code&gt; that makes it easy to add pagination links to your views. Here’s an example of its use:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# In the controller
@users = User.paginate(:page =&gt; params[:page])

# In the view
&amp;lt;%= will_paginate(@users) %&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will produce the following HTML markup:&lt;/p&gt;
&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;div class="pagination"&amp;gt;&amp;lt;span class="disabled prev_page"&amp;gt;&amp;laquo; Previous&amp;lt;/span&amp;gt; &amp;lt;span class="current"&amp;gt;1&amp;lt;/span&amp;gt; &amp;lt;a href="/users?page=2" rel="next"&amp;gt;2&amp;lt;/a&amp;gt; &amp;lt;a href="/users?page=3"&amp;gt;3&amp;lt;/a&amp;gt; &amp;lt;a href="/users?page=2" class="next_page" rel="next"&amp;gt;Next &amp;raquo;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see the helper uses the fairly common markup of a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; containing links or spans for the page numbers along with previous and next page links. The plugin includes a number of CSS examples that allow the markup to be styled like &lt;a href="http://www.digg.com/" title="See digg pagination in action"&gt;digg&lt;/a&gt; or &lt;a href="http://www.flickr.com/" title="See flickr pagination in action"&gt;flickr&lt;/a&gt; (take a look &lt;a href="http://mislav.caboo.se/static/will_paginate/" title="See example styles"&gt;here&lt;/a&gt; for more) and the helper accepts a hash of options that allow basic customisation.&lt;/p&gt;
&amp;lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;:container&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Determines whether or not the container &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; is included in the generated markup (defaults to true).&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:class&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Allows the CSS class of the container &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; to be specified (defaults to &lt;samp&gt;pagination&lt;/samp&gt;).&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:previous_label&lt;/code&gt;&lt;/dt&gt;
  &lt;dt&gt;&lt;code&gt;:next_label&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Customises the previous and next page link labels.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:page_links&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Determines whether or not the individual page links are included in the generated markup (defaults to true). If false then only previous and next page links are generated.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:inner_window&lt;/code&gt;&lt;/dt&gt;
  &lt;dt&gt;&lt;code&gt;:outer_window&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Customises the number of links displayed at either side of the current page (&lt;code&gt;:inner_window&lt;/code&gt;) and at the start and end of the page links (&lt;code&gt;:outer_window&lt;/code&gt;).&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;:separator&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Specifies the text inserted between the individual HTML elements generated by the helper (defaults to a single space).&lt;/dd&gt;
&amp;lt;/dl&gt;
&lt;h3&gt;Doing it your way&lt;/h3&gt;
&lt;p&gt;The standard helper provides customisation through CSS styling and the options listed above, but what do you do if the UI designer on your project insists that the pagination markup must look like this?&lt;/p&gt;
&lt;pre&gt;&lt;code class="html"&gt;&amp;lt;ul class="pagination"&amp;gt;
  &amp;lt;li class="previous"&amp;gt;&amp;lt;a href="/users?page=1"&amp;gt;« Previous&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;&amp;lt;a href="/users?page=1"&amp;gt;1&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;li class="current"&amp;gt;2&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;&amp;lt;a href="/users?page=3"&amp;gt;3&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;li class="next"&amp;gt;&amp;lt;a href="/users?page=3"&amp;gt;Next »&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You have a couple of options: either you beat the designer with a stick until they agree that the default markup is acceptable or, if like us you prefer a non-violent approach to web development, you can take advantage of will_paginate’s support for custom link renderers.&lt;/p&gt;
&lt;p&gt;Here’s an example that will generate the above markup:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class PaginationListLinkRenderer &amp;lt; WillPaginate::LinkRenderer

  def to_html
    links = @options[:page_links] ? windowed_links : []

    links.unshift(page_link_or_span(@collection.previous_page, 'previous', @options[:previous_label]))
    links.push(page_link_or_span(@collection.next_page, 'next', @options[:next_label]))

    html = links.join(@options[:separator])
    @options[:container] ? @template.content_tag(:ul, html, html_attributes) : html
  end

protected

  def windowed_links
    visible_page_numbers.map { |n| page_link_or_span(n, (n == current_page ? 'current' : nil)) }
  end

  def page_link_or_span(page, span_class, text = nil)
    text ||= page.to_s
    if page &amp;amp;&amp;amp; page != current_page
      page_link(page, text, :class =&amp;gt; span_class)
    else
      page_span(page, text, :class =&amp;gt; span_class)
    end
  end

  def page_link(page, text, attributes = {})
    @template.content_tag(:li, @template.link_to(text, url_for(page)), attributes)
  end

  def page_span(page, text, attributes = {})
    @template.content_tag(:li, text, attributes)
  end

end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see the link renderer is a subclass of &lt;code&gt;WillPaginate::LinkRenderer&lt;/code&gt; the main method of which is &lt;code&gt;to_html&lt;/code&gt;: this is the method that is used by the view helper to generate pagination markup. In this example I’ve chosen to preserve support for all of the standard options (&lt;code&gt;:container&lt;/code&gt;, &lt;code&gt;:previous_label&lt;/code&gt;, etc.) however you do not have to do so in your own link renderers if you don’t want to. I’ve also chosen to override the four protected methods that are called upon by &lt;code&gt;to_html&lt;/code&gt; to actually perform the HTML generation:&lt;/p&gt;
&amp;lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;windowed_links&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Generates the individual page number links using a call to &lt;code&gt;visible_page_numbers&lt;/code&gt; to determine the page numbers that should be included based on the inner and outer window options.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;page_link_or_span&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Used by &lt;code&gt;windowed_links&lt;/code&gt; to generate the appropriate HTML for a page: this will be a link for all but the current page.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;page_link&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Generates a list item containing a link to a specific page.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;page_span&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Generates a list item containing text rather than a link.&lt;/dd&gt;
&amp;lt;/dl&gt;
&lt;p&gt;Of course you don’t have to override these methods if you don’t want to: you could choose to do all of your rendering in your custom &lt;code&gt;to_html&lt;/code&gt; method or you could choose to define your own protected methods for performing specific tasks, the choice is yours. In this example I chose to use the existing method names for two reasons: it makes it easier for somebody else to maintain the code as it follows the same naming as the standard link renderer, and I couldn’t think of any better names!&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;WillPaginate::LinkRenderer&lt;/code&gt; also has &lt;code&gt;initialize&lt;/code&gt; and &lt;code&gt;prepare&lt;/code&gt; methods that you can extend in your own renderer, although in most cases you won’t need to.&lt;/p&gt;
&amp;lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;initialize&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;The constructor initialises the &lt;code&gt;gap_marker&lt;/code&gt; attribute used by the &lt;code&gt;windowed_links&lt;/code&gt; method: this is the HTML that is used to fill in the gaps in page numbers (caused by the inner and outer window settings) and defaults to &lt;code&gt;&amp;lt;span class="gap"&amp;gt;&amp;amp;hellip;&amp;lt;/span&amp;gt;&lt;/code&gt;. The gap marker is not used in the example renderer above.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;prepare&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;This method is called each time you use the &lt;code&gt;will_paginate&lt;/code&gt; helper in your view and is passed the collection being paginated, the options hash and view template.&lt;/dd&gt;
&amp;lt;/dl&gt;
&lt;p&gt;If you need to do one-time initialisation when your renderer is created then override the &lt;code&gt;initialize&lt;/code&gt; method, and if you need to perform initialisation each time the renderer is called override &lt;code&gt;prepare&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Having created a custom renderer you need to tell will_paginate to use it. There are two ways to do this, the first is to pass the &lt;code&gt;:renderer&lt;/code&gt; option like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;&amp;lt;%= will_paginate(@users, :renderer =&amp;gt; PaginationListLinkRenderer) %&amp;gt;&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;:renderer&lt;/code&gt; option accepts a class name string, a class or an instance of a link renderer. If you want your custom link renderer to be the default for all pagination you don’t have to add a &lt;code&gt;:renderer&lt;/code&gt; option to all of your &lt;code&gt;will_paginate&lt;/code&gt; calls, instead you can specify the default in a Rails initializer like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;WillPaginate::ViewHelpers.pagination_options[:renderer] = 'PaginationListLinkRenderer'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your view can then contain &lt;code&gt;&amp;lt;%= will_paginate(@users) %&amp;gt;&lt;/code&gt; and your link renderer will be used automatically.&lt;/p&gt;
&lt;p&gt;Custom link renderers are an excellent, if underused, feature of will_paginate that give you the freedom to markup your pagination links in whatever creative way you can come up with. Go forth and paginate!&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395059" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/8/3/roll-your-own-pagination-links-with-will_paginate</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-07-20:1161</id>
    <published>2008-07-20T10:30:00Z</published>
    <updated>2008-07-20T10:32:15Z</updated>
    <category term="Blog" />
    <category term="api" />
    <category term="docrails" />
    <category term="documentation" />
    <category term="php" />
    <category term="rails development" />
    <category term="rails-doc" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395060/finally-decent-documentation-for-rails-developers" rel="alternate" type="text/html" />
    <title>Finally: decent documentation for Rails developers</title>
<content type="html">
            &lt;p&gt;Last week Jeremy McAnally &lt;a href="http://www.omgbloglol.com/?p=34" title="Read Jeremy’s post"&gt;talked&lt;/a&gt; about the continuing decline in Rails blogging. Like many Rails developers I’ve learned a lot from blogs over the last couple of years: in the early days it was pretty much the only way to find out about how Rails worked as the &lt;a href="http://api.rubyonrails.com/" title="See the Rails API"&gt;official&lt;/a&gt; documentation was poor to say the least.&lt;/p&gt;
&lt;p&gt;In my opinion though, the future for Rails documentation is not as bleak as Jeremy suggests. Less blogging could simply indicate a move towards better quality postings: I’d rather have a choice from a handful of really well written blogs than the hundreds of “OMG!!! Look how awesome Rails is…” style posts that I used to have to trawl through – less hype and more substance is definitely better.&lt;/p&gt;
&lt;p&gt;The official documentation is, at last, being improved too: as &lt;a href="http://weblog.rubyonrails.org/2008/5/2/help-improve-rails-documentation-on-git-branch" title="Read the announcement"&gt;announced in May&lt;/a&gt; there is now a &lt;a href="http://github.com/lifo/docrails/tree/master" title="Go to the Github branch"&gt;docrails branch on Github&lt;/a&gt; and it has already seen a huge number of changes committed.&lt;/p&gt;
&lt;p&gt;While I don’t particularly miss coding in &lt;a href="http://www.php.net/" title="Go to the PHP site"&gt;PHP&lt;/a&gt; it came as quite a shock when I made the move to Rails to find that there wasn’t anything that came close to its &lt;a href="http://www.php.net/manual/en/" title="Behold the PHP documentation"&gt;documentation&lt;/a&gt;. Not only is there a language reference, full documentation for the standard extensions (and with the crazy lack of naming conventions or namespaces in PHP this is &lt;em&gt;really&lt;/em&gt; useful!) there is also the invaluable comments section where other PHP developers can contribute extra documentation to each and every part of the language.&lt;/p&gt;
&lt;p&gt;This is what Rails has needed for a long time. The great news is that thanks to the hard work of the guys at &lt;a href="http://blog.nodeta.fi/" title="Visit the Nodeta blog"&gt;Nodeta&lt;/a&gt; it has finally arrived: behold &lt;a href="http://rails-doc.org/" title="Take a look at Rails-doc"&gt;Rails-doc&lt;/a&gt;! The site reached version 2.0 last week and now it has pretty much everything you could ask for:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Full documentation of the Rails API &lt;strong&gt;including&lt;/strong&gt; different versions of the API.&lt;/li&gt;
  &lt;li&gt;User comments.&lt;/li&gt;
  &lt;li&gt;Easy to use search, as well as a Firefox search bar extension.&lt;/li&gt;
  &lt;li&gt;A simple, clear user interface that is far better to navigate than the official API documentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, perhaps more than ever before, we as a community can get involved to improve Rails documentation: we can of course continue with our blogs, but we can also submit patches to docrails and post comments to Rails-doc. These things combined should ensure that we don’t reach the point where, to quote Jeremy, &amp;lt;q cite="http://www.omgbloglol.com/?p=34"&gt;Rails becomes an esoteric project doomed to eventual abandonment because everyone has to shell out $40 for a book to learn how to use it.&amp;lt;/q&gt;&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395060" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/7/20/finally-decent-documentation-for-rails-developers</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-07-14:1142</id>
    <published>2008-07-14T11:52:00Z</published>
    <updated>2008-07-14T11:57:29Z</updated>
    <category term="Blog" />
    <category term="aes" />
    <category term="cookies" />
    <category term="encryption" />
    <category term="ezcrypto" />
    <category term="hmac" />
    <category term="openssl" />
    <category term="optimisation" />
    <category term="performance" />
    <category term="rails" />
    <category term="rails patch" />
    <category term="rails plugin" />
    <category term="ruby" />
    <category term="security" />
    <category term="tamper" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395061/a-tamper-proof-cookie-jar-for-rails-development" rel="alternate" type="text/html" />
    <title>A tamper-proof cookie jar for Rails</title>
<summary type="html">&lt;p&gt;When the default session store for Rails was changed to use cookies last year it caused quite a furore: "It’s not secret! It’s not safe!" The truth is it was never meant to be: in most circumstances you shouldn’t really be storing data in cookies that need to be protected so strongly. But I don’t really want to re-open that can of worms! Instead I want to look at a different cookie-related situation that arose during some optimisation work I’ve been doing on an existing Rails application.&lt;/p&gt;
&lt;p&gt;&lt;img title="Stop cookie monsters from tampering with your cookies!" src="/assets/2008/7/14/no-cookie-monster.png" alt="No cookie monsters" /&gt;The scenario is straightforward enough: the application stores a numeric record ID in a persistent cookie that, while perfectly safe to be seen by users, shouldn’t be changed by them. The solution currently used in the application is equally straightforward: the data is encrypted (using the &lt;a href="http://ezcrypto.rubyforge.org/" title="Read the documentation"&gt;EzCryto gem&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard" title="Find out about AES encryption"&gt;AES encryption&lt;/a&gt;) before being written to the cookie, and then decrypted when the data is read back in.&lt;/p&gt;
&lt;p&gt;In situations where cookie contents really shouldn’t be seen by users then encryption is the way to go (unless of course you can find a way of not using a cookie at all), however for a simple numeric ID where tampering is the only thing we need to protect against then it seems like overkill. A better solution is to take inspiration from the Rails cookie session store and use a &lt;a href="http://en.wikipedia.org/wiki/HMAC" title="Find out about HMACs"&gt;HMAC&lt;/a&gt;.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;When the default session store for Rails was changed to use cookies last year it caused quite a furore: "It’s not secret! It’s not safe!" The truth is it was never meant to be: in most circumstances you shouldn’t really be storing data in cookies that need to be protected so strongly. But I don’t really want to re-open that can of worms! Instead I want to look at a different cookie-related situation that arose during some optimisation work I’ve been doing on an existing Rails application.&lt;/p&gt;
&lt;p&gt;&lt;img title="Stop cookie monsters from tampering with your cookies!" src="/assets/2008/7/14/no-cookie-monster.png" alt="No cookie monsters" /&gt;The scenario is straightforward enough: the application stores a numeric record ID in a persistent cookie that, while perfectly safe to be seen by users, shouldn’t be changed by them. The solution currently used in the application is equally straightforward: the data is encrypted (using the &lt;a href="http://ezcrypto.rubyforge.org/" title="Read the documentation"&gt;EzCryto gem&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard" title="Find out about AES encryption"&gt;AES encryption&lt;/a&gt;) before being written to the cookie, and then decrypted when the data is read back in.&lt;/p&gt;
&lt;p&gt;In situations where cookie contents really shouldn’t be seen by users then encryption is the way to go (unless of course you can find a way of not using a cookie at all), however for a simple numeric ID where tampering is the only thing we need to protect against then it seems like overkill. A better solution is to take inspiration from the Rails cookie session store and use a &lt;a href="http://en.wikipedia.org/wiki/HMAC" title="Find out about HMACs"&gt;HMAC&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Enter the TamperProofCookieJar&lt;/h3&gt;
&lt;p&gt;Here’s the code (if it seems familiar it’s because it borrows heavily from the Rails cookie session store):&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;require 'openssl'

module ActionController
  class TamperProofCookieJar &amp;lt; ActionController::CookieJar

    class TamperedWithCookie &amp;lt; StandardError;
      attr_reader :cookie_name
      def initialize(cookie_name)
        @cookie_name = cookie_name.to_s
      end
    end

    def initialize(controller, secret, digest = 'SHA1')
      super(controller)
      @secret = secret
      @digest = OpenSSL::Digest::Digest.new(digest)
    end

    def [](name, protect_from_forgery = false)
      if (value = super(name)) &amp;amp;&amp;amp; protect_from_forgery
        value, hmac = value.to_s.split('--')
        unless hmac == generate_digest(value) || hmac == generate_digest(value = CGI.unescape(value))
          raise TamperedWithCookie.new(name)
        end
      end

      value
    end

    def []=(name, options)
      if options.is_a?(Hash)
        options = options.stringify_keys
        options['name'] = name.to_s
        options['value'] = options['protect_from_forgery'] == true ? "#{options['value']}--#{generate_digest(options['value'])}" : options['value'].to_s
      else
        options = { "name" =&gt; name.to_s, "value" =&gt; options.to_s }
      end
      set_cookie(options)
    end

    protected

      def generate_digest(value)
        OpenSSL::HMAC.hexdigest(@digest, @secret, value.to_s)
      end

  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code makes use of the Ruby &lt;a href="http://ruby-doc.org/stdlib/libdoc/openssl/rdoc/index.html" title="Read the (limited) documentation"&gt;OpenSSL library&lt;/a&gt; to generate a HMAC using the &lt;a href="http://en.wikipedia.org/wiki/SHA-1" title="Find out more about SHA-1"&gt;SHA-1 hashing algorithm&lt;/a&gt;. A few notes about the code:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The &lt;code&gt;TamperedWithCookie&lt;/code&gt; exception will be raised on reading a cookie value if it is deemed to have been tampered with. The exception provides a &lt;code&gt;cookie_name&lt;/code&gt; attribute that can be used to get the name of the offending cookie.&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;TamperProofCookieJar&lt;/code&gt; class is a subclass of the regular Rails &lt;code&gt;CookieJar&lt;/code&gt; and as such is a drop-in replacement for it with one exception: the cookie value is converted to a string before being written to the cookie - this means if you’re not storing a simple string or number then you’ll need to ensure you have marshalled the data correctly before trying to write it to the cookie (again in most situations you shouldn’t be storing any complex objects in a cookie anyway).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using the &lt;code&gt;TamperProofCookieJar&lt;/code&gt; is easy:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# Write a regular cookie (by default HMAC protection is NOT used - so this is just like a regular Rails cookie)
cookies[:test_unprotected] = { :value =&gt; user.id, :expires =&gt; Time.zone.now + 30.days }

# Write a HMAC protected cookie
# user.id = 100
cookies[:test_protected] = { :value =&gt; user.id, :protect_from_forgery =&gt; true, :expires =&gt; Time.zone.now + 30.days }

# Read a regular cookie (again no protection is the default)
user_id = cookies[:test_unprotected]
=&gt; "100"

# Read a HMAC protected cookie (the boolean parameter turns on HMAC protection)
# Raises TamperProofCookieJar::TamperedWithCookie if the cookie appears to have been changed
user_id = cookies[:test_protected, true]
=&gt; "100"

# Read a raw HMAC protected cookie
# This returns the actual contents of the cookie, including the HMAC, and does not perform tamper checking
user_id = cookies[:test_protected]
=&gt; "100--2157acbbe09b9f412cee3b97ad2e2c2136d3f5e1"&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Replacing the Rails CookieJar&lt;/h3&gt;
&lt;p&gt;If you want to replace the Rails &lt;code&gt;CookieJar&lt;/code&gt; with the &lt;code&gt;TamperProofCookieJar&lt;/code&gt; in your application you can override the &lt;code&gt;cookies&lt;/code&gt; method in your &lt;code&gt;ApplicationController&lt;/code&gt; like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;class ApplicationController &amp;lt; ActionController::Base
  def cookies
    ActionController::TamperProofCookieJar.new(self, 'this should be a long secret key')
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second parameter should be a secret key that is hard to guess, just like the one used by the Rails cookie session store.&lt;/p&gt;
&lt;h3&gt;Performance improvements&lt;/h3&gt;
&lt;p&gt;As I said earlier, the &lt;code&gt;TamperProofCookieJar&lt;/code&gt; was created as part of an optimisation project, so how does its performance compare with the original encryption solution? Using a simple benchmark on 20,000 encryptions versus 20,000 HMACs gives the following results:&lt;/p&gt;
&amp;lt;dl&gt;
  &lt;dt&gt;Encryption total time&lt;/dt&gt;
  &lt;dd&gt;2.918 seconds&lt;/dd&gt;
  &lt;dt&gt;HMAC total time&lt;/dt&gt;
  &lt;dd&gt;0.854 seconds&lt;/dd&gt;
&amp;lt;/dl&gt;
&lt;p&gt;This gives a 3.4x performance increase which on a high volume site such as the one I’m working on is a worthy saving!&lt;/p&gt;
&lt;h3&gt;To patch or plugin?&lt;/h3&gt;
&lt;p&gt;My original intention was to submit this as a patch to Rails however I don’t think it will be seen as “useful” enough for the wider Rails community to be included in core. Instead I’m leaning towards making it a plugin: so please let me know if you have any problems with the code or have any suggestions for how it can be improved and when time allows I’ll put it all together.&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395061" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/7/14/a-tamper-proof-cookie-jar-for-rails-development</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-06-30:1096</id>
    <published>2008-06-30T14:48:00Z</published>
    <updated>2008-07-14T11:54:52Z</updated>
    <category term="Blog" />
    <category term="holiday" />
    <category term="italy" />
    <category term="wedding" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395062/the-wedding-of-the-year" rel="alternate" type="text/html" />
    <title>The Wedding of the Year</title>
<content type="html">
            &lt;p&gt;In the week when TheWebFellas became famous for five minutes thanks to &lt;a href="http://railscasts.com/episodes/115" title="Railscast #115"&gt;Ryan Bates&lt;/a&gt;, &lt;a href="http://weblog.rubyonrails.com/2008/6/16/this-week-in-rails-june-16-2008" title="Rails blog"&gt;Antonio Cangiano&lt;/a&gt; and Gregg &amp;amp; Jason at &lt;a href="http://www.railsenvy.com/2008/6/20/rails-envy-podcast-episode-034" title="Rails Envy Podcast #34"&gt;Rails Envy&lt;/a&gt;, I was away enjoying a relaxing holiday in the beautiful &lt;a href="http://en.wikipedia.org/wiki/Garfagnana" title="Find out more about Garfagnana"&gt;Garfagnana&lt;/a&gt; region of Italy. But taking a break from the fast-paced world of Rails development wasn’t the only motivation for the trip: my brother and partner in crime at TheWebFellas was getting married to his girlfriend of many years Samantha.&lt;/p&gt;
&lt;p&gt;Resisting offers from &lt;a href="http://www.hellomagazine.com/" title="Hello magazine"&gt;Hello magazine&lt;/a&gt; (although the wedding did feature in the equally popular &lt;a href="http://www.barganews.com/2008/06/christopher-and-samantha/" title="Barga News story"&gt;Barga News&lt;/a&gt;) the highly exclusive ceremony was held in the Barga Commune with only 22 members of immediate family and close friends in attendance. The evening was spent in the grounds of the 18th Century “I Cedri” villa in nearby Albiano where we enjoyed a huge Tuscan feast that went on well into the night. I’ve put a few of my photos up on &lt;a href="http://www.flickr.com/photos/thewebfellas/sets/72157605902074859/" title="Photos on Flickr"&gt;Flickr&lt;/a&gt;: incredibly the &lt;a href="http://www.fotograficasposi.it/" title="Arteimmagine Foto&amp;amp;amp;Grafica"&gt;official photographer&lt;/a&gt; managed to take about 600 photos!&lt;/p&gt;
&lt;p&gt;For the remainder of the week I was able to relax by the pool, drive on some of the greatest roads in Europe in my trusty Micra convertible and enjoy some excellent food in various restaurants and pasticcerias: if you ever find yourself in Barga you must visit Bar Lucchesi in the new part of town for some genuine Italian atmosphere, pastries and the best cappuccino ever.&lt;/p&gt;
&lt;p&gt;Sadly while Chris and Sam are still enjoying a leisurely trip back through Europe  I’m now back in the UK, working hard and missing my swimming pool with a view!&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395062" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/6/30/the-wedding-of-the-year</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Chris Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-06-12:986</id>
    <published>2008-06-12T08:00:00Z</published>
    <updated>2008-06-12T07:59:47Z</updated>
    <category term="Blog" />
    <category term="amazon" />
    <category term="aws" />
    <category term="cloud" />
    <category term="consultancy" />
    <category term="drdb" />
    <category term="ec2" />
    <category term="fuse" />
    <category term="infiniteftp" />
    <category term="linux" />
    <category term="persistence" />
    <category term="persistent storage" />
    <category term="persistentfs" />
    <category term="rails development" />
    <category term="s3fs. elasticdrive" />
    <category term="storage" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395063/ec2-persistent-storage-for-the-impatient" rel="alternate" type="text/html" />
    <title>EC2 Persistent Storage for the Impatient?</title>
<summary type="html">&lt;p&gt;As I &lt;a href="blog/2008/4/14/persistent-storage-for-amazon-ec2-is-on-it-s-way" title="Persistent storage for Amazon EC2 is on it's way"&gt;previously posted&lt;/a&gt; Amazon have announced that persistent storage is on it's way for EC2. Sadly the public launch date has not yet been disclosed - it's "coming later in the year". In the meantime this leaves the question of what to do when you need data to persist?&lt;/p&gt;
&lt;p&gt;There are a number of options, especially when you start to consider scalability and fault tolerance. I won't dare claim I've considered all the options out there - I've simply started to look at what the immediate options are for persistent storage.&lt;/p&gt;
&lt;p&gt;Without further ado, then, on to the technology. I've found a number of choices - rather than this being a 'how to' then it is more about the solutions I have found so far and that are on my list for consideration. Hopefully, if one of the options fits my needs then I will provide a guide at a later date!&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;As I &lt;a href="blog/2008/4/14/persistent-storage-for-amazon-ec2-is-on-it-s-way" title="Persistent storage for Amazon EC2 is on it's way"&gt;previously posted&lt;/a&gt; Amazon have announced that persistent storage is on it's way for EC2. Sadly the public launch date has not yet been disclosed - it's "coming later in the year". In the meantime this leaves the question of what to do when you need data to persist?&lt;/p&gt;
&lt;p&gt;There are a number of options, especially when you start to consider scalability and fault tolerance. I won't dare claim I've considered all the options out there - I've simply started to look at what the immediate options are for persistent storage.&lt;/p&gt;
&lt;p&gt;Without further ado, then, on to the technology. I've found a number of choices - rather than this being a 'how to' then it is more about the solutions I have found so far and that are on my list for consideration. Hopefully, if one of the options fits my needs then I will provide a guide at a later date!&lt;/p&gt;
&lt;p&gt;At a high level the solutions can be split into two categories - file system interfaces to S3 or architecture based replication and backup. There are likely to be other options that allow you to use persistent storage outside the Amazon cloud - for the time being I'm trying to stay within the bubble. There is also a cross-over between the two strategies - i.e. using a particular architecture with a file system interface.&lt;/p&gt;

&lt;h3&gt;File System Interfaces to Amazon S3&lt;/h3&gt;
&lt;p&gt;The file system interfaces to S3 are typically based on either the &lt;a href="http://fuse.sourceforge.net/" title="FUSE"&gt;FUSE&lt;/a&gt; library or implemented as an &lt;a href="http://nbd.sourceforge.net/" title="NBD"&gt;NBD&lt;/a&gt;. FUSE allows developers to create interfaces (in user space) that ultimately surface to the user as a standard file system, while NBD allows interfaces that appear as a raw, unformatted physical disk (allowing the user to format the disk as they please).&lt;/p&gt;
&lt;h4&gt;FUSE Interfaces&lt;/h4&gt;
&amp;lt;dl&gt;
&lt;dt&gt;&lt;a href="http://code.google.com/p/s3fs/wiki/FuseOverAmazon" title="s3fs"&gt;s3fs&lt;/a&gt; (Open Source)&lt;/dt&gt;&lt;dd&gt;&lt;blockquote&gt;s3fs is a FUSE filesystem that allows you to mount an Amazon S3 bucket as a local filesystem. It stores files natively and transparently in S3 (i.e., you can use other programs to access the same files). Maximum file size is 5G.&lt;/blockquote&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;a href="http://www.persistentfs.com/" title="PersistentFS"&gt;PersistentFS&lt;/a&gt; (Closed Source, Current Development Version is Free)&lt;/dt&gt;&lt;dd&gt;&lt;blockquote&gt;PersistentFS is a fast and efficient POSIX-compliant file system that provides unlimited online storage in the Amazon Web Services (AWS) storage cloud.&lt;/blockquote&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;a href="http://www.infinitebits.info/" title="InfiniteFTP"&gt;InfiniteFTP&lt;/a&gt; (Closed Source, Paid Service)  over &lt;a href="http://curlftpfs.sourceforge.net/" title="CurlFtpFs"&gt;CurlFtpFs&lt;/a&gt; (Open Source)&lt;/dt&gt;&lt;dd&gt;InfiniteFTP provides an FTP interface to Amazon S3 - while this isn't a file system approach then you could add a FUSE layer over the top to make it appear as one.&lt;blockquote&gt;CurlFtpFS is a filesystem for accessing FTP hosts based on FUSE and libcurl. &lt;/blockquote&gt;&lt;/dd&gt;
&amp;lt;/dl&gt;
&lt;h4&gt;NBD Interfaces&lt;/h4&gt;
&amp;lt;dl&gt;
&lt;dt&gt;&lt;a href="http://www.elasticdrive.com/" title="ElasticDrive"&gt;ElasticDrive&lt;/a&gt; (Closed Source, Paid Service)&lt;/dt&gt;&lt;dd&gt;&lt;blockquote&gt;ElasticDrive is a Distributed Remote Storage Application that allows you to access your data regardless of location with the assurance your data is safe. It makes it possible for a remote storage resource, such as Amazon's Simple Storage Service (S3), Nirvanix &amp;amp; Xdrive to behave like a local hard drive.&lt;/blockquote&gt;&lt;/dd&gt;
&amp;lt;/dl&gt;

&lt;h3&gt;Architecture Considerations&lt;/h3&gt;
&lt;p&gt;There are a number of options for architecture based persistence that immediately spring to mind - i.e. various replication strategies such as &lt;a href="http://www.drbd.org/" title="drdb"&gt;DRDB&lt;/a&gt; or distributed filesystems perhaps backed by backups to an external service - the lag of such an approach would need to be considered. There are also options such as mirrored RAID (potentially for read speed and consistency) although RAID isn't an option on FUSE based devices. &lt;/p&gt;

&lt;h3&gt;Cost Considerations&lt;/h3&gt;
&lt;p&gt;I've only considered the options I could find for storage backed by S3 - my main in head reason for this was to avoid transfer charges. There will still be charges for the GET, PUT and LIST requests so I also need to consider the cost implications of using S3 to assist with persistent storage.&lt;/p&gt;

&lt;h3&gt;What Next?&lt;/h3&gt;
&lt;p&gt;The next step is to take a deeper look at the options on offer and try to discover if there is a workable solution for persistent storage already available. I also want to run benchmarks against some sample configurations to see if the options perform under real world requirements. Finally, I will run some numbers to check if the costs stack up. By the time I've finished, the official Amazon offering may well be available - if not I shall document my findings!&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395063" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/6/12/ec2-persistent-storage-for-the-impatient</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-06-09:989</id>
    <published>2008-06-09T17:00:00Z</published>
    <updated>2008-11-27T12:27:57Z</updated>
    <category term="Blog" />
    <category term="activesupport" />
    <category term="cache" />
    <category term="memcached" />
    <category term="performance" />
    <category term="rails" />
    <category term="rails development" />
    <category term="ruby" />
    <category term="win32" />
    <category term="windows" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395064/rails-2-1-now-with-better-integrated-caching" rel="alternate" type="text/html" />
    <title>Rails 2.1: now with better integrated caching</title>
<summary type="html">&lt;p&gt;Rails 2.1 has just been out a week and so far something that seems to have passed most people by is that it now includes much better caching capabilities, including built-in support for &lt;a href="http://www.danga.com/memcached/" title="Find out more about memcached"&gt;memcached&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last week I reached the point with an application where I needed to cache some models in memory to get a performance boost and decided to check out the current status of plugins like &lt;a href="http://github.com/defunkt/cache_fu/" title="See cache_fu on GitHub"&gt;cache_fu&lt;/a&gt; and &lt;a href="http://seattlerb.rubyforge.org/" title="See cached_model on Seattle.rb"&gt;CachedModel&lt;/a&gt; to make sure they’d work with Rails 2.1. It was completely by accident that I stumbled across &lt;a href="http://github.com/rails/rails/commit/2a9ad9ccbc706e546bf02ec95f864944e7d7983b" title="See the commit message on Github"&gt;this innocent looking commit&lt;/a&gt; by DHH from start of this year and realised that Rails already had everything I needed!&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Rails 2.1 has just been out a week and so far something that seems to have passed most people by is that it now includes much better caching capabilities, including built-in support for &lt;a href="http://www.danga.com/memcached/" title="Find out more about memcached"&gt;memcached&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last week I reached the point with an application where I needed to cache some models in memory to get a performance boost and decided to check out the current status of plugins like &lt;a href="http://github.com/defunkt/cache_fu/" title="See cache_fu on GitHub"&gt;cache_fu&lt;/a&gt; and &lt;a href="http://seattlerb.rubyforge.org/" title="See cached_model on Seattle.rb"&gt;CachedModel&lt;/a&gt; to make sure they’d work with Rails 2.1. It was completely by accident that I stumbled across &lt;a href="http://github.com/rails/rails/commit/2a9ad9ccbc706e546bf02ec95f864944e7d7983b" title="See the commit message on Github"&gt;this innocent looking commit&lt;/a&gt; by DHH from start of this year and realised that Rails already had everything I needed!&lt;/p&gt;
&lt;h3&gt;Making sense of my notes&lt;/h3&gt;
&lt;p&gt;Unfortunately the documentation for this new caching support seems quite scarce and unusually Google couldn’t help much either as there hasn’t been much blogging about it yet. So, not for the first time, I spent a bit of time digging into the source code to find out how it all fits together. What follows is a write-up of my hastily scribbled notes.&lt;/p&gt;
&lt;h4&gt;The basics&lt;/h4&gt;
&lt;p&gt;The code lives in the &lt;code&gt;ActiveSupport::Cache&lt;/code&gt; module and it defines a base &lt;code&gt;Store&lt;/code&gt; class which provides the basic interface for a caching store with methods like: &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt; and &lt;code&gt;exist?&lt;/code&gt; (why oh why isn’t it &lt;code&gt;exists?&lt;/code&gt; like ActiveRecord?). There is also a &lt;code&gt;ThreadSafety&lt;/code&gt; module that wraps read/write operations in a &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/thread/rdoc/classes/Mutex.html#M004869" title="See method documentation"&gt;&lt;code&gt;Mutex#synchronize&lt;/code&gt;&lt;/a&gt; block. Enabling thread safety on a cache store is a simple matter of calling the &lt;code&gt;threadsafe!&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Rails includes five cache stores:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;File store (&lt;code&gt;ActiveSupport::Cache::FileStore&lt;/code&gt;) - uses individual files to store cached values.&lt;/li&gt;
  &lt;li&gt;Memory store (&lt;code&gt;ActiveSupport::Cache::MemoryStore&lt;/code&gt;) - uses a simple hash to store values.&lt;/li&gt;
  &lt;li&gt;DRb store (&lt;code&gt;ActiveSupport::Cache::DRbStore&lt;/code&gt;) - works just like the &lt;code&gt;MemoryStore&lt;/code&gt; but uses a DRb server to store values.&lt;/li&gt;
  &lt;li&gt;Memcached store (&lt;code&gt;ActiveSupport::Cache::MemCacheStore&lt;/code&gt;) - uses memcache and &lt;a href="http://rubyforge.org/frs/shownotes.php?release_id=13743" title="Find out more about the memcache-client for Ruby"&gt;memcache-client&lt;/a&gt; (version 1.5.0 is bundled with Rails so there’s no need to install the Gem separately) to store values in a shared memory cache.&lt;/li&gt;
  &lt;li&gt;Compressed memcached store (&lt;code&gt;ActiveSupport::Cache::CompressedMemCacheStore&lt;/code&gt;) - works just like the regular &lt;code&gt;MemCacheStore&lt;/code&gt; but uses GZip to decompress/compress on read/write.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rails automatically creates a global cache during initialisation and you can access this in your code either using the &lt;code&gt;RAILS_CACHE&lt;/code&gt; global variable or the (in my opinion nicer looking) &lt;code&gt;Rails.cache&lt;/code&gt;. Here are a few simple examples:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# Write a string to the cache
Rails.cache.write('test_key', 'test_value')
=&gt; true

# Read it back in
Rails.cache.read('test_key')
=&gt; 'test_value'

# Delete the item
Rails.cache.delete('test_key')
=&gt; true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default if the &lt;kbd&gt;tmp/cache&lt;/kbd&gt; directory exists in your application root then Rails will use a &lt;code&gt;FileStore&lt;/code&gt; otherwise it’ll use a &lt;code&gt;MemoryStore&lt;/code&gt; as the global cache. Either of these options should be fine for development and testing, but for production you’ll almost certainly want to consider using the &lt;code&gt;MemCacheStore&lt;/code&gt;. One of the big advantages of this new code is that for the most part it allows you to switch cache store without having to change any of your code.&lt;/p&gt;
&lt;p&gt;&lt;ins&gt;&lt;strong&gt;Important!&lt;/strong&gt; As Peter points out in the comments, this behaviour is not currently implemented (the code is there but not used) - I’ve submitted a &lt;a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/514-rails-configuration-default_cache_store-not-called" title="Rails configuration bug report"&gt;bug report&lt;/a&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;h4&gt;Changing the global cache store&lt;/h4&gt;
&lt;p&gt;Rails provides the &lt;code&gt;config.cache_store&lt;/code&gt; option in &lt;kbd&gt;environment.rb&lt;/kbd&gt; to allow you to change the cache store. It accepts either a class name or symbol for the required store and an array of options used when initialising the store. Some examples:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# Use the memory store - this store has no options
config.cache_store = :memory_store

# Use the file store with a custom storage path (if the directory doesn’t already exist it will be created)
config.cache_store = :file_store, '/my_cache_path'

# Use the memcached store with default options (localhost, TCP port 11211)
config.cache_store = :mem_cache_store

# Use the memcached store with an options hash
config.cache_store = :mem_cache_store, 'localhost', '192.168.1.1:1001', { :namespace =&gt; 'test' }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Behind the scenes this makes use of the &lt;code&gt;ActiveSupport::Cache.lookup_store&lt;/code&gt; method, which you can also call directly to create a cache of your own:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# Create a separate memory cache in addition to the global Rails cache
my_cache = ActiveSupport::Cache.lookup_store(:memory_cache)&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Data keys&lt;/h4&gt;
&lt;p&gt;All of these cache stores provide what is essentially a &lt;code&gt;Hash&lt;/code&gt; that can be read from and written to using a key. Just like with a regular &lt;code&gt;Hash&lt;/code&gt; object, this key needs to be unique and not just within the scope of your application but also, in the case of shared caches like memcached, across all applications that are using the cache. To make cache key generation a little easier Rails does two things:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Adds a cache_key method to &lt;code&gt;ActiveRecord::Base&lt;/code&gt; that generates a key using the class name, record ID and &lt;code&gt;updated_at&lt;/code&gt; timestamp (if available).&lt;/li&gt;
  &lt;li&gt;Provides the &lt;code&gt;ActiveSupport::Cache.expand_cache_key&lt;/code&gt; method that builds a key using an optional namespace passed as a parameter to the method, the &lt;code&gt;RAILS_CACHE_ID&lt;/code&gt; or &lt;code&gt;RAILS_APP_VERSION&lt;/code&gt; environment variables (if they are set) and the result of a call to the &lt;code&gt;cache_key&lt;/code&gt; or &lt;code&gt;to_param&lt;/code&gt; method of the object being cached (if it responds to either of them) or in the case of an &lt;code&gt;Array&lt;/code&gt; the &lt;code&gt;expand_cache_key&lt;/code&gt; method is called for each element of the array and the resulting keys joined to form a single (potentially very long!) key.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;MemCacheStore specifics&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;MemCacheStore&lt;/code&gt; accepts an array of server addresses in the form &lt;code&gt;hostname[:port][:weight]&lt;/code&gt;. For example, if you have two servers on different ports you could specify them like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;config.cache_store = :mem_cache_store, '192.168.1.1:11000', '192.168.1.2:11001'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It also accepts a hash of additional options:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;:namespace&lt;/code&gt; - specifies a string that will automatically be prepended to keys when accessing the memcached store.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;:readonly&lt;/code&gt; - a boolean value that when set to true will make the store read-only, with an error raised on any attempt to write.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;:multithread&lt;/code&gt; - a boolean value that adds thread safety to read/write operations - it is unlikely you’ll need to use this option as the Rails &lt;code&gt;threadsafe!&lt;/code&gt; method offers the same functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;read&lt;/code&gt; and &lt;code&gt;write&lt;/code&gt; methods of the &lt;code&gt;MemCacheStore&lt;/code&gt; accept an options hash too. When reading you can specify &lt;code&gt;:raw =&gt; true&lt;/code&gt; to prevent the object being marshaled (by default this is false which means the raw value in the cache is passed to &lt;code&gt;Marshal.load&lt;/code&gt; before being returned to you.&lt;/p&gt;
&lt;p&gt;When writing to the cache it is also possible to use the &lt;code&gt;:raw&lt;/code&gt; option which when false (the default) means the value is passed to &lt;code&gt;Marshal.dump&lt;/code&gt; before being stored in the cache. The &lt;code&gt;write&lt;/code&gt; method also accepts an &lt;code&gt;:unless_exist&lt;/code&gt; flag which determines whether the memcached &lt;code&gt;add&lt;/code&gt; (when true) or &lt;code&gt;set&lt;/code&gt; (when false) method is used to store the item in the cache and an &lt;code&gt;:expires_in&lt;/code&gt; option that specifies the time-to-live for the cached item in seconds. A few examples:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# Write a raw value to the cache
Rails.cache.write('test_key', 1, :raw =&gt; true)

# Read a raw value from the cache
Rails.cache.read('test_key', :raw =&gt; true)

# Write a value using the add method and setting expiry to 15 minutes
Rails.cache.write('test_key', 'test_value', :unless_exist =&gt; true, :expires_in =&gt; 15.minutes)&lt;/code&gt;&lt;/pre&gt;


&lt;h4&gt;Increment and decrement&lt;/h4&gt;
&lt;p&gt;As caches are often used to store counters all of the cache stores provide &lt;code&gt;increment&lt;/code&gt; and &lt;code&gt;decrement&lt;/code&gt; methods. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;# Store an initial counter value in the cache
Rails.cache.write('number_of_cakes_eaten', 1)

# Increment the counter by 5
Rails.cache.increment('number_of_cakes_eaten', 5)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This encapsulates the process of retrieving a value, incrementing or decrementing it and then storing the modified value back in the cache. In addition, the &lt;code&gt;MemCacheStore&lt;/code&gt; takes advantage of memcached atomic increment/decrement functionality to perform this action in a single call to the cache.&lt;/p&gt;
&lt;h3&gt;Custom caches&lt;/h3&gt;
&lt;p&gt;You now know enough about Rails caching to make good use of it in your own code. If you want to take things a step further and implement your own custom cache store you might want to take a look at &lt;a href="http://ryandaigle.com/articles/2007/12/19/what-s-new-in-edge-rails-pluggable-controller-caching" title="Read Ryan’s blog entry"&gt;Ryan Daigle’s example&lt;/a&gt; - his blog entry also demonstrates how to configure ActionController caching in Rails 2.1.&lt;/p&gt;
&lt;h3&gt;And finally…running memcached on Windows (groan!)&lt;/h3&gt;
&lt;p&gt;As a long suffering Windows developer you may well have read all of this, gotten quite excited about using memcached, and then realised that you’ve got to get it running on Windows. It’s normally at this point that I end up getting annoyed and resolve to buy a Mac, but I’m pleased to say on this occasion I was pleasantly surprised. I simply did the following:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Downloaded &lt;a href="http://www.splinedancer.com/memcached-win32/" title="Get a Windows port of memcached"&gt;this Win32 port of memcached&lt;/a&gt; by Kenneth Dalgleish.&lt;/li&gt;
  &lt;li&gt;Extracted the files to &lt;kbd&gt;C:\Program Files\memcached&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Opened a command prompt in the folder and installed memcached as a service using &lt;kbd&gt;memcached -d install&lt;/kbd&gt;&lt;/li&gt;
  &lt;li&gt;Started the service using &lt;kbd&gt;net start "memcached Server"&lt;/kbd&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And, shockingly, it just worked!&lt;/p&gt;
          &lt;img src="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~4/424395064" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://thewebfellas.com/blog/2008/6/9/rails-2-1-now-with-better-integrated-caching</feedburner:origLink></entry>
  <entry xml:base="http://thewebfellas.com/">
    <author>
      <name>Rob Anderton</name>
    </author>
    <id>tag:thewebfellas.com,2008-06-02:957</id>
    <published>2008-06-02T14:23:00Z</published>
    <updated>2008-06-10T11:12:58Z</updated>
    <category term="Blog" />
    <category term="database" />
    <category term="migration" />
    <category term="mysql" />
    <category term="patch" />
    <category term="rails" />
    <category term="rails development" />
    <category term="ruby" />
    <category term="schema" />
    <category term="unsigned" />
    <link href="http://feeds.thewebfellas.com/~r/thewebfellas/blog/~3/424395065/unsigned-integers-for-mysql-on-rails" rel="alternate" type="text/html" />
    <title>Unsigned integers for MySQL on Rails</title>
<summary type="html">&lt;p&gt;Ok, so I’m starting a new Rails application, I’ve spent some time refining my database, I’ve considered storage requirements and performance when choosing the data types for my fields and now I’m ready to create some migrations to implement my design.&lt;/p&gt;
&lt;p&gt;And then I’m reminded that, lovely though Rails migrations are, there are two things that really bug me about them: they create signed primary keys and they don’t allow me to easily create unsigned integer columns.&lt;/p&gt;
&lt;p&gt;It’s been discussed &lt;a href="http://dev.rubyonrails.org/ticket/5219" title="See Rails ticket 5219"&gt;before&lt;/a&gt;, dismissed as an ‘uncommon requirement’ (probably because MySQL is, as far as I know, the only database that uses unsigned integers) and, as far as I can tell, not a lot more has happened. So, while sat out in the garden, enjoying a sunny Saturday afternoon, I grabbed edge Rails from &lt;a href="http://github.com/rails/rails" title="Go to Rails on GitHub"&gt;GitHub&lt;/a&gt; and decided I’d see if I could do something about it (how’s that for geekyness?!)&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Ok, so I’m starting a new Rails application, I’ve spent some time refining my database, I’ve considered storage requirements and performance when choosing the data types for my fields and now I’m ready to create some migrations to implement my design.&lt;/p&gt;
&lt;p&gt;And then I’m reminded that, lovely though Rails migrations are, there are two things that really bug me about them: they create signed primary keys and they don’t allow me to easily create unsigned integer columns.&lt;/p&gt;
&lt;p&gt;It’s been discussed &lt;a href="http://dev.rubyonrails.org/ticket/5219" title="See Rails ticket 5219"&gt;before&lt;/a&gt;, dismissed as an ‘uncommon requirement’ (probably because MySQL is, as far as I know, the only database that uses unsigned integers) and, as far as I can tell, not a lot more has happened. So, while sat out in the garden, enjoying a sunny Saturday afternoon, I grabbed edge Rails from &lt;a href="http://github.com/rails/rails" title="Go to Rails on GitHub"&gt;GitHub&lt;/a&gt; and decided I’d see if I could do something about it (how’s that for geekyness?!)&lt;/p&gt;
&lt;h3&gt;Unsigned primary keys&lt;/h3&gt;
&lt;p&gt;Thanks to a &lt;a href="http://snippets.dzone.com/posts/show/4422" title="See the DZone snippet"&gt;snippet on DZone&lt;/a&gt; this was the easy bit:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;module ActiveRecord
  module ConnectionAdapters

    class MysqlAdapter
      def native_database_types_with_unsigned_primary_key
        returning native_database_types_without_unsigned_primary_key do |types|
          types[:primary_key] = 'int(11) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY'
        end
      end
      alias_method_chain :native_database_types, :unsigned_primary_key

  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see this extends the &lt;code&gt;native_database_types&lt;/code&gt; method of the &lt;code&gt;MysqlAdapter&lt;/code&gt; class which means that all other database adapters will be unaffected by this change.&lt;/p&gt;
&lt;h3&gt;Dealing with references&lt;/h3&gt;
&lt;p&gt;If you use the ‘sexy’ &lt;code&gt;references&lt;/code&gt; or &lt;code&gt;belongs_to&lt;/code&gt; syntax in your migration then changing the primary key to unsigned can cause problems. For example if you try and create a foreign key constraint you might see an error like this:&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;ERROR 1005 (HY000): Can't create table 'test_development.#sql-160_31' (errno: 150)&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;This unhelpful error message occurs because the primary key is unsigned but the foreign key field created by &lt;code&gt;references&lt;/code&gt; is signed. To fix this I subclassed the &lt;code&gt;Table&lt;/code&gt; and &lt;code&gt;TableDefinition&lt;/code&gt; classes to provide MySQL specific behaviour that defaults to creating unsigned foreign key columns. This also involved overriding the &lt;code&gt;create_table&lt;/code&gt; and &lt;code&gt;change_table&lt;/code&gt; methods of the &lt;code&gt;MysqlAdapter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course if you really want an signed reference you can simply pass &lt;code&gt;:unsigned =&gt; false&lt;/code&gt; in your call to &lt;code&gt;references&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;module ActiveRecord
  module ConnectionAdapters
    class MysqlTable &amp;lt; Table
      def references(*args)
        options = args.extract_options!
        polymorphic = options.delete(:polymorphic)
        args.each do |col|
          @base.add_column(@table_name, "#{col}_id", :integer, options.reverse_merge(:unsigned =&gt; true))
          @base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
        end
      end
      alias :belongs_to :references
    end

    class MysqlTableDefinition &amp;lt; TableDefinition
      def references(*args)
        options = args.extract_options!
        polymorphic = options.delete(:polymorphic)
        args.each do |col|
          column("#{col}_id", :integer, options.reverse_merge(:unsigned =&gt; true))
          column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
        end
      end
      alias :belongs_to :references
    end
    
    class MysqlAdapter
      def create_table(table_name, options = {}) #:nodoc:
        options = options.reverse_merge(:options =&gt; "ENGINE=InnoDB")
        table_definition = MysqlTableDefinition.new(self)
        table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false

        yield table_definition

        if options[:force] &amp;amp;&amp;amp; table_exists?(table_name)
          drop_table(table_name, options)
        end

        create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
        create_sql &amp;lt;&amp;lt; "#{quote_table_name(table_name)} ("
        create_sql &amp;lt;&amp;lt; table_definition.to_sql
        create_sql &amp;lt;&amp;lt; ") #{options[:options]}"
        execute create_sql
      end

      def change_table(table_name)
        yield MysqlTable.new(table_name, self)
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Adding an :unsigned =&gt; true option&lt;/h3&gt;
&lt;p&gt;This was the tricky bit, here’s the code:&lt;/p&gt;
&lt;pre&gt;&lt;code class="ruby"&gt;module ActiveRecord
  module ConnectionAdapters

    class MysqlAdapter
      def type_to_sql_with_unsigned(type, limit = nil, precision = nil, scale = nil, unsigned = false)
        returning type_to_sql_without_unsigned(type, limit, precision, scale) do |sql|
          sql &amp;lt;&amp;lt; ' UNSIGNED' if unsigned &amp;amp;&amp;amp; type.to_s == 'integer'
        end
      end
      alias_method_chain :type_to_sql, :unsigned

      def add_column(table_name, column_name, type, options = {})
        add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale], options[:unsigned])}"
        add_column_options!(add_column_sql, options)
        execute(add_column_sql)
      end

      def change_column(table_name, column_name, type, options = {})
        unless options_include_default?(options)
     