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

<channel>
	<title>matt.west.co.tt &#187; Demozoo</title>
	<atom:link href="http://matt.west.co.tt/category/demoscene/demozoo/feed/" rel="self" type="application/rss+xml" />
	<link>http://matt.west.co.tt</link>
	<description>adventures of a retro electro media hacker type person</description>
	<lastBuildDate>Mon, 25 Jul 2011 21:37:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Passing remote web data to attachment_fu</title>
		<link>http://matt.west.co.tt/ruby/passing-remote-web-data-to-attachment_fu/</link>
		<comments>http://matt.west.co.tt/ruby/passing-remote-web-data-to-attachment_fu/#comments</comments>
		<pubDate>Thu, 16 Aug 2007 23:15:03 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Demozoo]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://matt.west.co.tt/ruby/passing-remote-web-data-to-attachment_fu/</guid>
		<description><![CDATA[This week I have been mostly discovering what a wonderful Rails plugin attachment_fu is for handling image uploads. You just hand it the contents of an upload field on a form, and it takes care of everything else &#8211; checking that it&#8217;s a valid image, working out its file type, choosing a sensible filename for [...]]]></description>
			<content:encoded><![CDATA[<p>This week I have been mostly discovering what a wonderful Rails plugin <a href="http://clarkware.com/cgi/blosxom/2007/02/24">attachment_fu</a> is for handling image uploads. You just hand it the contents of an upload field on a form, and it takes care of everything else &#8211; checking that it&#8217;s a valid image, working out its file type, choosing a sensible filename for it, resizing it appropriately, and sticking the resulting image file into either the filesystem, the database, or <a href="http://www.amazon.com/gp/browse.html?node=16427261">Amazon S3</a>.</p>
<p>That last feature has been particularly handy on <a href="http://demozoo.org/">Demozoo</a>, which is currently hosted in borrowed space on a server that doesn&#8217;t really have 100-odd megabytes of free space for demo screenshots. However, attachment_fu comes a bit unstuck when you&#8217;re dealing with files that don&#8217;t come from a form upload &#8211; for instance, in my case I&#8217;m planning to have a scheduled task that leeches new productions and their screenshots from <a href="http://www.pouet.net/">Pou&euml;t</a>, and I&#8217;d quite like to take advantage of the Imagemagick-and-S3 goodness that attachment_fu brings. A bit of digging around was in order.<br />
<span id="more-78"></span><br />
As the <a href="http://wiki.rubyonrails.org/rails/pages/HowtoUploadFiles">HowtoUploadFiles</a> page on the Rails wiki helpfully explains, when you post a form containing a file upload field, it emerges on the Rails side as a sort-of IO object with a bunch of additional attributes: <i>original_filename</i>, <i>content_type</i> and <i>length</i> (in addition to the usual <i>read</i> method you expect from an IO object), and this is what the uploaded_data method (as implemented by attachment_fu) expects to be passed. According to Ruby&#8217;s principle of duck typing (i.e. it doesn&#8217;t have to actually <em>be</em> a duck, as long as it quacks like one and waddles like one), we therefore have to come up with our own sort-of IO object that behaves the same way, but with the data sourced from an HTTP fetch instead.</p>
<p>By a happy coincidence, the <a href="http://www.ruby-doc.org/stdlib/libdoc/open-uri/rdoc/">open-uri</a> module from Ruby&#8217;s standard library returns a sort-of IO object that&#8217;s mutated in almost (but not quite) just the right way. It gives us <i>content_type</i> and <i>length</i>, but we&#8217;re still missing <i>original_filename</i>. Following the guidance of <a href="http://manuals.rubyonrails.com/read/chapter/28#page237">a rails recipe</a>, I came up with the following code to tack that method on:</p>
<pre>
require 'open-uri'

class Screenshot &lt; ActiveRecord::Base
  has_attachment(
    :content_type =&gt; :image,
    :resize_to =&gt; '400x300&gt;',
    :storage =&gt; :s3
  )

  def source_uri=(uri)
    io = open(URI.parse(uri))
    (class &lt;&lt; io; self; end;).class_eval do
      define_method(:original_filename) { base_uri.path.split('/').last }
    end

    self.uploaded_data = io
  end

end
</pre>
<p>The source_uri method is the bit we&#8217;re interested in; after getting back our IO object from <i>open</i>, we do some class-level fiddling (which, um, I don&#8217;t completely understand myself &#8211; I think it&#8217;s creating a subclass descending from the IO object or something) to define the missing method <i>original_filename</i>. (If your URLs are coming from somewhere unpredictable, like a web form, you might want to do something more robust than base_uri.path.split(&#8216;/&#8217;).last &#8211; you might also want to deal with nil being passed as the URI.) We then pass our tweaked IO object off to the uploaded_data method, from where attachment_fu will start doing its stuff unaware that it isn&#8217;t really a form upload. Let&#8217;s see it in action then&#8230;</p>
<pre>
&gt;&gt; s = Screenshot.new(:source_uri => "http://www.pouet.net/screenshots/18890.jpg")
=&gt; #&lt;Screenshot id: nil, width: nil, height: nil, format: nil, size: nil,
content_type: "image/jpeg", filename: "18890.jpg"&gt;
&gt;&gt; s.save!
=&gt; true
&gt;&gt; s.public_filename
=&gt; "http://i-has-a-bucket.s3.amazonaws.com/1/18890.jpg"
</pre>
<p>There we go&#8230; one screenshot successfully uploaded to Amazon S3, without a form upload in sight! (And as a bonus, in theory open-uri ought to work just the same with FTP URLs as HTTP ones, if that floats your boat.)</p>
]]></content:encoded>
			<wfw:commentRss>http://matt.west.co.tt/ruby/passing-remote-web-data-to-attachment_fu/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Demozoo</title>
		<link>http://matt.west.co.tt/demoscene/demozoo/</link>
		<comments>http://matt.west.co.tt/demoscene/demozoo/#comments</comments>
		<pubDate>Sun, 05 Aug 2007 22:15:07 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Demoscene]]></category>
		<category><![CDATA[Demozoo]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://matt.west.co.tt/demoscene/demozoo/</guid>
		<description><![CDATA[I&#8217;m back from Assembly Summer 2007, where I launched my long-promised demoscene database site Demozoo to not very much fanfare at all. It&#8217;s been in development on and off for at least two years &#8211; I ambitiously chose it as my &#8216;hello world&#8217; project to learn Ruby On Rails with, subsequently aborted and restarted it [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m back from <a href="http://www.assembly.org/summer07">Assembly Summer 2007</a>, where I launched my long-promised demoscene database site <strong><a href="http://demozoo.org">Demozoo</a></strong> to not very much fanfare at all. It&#8217;s been in development on and off for at least two years &#8211; I ambitiously chose it as my &#8216;hello world&#8217; project to learn <a href="http://www.rubyonrails.org/">Ruby On Rails</a> with, subsequently aborted and restarted it about seven times over as I learned more and more Right Ways To Do Things, and eventually reached the stage of hacking on Rails internals to make it do what I wanted (most significantly the <a href="http://agilewebdevelopment.com/plugins/nested_has_many_through">Nested has_many_through</a> patch/plugin, which lets you achieve simple and yet bizarrely normally-impossible relationships like &#8216;all productions made by members of this group&#8217;).</p>
<p>The initial reception of the site has been mixed; there have been excited noises from people who have immediately seen its potential, and it&#8217;s already been useful for filling in those &#8216;dammit, what group is he in again&#8217; memory lapses at the pub (as well as a cunning way to startle Smash on AssemblyTV, by introducing him as &#8220;Smash of <a href="http://demozoo.org/groups/1572">jecoute</a>&#8221; rather than his rather more well-known role in <a href="http://demozoo.org/groups/1284">Fairlight</a>). It&#8217;s also attracted some (not entirely unfair) comments that it&#8217;s basically a very unfinished clone of <a href="http://www.pouet.net">Pou&euml;t</a>, to which I have three replies:</p>
<ul>
<li>Yes. Deadlines, party coding etc, mumble mumble, not enough time to add much data at all besides Pou&euml;t / add whizzy features other than the minimum necessary to make it work. <i>*shuffles feet*</i></li>
<li>Yes. But the massively important and really subtle difference is that <em>it can handle individual people&#8217;s nicknames properly</em>, even where they&#8217;re duplicated all over the place. (And that&#8217;s what&#8217;s taken two years to get right, pretty much.) For example, there are at least three people on the scene who go by the name of Simon and at least two groups called CPU, but if you enter a production by &#8220;Simon / CPU&#8221; then it knows exactly who you mean. And once you&#8217;ve got individual authors in the database, you can start indexing graphics and music. And if you don&#8217;t have to pick authors from a dropdown every single time, it becomes viable to enter a whole heap of complete party results in one sitting. Which will happen, soon.</li>
<li>Yes. How about I stop trying to justify its existence right now, and work on it some more until it speaks for itself?</li>
</ul>
<p>I like answer number 3 best.</p>
]]></content:encoded>
			<wfw:commentRss>http://matt.west.co.tt/demoscene/demozoo/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

