<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>flouri.sh - Blog</title>
  <id>tag:flouri.sh,2009:mephisto/</id>
  <generator version="0.7.2" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  
  <link href="http://flouri.sh/" rel="alternate" type="text/html" />
  <updated>2009-04-15T04:25:37Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/Flourish-Blog" type="application/atom+xml" /><entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2009-04-11:68</id>
    <published>2009-04-11T18:28:00Z</published>
    <updated>2009-04-15T04:25:37Z</updated>
    <category term="Projects" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/_YrFrCaQINs/ruby-sandboxing-resources" rel="alternate" type="text/html" />
    <title>Ruby Sandboxing Resources</title>
<summary type="html">A complete list of sandboxing resources that I've been able to find, from articles on the sandbox itself to examples of the sandbox in action.</summary><content type="html">
            A complete list of sandboxing resources that I've been able to find, from articles on the sandbox itself to examples of the sandbox in action.
&lt;h3&gt;The sandbox itself&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://github.com/why/sandbox/tree/master"&gt;Freaky Freaky Sandbox&lt;/a&gt; 
- A sandboxing gem based on the MRI ruby interpreter.  Written in C, it hacks the VM to 
allow safe execution of untrusted code&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.ruby-forum.com/topic/150864"&gt;Why-the-lucky-stiff talking about the
freaky freaky sandbox&lt;/a&gt; - He explains it as an alternative to $SAFE in a 
discussion with ruby team.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://flouri.sh/2009/4/4/how-to-set-up-the-ruby-sandbox"&gt;How to set up the 
C-Ruby sandbox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://ola-bini.blogspot.com/search/label/javasand"&gt;JavaSand&lt;/a&gt; - A sandboxing gem
for JRuby.  It provides the same API as the C-based-ruby sandbox.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://flouri.sh/2009/4/4/how-to-set-up-the-jruby-sandbox"&gt;How to set up the JRuby
sandbox&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Sandbox Support&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="http://github.com/dsboulder/acts_as_wrapped_class/tree/master"&gt;
acts_as_wrapped_class&lt;/a&gt;&lt;/code&gt; - A gem that adds easy class-wrapping for safely exposing
an API to the sandbox code.
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href="http://github.com/dsboulder/acts_as_wrapped_class/tree/master"&gt;
acts_as_runnable_code&lt;/a&gt;&lt;/code&gt; - A gem that makes creation of sandboxes and evaluation
of uploaded code easier.
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://flouri.sh/2007/10/27/safely-exposing-your-app-to-a-ruby-sandbox"&gt;
Safely Exposing your App to a ruby sandbox&lt;/a&gt; - My article on setting up a sandbox. 
&lt;/ul&gt;
&lt;h3&gt;Sandbox Examples&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://expr.sandbox.flouri.sh/"&gt;Expression Runner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://hangman.sandbox.flouri.sh/"&gt;Hangman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tictactoe.sandbox.flouri.sh/"&gt;TicTacToe&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/_YrFrCaQINs" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2009/4/11/ruby-sandboxing-resources</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2009-04-04:66</id>
    <published>2009-04-04T21:15:00Z</published>
    <updated>2009-04-04T21:16:20Z</updated>
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/XF-HumJNGlc/how-to-set-up-the-jruby-sandbox" rel="alternate" type="text/html" />
    <title>How to set up the JRuby sandbox</title>
<content type="html">
            &lt;p&gt;
The JRuby Sandbox is simply a rewrite of why's original sandbox gem in JRuby.  It's much less of a hack
than the C implementation, and generally considered to be more safe.  Here's how I set it up:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download and install the latest JRuby binaries from 
&lt;a href="http://dist.codehaus.org/jruby/"&gt;CodeHaus&lt;/a&gt; (I tested with 1.1.5).
&lt;/li&gt;
&lt;li&gt;Download the source of the javasand jruby gem from the JRuby addons project&lt;br /&gt;
&lt;code&gt;svn checkout http://jruby-extras.rubyforge.org/svn/trunk/javasand&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compile the gem:&lt;br /&gt;
&lt;code&gt;ant&lt;/code&gt;&lt;br /&gt;
&lt;em&gt;BUILD SUCCESSFUL&lt;/em&gt;&lt;br /&gt;
&lt;strong&gt;If the build fails&lt;/strong&gt;, it might be because it can't find the JRuby classes.  
You'll need to find jruby.jar and then add a line to build.xml inside the "build.classpath" path:&lt;br /&gt;
&lt;code&gt;&amp;lt;fileset dir="/path/to/jruby/jars" includes="*.jar" /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Package up the gem:&lt;br /&gt;
&lt;code&gt;jgem build javasand.gemspec&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install the gem:&lt;br /&gt;
&lt;code&gt;sudo jgem install javasand-0.0.2.gem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Test the sandbox with &lt;code&gt;jirb -rubygems&lt;/code&gt;
&lt;pre class="blackboard"&gt;&lt;span class="Keyword"&gt;require&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;sandbox&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="Support"&gt;Sandbox&lt;/span&gt;.&lt;span class="Entity"&gt;safe&lt;/span&gt;.&lt;span class="Entity"&gt;eval&lt;/span&gt;(&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;2+2&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; yields 4&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you can see above, I had to compile the gem from source.  The &lt;strong&gt;binary gem of javasand 
from rubyforge failed&lt;/strong&gt; with the following exception:&lt;br /&gt;
&lt;code&gt;&lt;pre&gt;
irb(main):001:0&gt; require "sandbox"
=&gt; true
irb(main):002:0&gt; Sandbox.safe
org.jruby.ext.sandbox.Sandkit:714:in `removeMethods': java.lang.NoSuchMethodError: org.jruby.RubyModule.removeMethod(Ljava/lang/String;)V
&lt;/pre&gt;&lt;/code&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/XF-HumJNGlc" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2009/4/4/how-to-set-up-the-jruby-sandbox</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2009-04-04:65</id>
    <published>2009-04-04T20:43:00Z</published>
    <updated>2009-04-04T20:50:57Z</updated>
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/0jKePWQzXEk/how-to-set-up-the-ruby-sandbox" rel="alternate" type="text/html" />
    <title>How to set up the ruby sandbox</title>
<content type="html">
            &lt;p&gt;There's very little recent work on the MRI ruby sandbox, so here's a quick guide to getting the
sandbox installed and running.  Unfortunately, the sandbox &lt;strong&gt;requires a patched ruby&lt;/strong&gt;,
but luckily it's not that hard to set up.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Download the latest version of ruby 1.8.6 from 
&lt;a href="ftp://ftp.ruby-lang.org/pub/ruby/1.8/"&gt;ftp://ftp.ruby-lang.org/pub/ruby/1.8&lt;/a&gt;
(does not work with 1.8.7 or 1.9, sorry)
&lt;/li&gt;
&lt;li&gt;
Download the sandbox gem source from 
&lt;a href="http://github.com/why/sandbox/tree/master"&gt;git://github.com/why/sandbox.git&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Patch ruby:&lt;br /&gt;
&lt;code&gt;patch -p1 &amp;lt; ../sandbox_gem/patch/ruby-1.8.6-sandbox_needs.patch&lt;/code&gt;&lt;br /&gt;
&lt;em&gt;patching file error.c&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
Compile and install the patched ruby:&lt;br /&gt;
&lt;code&gt;./configure&lt;br /&gt;
make&lt;br /&gt;
sudo make install&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
Download and install rubygems from 
&lt;a href="http://rubyforge.org/frs/?group_id=126&amp;release_id=27655"&gt;RubyForge&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Install the sandbox gem:&lt;br /&gt;
&lt;code&gt;cd sandbox_gem &amp;&amp; sudo ruby setup.rb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
Test the sandbox:&lt;br&gt;
&lt;pre class="blackboard"&gt;&lt;span class="Keyword"&gt;require&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;sandbox&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class="Support"&gt;Sandbox&lt;/span&gt;.&lt;span class="Entity"&gt;safe&lt;/span&gt;.&lt;span class="Entity"&gt;eval&lt;/span&gt;(&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;2+2&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;#&lt;/span&gt; yields 4&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now that you've got the sandbox running, read more about it in my article on 
&lt;a href="http://flouri.sh/2007/10/27/safely-exposing-your-app-to-a-ruby-sandbox"&gt;Advanced Sandboxing&lt;/a&gt;,
or my &lt;a href="http:" /&gt;Sandbox Introduction&lt;/a&gt;.
&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/0jKePWQzXEk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2009/4/4/how-to-set-up-the-ruby-sandbox</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2009-04-04:64</id>
    <published>2009-04-04T19:29:00Z</published>
    <updated>2009-04-04T19:32:10Z</updated>
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/0UNpmNtqabU/i-m-speaking-at-golden-gate-ruby-conf" rel="alternate" type="text/html" />
    <title>I'm speaking at Golden Gate Ruby Conf</title>
<content type="html">
            &lt;p&gt;The title of my talk is: &lt;a href="http://gogaruco.com/schedule/#stevenson"&gt;
&lt;em&gt;Playing with Fire: Running untrusted code in a sandbox&lt;/em&gt;&lt;/a&gt;.  
I expect
to be posting some more articles related to the sandbox before my talk on April 17th.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/0UNpmNtqabU" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2009/4/4/i-m-speaking-at-golden-gate-ruby-conf</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-11-22:61</id>
    <published>2008-11-22T19:25:00Z</published>
    <updated>2008-11-22T19:25:52Z</updated>
    <category term="Work" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/DF680CTzgvY/duplicate-joins-merge-in-rails-2-2" rel="alternate" type="text/html" />
    <title>Duplicate joins merge in rails 2.2</title>
<content type="html">
            &lt;p&gt;
If you've ever suffered from duplicate table aliasing problems in rails, there's a new feature in 2.2 that
will help some of these situations go away.  This seems to come up mostly in named_scope, where you want
to define a list of scopes that can work by themselves or with any other scopes.  This often means having
identical or similar joins in multiple scopes.  Take this example:
&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;User&lt;/span&gt;
  has_one &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;profile&lt;/span&gt;
  named_scope &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;male&lt;/span&gt;, {
    &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;join&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;INNER JOIN profiles ON profiles.user_id = users.id&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;conditions&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;profiles.gender = 'male'&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; 
  }
  named_scope &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;recently_updated&lt;/span&gt;, {
    &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;join&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;INNER JOIN profiles ON profiles.user_id = users.id&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
    &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;conditions&lt;/span&gt; =&amp;gt; [&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;profiles.updated_at &amp;gt; ?&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="Constant"&gt;1&lt;/span&gt;.&lt;span class="Entity"&gt;week&lt;/span&gt;.&lt;span class="Entity"&gt;ago&lt;/span&gt;]	
  }
  named_scope &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;admin&lt;/span&gt;, {
    &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;join&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;INNER JOIN profiles ON profiles.user_id = users.id AND profiles.admin = 1&lt;/span&gt;
&lt;span class="String"&gt;              INNER JOIN emails ON emails.profile_id = profiles.id&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  }
  named_scope &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;with_profiles&lt;/span&gt;, {
    &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;join&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;profile&lt;/span&gt;
  }
&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;
Before 2.2, calling &lt;code&gt;User.male.recently_updated&lt;/code&gt; results in a table aliasing problem, because rails joins
in the &lt;code&gt;profiles&lt;/code&gt; table twice.  Three features in 2.2 make this better:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;:join with hash/symbol syntax merges hashes when combining scope (&lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/501-merge-joins-instead-of-clobbering-them"&gt;Andrew White&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;:join now can take an array of strings (&lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/1077-chaining-scopes-with-duplicate-joins-causes-alias-problem"&gt;David Stevenson &amp; Joseph Palermo&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;string identical joins are uniqued&lt;/b&gt; when combining scopes (&lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/1077-chaining-scopes-with-duplicate-joins-causes-alias-problem"&gt;David Stevenson &amp; Joseph Palermo&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
After 2.2, you &lt;i&gt;can call &lt;code&gt;User.male.recently_updated&lt;/code&gt;&lt;/i&gt; because there are two string identical
joins combined in different scopes.  You &lt;i&gt;can't call &lt;code&gt;User.male.admin&lt;/code&gt;&lt;/i&gt; without making some
modifications, because the two joins involved are not string identical.  Here's how I'd modify the
&lt;code&gt;:admin&lt;/code&gt; scope:&lt;/p&gt;
&lt;pre class="blackboard"&gt;named_scope &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;admin&lt;/span&gt;, {
  &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;join&lt;/span&gt; =&amp;gt; [&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;INNER JOIN profiles ON profiles.user_id = users.id&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,
            &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;INNER JOIN emails ON emails.profile_id = profiles.id&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;],
  &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;conditions&lt;/span&gt; =&amp;gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;profiles.admin = 1&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
}
&lt;/pre&gt;
&lt;p&gt;By using the array of strings :join syntax, I can let rails know that those are two separate joins,
each of which can be merged if an identical join comes up in another scope.  I also moved the extra join
condition (&lt;code&gt;profiles.admin = 1&lt;/code&gt;)to &lt;code&gt;:conditions&lt;/code&gt;, so that the INNER JOIN statement would not have any specific logic for that
particular &lt;code&gt;named_scope&lt;/code&gt; in it.&lt;/p&gt;
&lt;p&gt;I still can't call &lt;code&gt;User.male.with_profiles&lt;/code&gt; because the string representation of the join
from &lt;code&gt;with_profiles&lt;/code&gt; probably doesn't match the join from &lt;code&gt;male&lt;/code&gt;.  It will be off
due to the way rails generates join using different whitespace and escape characters than I originally 
wrote.  This can be easily fixed by copying the exact string rails generates from 
&lt;code&gt;:join =&gt; :profile&lt;/code&gt;and pasting it into &lt;code&gt;male&lt;/code&gt;.
&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/DF680CTzgvY" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/11/22/duplicate-joins-merge-in-rails-2-2</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-11-18:60</id>
    <published>2008-11-18T20:30:00Z</published>
    <updated>2008-11-18T20:31:13Z</updated>
    <category term="Work" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/F2f9-T66f5k/acts_as_solr-has-a-new-home" rel="alternate" type="text/html" />
    <title>acts_as_solr has a new home</title>
<content type="html">
            &lt;h4&gt;Developers finally set up master repo for acts_as_solr&lt;/h4&gt;
&lt;p&gt;After a long time of no development, a new acts_as_solr plugin has emerged on GitHub.  Luke Francl &amp; 
Mathias Meyer have adding a lot to the old plugin and created a new "master".  Mathias has merged several
branches on github including changes from David Palm, kengruven, and myself.  This is great news for
people running/modifying acts_as_solr, as Mathias is a real person who will actually respond to your pull
requests.  Some new features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SOLR 1.3 installed&lt;/li&gt;
&lt;li&gt;Ruby 1.9 support&lt;/li&gt;
&lt;li&gt;LibXML 0.7+ support&lt;/li&gt;
&lt;li&gt;Store types as &lt;code&gt;string&lt;/code&gt; not &lt;code&gt;text&lt;/code&gt; fields in the index&lt;/li&gt;
&lt;li&gt;JVM options in solr.yml&lt;/li&gt;
&lt;li&gt;Completely rewritten test suite&lt;/li&gt;
&lt;li&gt;New solr:reindex task that automatically finds and indexes your solr models&lt;/li&gt;
&lt;/ul&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/F2f9-T66f5k" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/11/18/acts_as_solr-has-a-new-home</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-09-10:48</id>
    <published>2008-09-10T01:18:00Z</published>
    <updated>2008-09-10T01:20:23Z</updated>
    <category term="Technology" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/zUP_EvoBl4s/queryreviewer-now-aggregates-identical-queries" rel="alternate" type="text/html" />
    <title>QueryReviewer now aggregates identical queries</title>
<content type="html">
            &lt;p&gt;I've been using query reviewer exensively at pivotal, and we've noticed that
it is ridiculously slow when you have a lot of queries.  This is due to the large
number of partials rendered (5 partials) for each query in the reviewer box.&lt;/p&gt;
&lt;p&gt;A solution to this problem, that also brings a huge advantage, was to report
aggregate statistics for near-identical queries.  Similar to way mysqlslowdump
groups near-identical queries, query_reviewer now also reports only 1 line for X
identical queries (identical means the same structure and same stack trace). 
Consequently, &lt;b&gt;it's a lot easier to find places where you're missing includes
&lt;/b&gt;. Here's what it looks like now:&lt;/p&gt;
&lt;a href="http://flouri.sh/assets/2008/9/10/QRaggregate.png?1221009351"&gt;
&lt;img src="http://flouri.sh/assets/2008/9/10/QRaggregate.png?1221009351" /&gt;
&lt;/a&gt;
&lt;p&gt;The time reported for a group is the &lt;i&gt;total&lt;/i&gt; time of all the queries
in that group.  In addition, I add up all the times for all the queries and report
that number in the header. From this, I've noticed that a lot of time is spent in
rails outside of waiting for mysql to return result.  I wonder where that time
goes...&lt;/p&gt;
&lt;p&gt;query_reviewer can be &lt;a href="http://github.com/dsboulder/query_reviewer"&gt;
downloaded from github&lt;/a&gt;!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/zUP_EvoBl4s" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/9/10/queryreviewer-now-aggregates-identical-queries</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-06-25:47</id>
    <published>2008-06-25T03:50:00Z</published>
    <updated>2008-06-25T03:52:27Z</updated>
    <category term="Technology" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/smlWAmpw1l4/queryreviewer-is-now-rails-2-1-safe" rel="alternate" type="text/html" />
    <title>QueryReviewer is now rails 2.1 safe</title>
<content type="html">
            &lt;p&gt;Thanks to a nice suggestion by the community which I pretty much used verbatim.  
Still works with rails 2.0 and 1.2.3.  Check out the project homepage.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/query-reviewer/"&gt;http://code.google.com/p/query-reviewer/&lt;/a&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/smlWAmpw1l4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/6/25/queryreviewer-is-now-rails-2-1-safe</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-04-30:45</id>
    <published>2008-04-30T16:05:00Z</published>
    <updated>2008-06-20T16:07:30Z</updated>
    <category term="Work" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/XNKKDwWz_2Q/i-m-working-at-pivotal" rel="alternate" type="text/html" />
    <title>I'm working at Pivotal</title>
<content type="html">
            After a 4 month interlude at &lt;a href="http://www.spongefish.com"&gt;SpongeFish&lt;/a&gt;,
I'm now working at &lt;a href="http://www.pivotallabs.com"&gt;Pivotal Labs&lt;/a&gt;.  Pivotal's
a really fun place to do agile rails consulting and I'm loving it so far...
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/XNKKDwWz_2Q" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/4/30/i-m-working-at-pivotal</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-04-10:43</id>
    <published>2008-04-10T21:05:00Z</published>
    <updated>2008-04-10T21:19:12Z</updated>
    <category term="Technology" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/ttdagfa0iAo/mysql-query-reviewer-now-with-ajax-and-profiling" rel="alternate" type="text/html" />
    <title>MySQL Query Reviewer - now with AJAX and Profiling</title>
<content type="html">
            &lt;p&gt;Kevin Hall and I have released a new version of the 
&lt;a href="http://code.google.com/p/query-reviewer/"&gt;query_reviewer&lt;/a&gt;
plugin. You should start by looking at my 
&lt;a href="http://flouri.sh/2008/2/13/mysql-query_reviewer-plugin"&gt;first post&lt;/a&gt;, 
to see what the basic premise is before reading this article.  The single largest improvment is the ability to 
analyze the database requests of AJAX requests, which is accomplished by piggy backing javascript or HTML
into the ends of AJAX responses.
Here's what it currently looks like, analyzing
my project on a page that does lots of database requests:&lt;/p&gt;
&lt;a href="http://flouri.sh/assets/2008/4/10/Picture_4.png"&gt;
  &lt;img src="http://flouri.sh/assets/2008/4/10/Picture_4.png" /&gt;
&lt;/a&gt;
&lt;p&gt;The improvements are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View query analysis for &lt;strong&gt;AJAX requests&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Take into account the &lt;strong&gt;duration&lt;/strong&gt; of a query (if production data)&lt;/li&gt;
&lt;li&gt;Show &lt;strong&gt;PROFILE&lt;/strong&gt; information from mysql&lt;/li&gt;
&lt;li&gt;Warnings for &lt;strong&gt;long key&lt;/strong&gt; lengths (which can be bad even when you hit an index)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lots of information is now available for a single slow query:&lt;/p&gt;
&lt;a href="http://flouri.sh/assets/2008/4/10/Picture_5.png"&gt;
  &lt;img src="http://flouri.sh/assets/2008/4/10/Picture_5.png" /&gt;
&lt;/a&gt;
&lt;p&gt;I'm really excited that this plugin is getting attention, and welcome feedback, suggestions, and bug reports
on the &lt;a href="http://code.google.com/p/query-reviewer/"&gt;Google Code project homepage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To install it, simply visit the &lt;a href="http://code.google.com/p/query-reviewer/"&gt;project homepage&lt;/a&gt;.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/ttdagfa0iAo" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/4/10/mysql-query-reviewer-now-with-ajax-and-profiling</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-03-30:41</id>
    <published>2008-03-30T18:07:00Z</published>
    <updated>2008-03-30T18:08:33Z</updated>
    <category term="Personal" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/sPgYjTMywDg/flourish-is-back-from-the-dead" rel="alternate" type="text/html" />
    <title>Flourish is back from the dead</title>
<content type="html">
            &lt;p&gt;Things started going very badly for flouri.sh when my home server wouldn't boot up.
I removed almost all the hardware, but could not even get a POST screen or any beeps.  I even
reseated the RAM and CPU, but no luck.  Finally, I grabbed an old media PC shuttle cube and
attempted the craziest idea:&lt;/p&gt;

&lt;img src="http://flouri.sh/assets/2008/3/30/server_lifeboat.jpg?1206900468" /&gt;

&lt;p&gt;The 4 x RAID5 disks are actually being powered by my old server, but the PCI raid card is 
inserted into my old media PC.  The shuttle doesn't have enough power or room to run all those disks
so I'm using the old server as a lifeboat with 4 IDE cables running between them!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/sPgYjTMywDg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/3/30/flourish-is-back-from-the-dead</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-02-18:39</id>
    <published>2008-02-18T19:11:00Z</published>
    <updated>2008-02-18T19:59:50Z</updated>
    <category term="Technology" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/jKGFUMpaGbg/writing-data-migrations-in-rails" rel="alternate" type="text/html" />
    <title>Writing data migrations in rails</title>
<content type="html">
            &lt;h3&gt;Using ActiveRecord can be tricky, here's how&lt;/h3&gt;
&lt;p&gt;
Data migrations are a major headache in every rails project I've worked on.  Developers typically write straight SQL migrations which take much
longer to create and test, or they use ActiveRecord and run into problems.  I recent wrote a data migration which took 7 existing tables and
compressed them into 4.  Some of the new 4 had the same names as the existing models, so I finally figured out how to do this safely with 
ActiveRecord.  Here's my advice:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When changing the schema of an existing set of tables, create new tables and then rename them.&lt;/li&gt;
&lt;li&gt;Include active record fragments &lt;b&gt;inside the migration class&lt;/b&gt; at the top of your migrations.&lt;/li&gt;
&lt;li&gt;Put your data migrations inside transactions.&lt;/li&gt;
&lt;li&gt;Make your data migrations completely reversible (which is a lot easier when you follow the first rule)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here's an example of an ActiveRecord class fragment at the top of a migration:&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Entity"&gt;MarkPrimaryBits&lt;span class="Superclass"&gt; &lt;span class="Superclass"&gt;&amp;lt;&lt;/span&gt; ActiveRecord::Migration&lt;/span&gt;&lt;/span&gt;
  &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Variable"&gt;LessonVersion&lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt; &lt;span class="Support"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="Entity"&gt;Base&lt;/span&gt;
    &lt;span class="Support"&gt;belongs_to&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;lesson&lt;/span&gt;
  &lt;span class="Keyword"&gt;end&lt;/span&gt;

  &lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="Variable"&gt;Lesson&lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt; &lt;span class="Support"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="Entity"&gt;Base&lt;/span&gt;
    &lt;span class="Support"&gt;has_many&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;lesson_versions&lt;/span&gt;
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
 
  &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;self.up&lt;/span&gt;
    ...
&lt;/pre&gt;
&lt;p&gt;By putting the Lesson and LessonVersion classes at the top of the migration, I'm allowing myself to use those classes inside my migration
and be &lt;i&gt;completely independent of any changes made to the real model&lt;/i&gt; from then on (including the deletion of the class itself).  
Furthermore, I can have another migration which uses those same class names with completely different meanings and they won't conflict 
with each other.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/jKGFUMpaGbg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/2/18/writing-data-migrations-in-rails</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-02-15:38</id>
    <published>2008-02-15T18:11:00Z</published>
    <updated>2008-02-15T18:25:04Z</updated>
    <category term="Technology" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/l2cJrAMDxRk/extending-has_many-associations-correctly" rel="alternate" type="text/html" />
    <title>Extending has_many associations correctly</title>
<content type="html">
            &lt;h3&gt;How to build custom methods on associations that aren't slow&lt;/h3&gt;
&lt;p&gt;The "has_many do" syntax has been widely adopted in rails, but I often see it going wrong.  Consider the following association extension:&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="Support"&gt;has_many&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;versions&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
  &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;primary&lt;/span&gt;
    &lt;span class="Entity"&gt;find&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;first&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;conditions&lt;/span&gt; =&amp;gt; {&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;primary&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;true&lt;/span&gt;})
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;What's wrong with this code is that the finder has to execute a database request every time it's invoked.  True, rails has a query cache, but it
results in more database requests then one should need.  We can make it better by caching the result in an instance variable attached to the
association:&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="Support"&gt;has_many&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;versions&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
  &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;primary&lt;/span&gt;
    &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;primary&lt;/span&gt; &lt;span class="Keyword"&gt;||=&lt;/span&gt; &lt;span class="Entity"&gt;find&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;first&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;conditions&lt;/span&gt; =&amp;gt; {&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;primary&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;true&lt;/span&gt;})
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;But what if you already have the association loaded?  Inside the block, you can access various methods of the AssociationCollection and
AssociationProxy classes.  Notable methods are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;proxy_owner - the module that contains the association&lt;/li&gt;
&lt;li&gt;proxy_reflection - the Reflection object that contains the association options (FK, :dependent, etc)&lt;/li&gt;
&lt;li&gt;proxy_target - the cached association data, if the association has been loaded&lt;/li&gt;
&lt;li&gt;loaded? - returns true if the association has been loaded&lt;/li&gt;
&lt;li&gt;reset - delete the cached association data and forget it has been loaded&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using these methods, we can rewrite our method to be the most efficient possible, by making use of loaded association data when present:&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="Support"&gt;has_many&lt;/span&gt; &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;versions&lt;/span&gt; &lt;span class="Keyword"&gt;do&lt;/span&gt;
  &lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;primary&lt;/span&gt;
    &lt;span class="Keyword"&gt;if&lt;/span&gt; loaded?
      &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;primary&lt;/span&gt; &lt;span class="Keyword"&gt;||=&lt;/span&gt; proxy_target.&lt;span class="Entity"&gt;detect&lt;/span&gt; { |&lt;span class="Variable"&gt;ver&lt;/span&gt;| ver.&lt;span class="Entity"&gt;primary?&lt;/span&gt; }
    &lt;span class="Keyword"&gt;else&lt;/span&gt;
      &lt;span class="Variable"&gt;&lt;span class="Variable"&gt;@&lt;/span&gt;primary&lt;/span&gt; &lt;span class="Keyword"&gt;||=&lt;/span&gt; &lt;span class="Entity"&gt;find&lt;/span&gt;(&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;first&lt;/span&gt;, &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;conditions&lt;/span&gt; =&amp;gt; {&lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;primary&lt;/span&gt; =&amp;gt; &lt;span class="Constant"&gt;true&lt;/span&gt;})
    &lt;span class="Keyword"&gt;end&lt;/span&gt;
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now our method is guarenteed to make only 1 database call, no matter how many times invoked.  It also will make zero database calls if the
entire association has already been loaded.  The only downside is that "how to determine if primary" logic has to be written once in rails_sql 
and once in pure ruby.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/l2cJrAMDxRk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/2/15/extending-has_many-associations-correctly</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-02-13:37</id>
    <published>2008-02-13T18:46:00Z</published>
    <updated>2008-02-13T18:47:38Z</updated>
    <category term="Work" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/QSJAjOJE9io/mysql-query_reviewer-plugin" rel="alternate" type="text/html" />
    <title>MySQL query_reviewer plugin</title>
<content type="html">
            &lt;h3&gt;query_analyzer on steriods!&lt;/h3&gt;
&lt;h4&gt;Features&lt;/h4&gt;
&lt;p&gt;QueryReviewer is an advanced SQL query analyzer.  It accomplishes the following goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View all EXPLAIN output for all SELECT queries to generate a page&lt;/li&gt;
&lt;li&gt;Rate a page's SQL usage into one of three categories: OK, WARNING, CRITICAL&lt;/li&gt;
&lt;li&gt;Attach meaningful warnings to individual queries&lt;/li&gt;
&lt;li&gt;Find out where the query was executed with a stack trace&lt;/li&gt;
&lt;li&gt;Display advanced interactive summary on page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It accomplishes this by injecting an absolutely positioned div into your HTML markup before it's sent out of rails.  View injection can be 
turned off, if necessary and replaced with &amp;lt;%= query_review_output %&amp;gt; somewhere in your view.&lt;/p&gt;

&lt;h4&gt;Screenshot&lt;/h4&gt;
&lt;img src="http://flouri.sh/assets/2008/2/13/Screenshot-stevend_on_SpongeFish_-_Mozilla_Firefox.png?1202927924" width="" /&gt;
&lt;a href="http://flouri.sh/assets/2008/2/13/Screenshot-stevend_on_SpongeFish_-_Mozilla_Firefox.png?1202927924"&gt;View larger&lt;/a&gt;

&lt;h4&gt;Project homepage&lt;/h4&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/query-reviewer/"&gt;http://code.google.com/p/query-reviewer/&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Installing&lt;/h4&gt;
&lt;p&gt;svn export http://query-reviewer.googlecode.com/svn/trunk/ vendor/plugins/query_reviewer&lt;/p&gt;
&lt;p&gt;Then optionally run "rake query_reviewer:setup" and edit config/query_reviewer.yml to change the default settings.&lt;p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/QSJAjOJE9io" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/2/13/mysql-query_reviewer-plugin</feedburner:origLink></entry>
  <entry xml:base="http://flouri.sh/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:flouri.sh,2008-01-02:36</id>
    <published>2008-01-02T21:24:00Z</published>
    <updated>2008-01-02T23:43:57Z</updated>
    <category term="Technology" />
    <link href="http://feedproxy.google.com/~r/Flourish-Blog/~3/s3Z6ouCJlew/mephisto-mac-com-photo-feed" rel="alternate" type="text/html" />
    <title>mac.com "Web Gallery" Photos in Mephisto</title>
<content type="html">
            &lt;h4&gt;All the flickr functionality with better iPhoto integration!&lt;/h4&gt;
&lt;p&gt;I just finished a conversion of my existing flickr ajax mephisto plugin to use mac.com web
galleries!  I finally ended up paying for mac.com, because of the awesome integration with everything.&lt;/p&gt;
&lt;p&gt;Features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pull photos from a specific album or your entire gallery&lt;/li&gt;
&lt;li&gt;Uses AJAX to pull feed data, so it won't bottleneck your main page rendering&lt;/li&gt;
&lt;li&gt;Randomly chooses X photos to display every time&lt;/li&gt;
&lt;li&gt;A variety of supported images sizes: square, small, medium, and large&lt;/li&gt;
&lt;li&gt;Images automatically link to Apple's awesome web gallery interface&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Issues (depending on size of gallery, mine has 400 images at the time):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The RSS feed takes between 2 and 10 seconds to deliver from apple.&lt;/li&gt;
&lt;li&gt;The downloaded XML file takes 2 to 5 seconds process.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Usage&lt;/h4&gt;
&lt;p&gt;How I used it in my site:&lt;/p&gt;
&lt;pre class="blackboard"&gt;&lt;span class="MetaTag"&gt;&lt;span class="MetaTag"&gt;&amp;lt;&lt;/span&gt;&lt;span class="MetaTag"&gt;p&lt;/span&gt;&lt;span class="MetaTag"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Pictures:&lt;span class="MetaTag"&gt;&lt;span class="MetaTag"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="MetaTag"&gt;p&lt;/span&gt;&lt;span class="MetaTag"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
{% macgallery feed: http://gallery.mac.com/dsboulder/?webdav-method=truthget&amp;amp;feedfmt=photocastrss  count: 4  format: square  width: 75  height: 75 %} 
{% endmacgallery %}
&lt;/pre&gt;
&lt;p&gt;Supported options to the "macgallery" liquid tag:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;feed: REQUIRED.  The url of the RSS feed to your gallery, or to a specific album.&lt;/li&gt;
  &lt;li&gt;count: OPTIONAL (default: 6).  The number of images to display.&lt;/li&gt;
  &lt;li&gt;format: OPTIONAL (default: square).  Also valid are "small", "medium", and "large".&lt;/li&gt;
  &lt;li&gt;width/height: OPTIONAL (default: none).  If specified, will add width and height attributes to the IMG tag.  Useful for resizing the square images from their 160x160 default size.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Where to get the plugin&lt;/h4&gt;
&lt;code&gt;
svn checkout http://mephisto-mac-gallery-ajax.googlecode.com/svn/trunk/ vendor/plugins/mephisto_mac_gallery_ajax
&lt;/code&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Flourish-Blog/~4/s3Z6ouCJlew" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://flouri.sh/2008/1/2/mephisto-mac-com-photo-feed</feedburner:origLink></entry>
</feed>
