<?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>assay depot - Home</title>
  <id>tag:blog.assaydepot.com,2009:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  
  <link href="http://blog.assaydepot.com/" rel="alternate" type="text/html" />
  <updated>2008-12-14T03:26:21Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/AssayDepotDevelopment" type="application/atom+xml" /><entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-12-14:2499</id>
    <published>2008-12-14T03:25:00Z</published>
    <updated>2008-12-14T03:26:21Z</updated>
    <category term="Ruby on Rails" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/k2QuvkM-n_Q/tanning-bed" rel="alternate" type="text/html" />
    <title>Tanning Bed</title>
<content type="html">
            &lt;div&gt;
&lt;img src="/assets/2008/12/14/tanning_bed.png" alt="tanning bed" /&gt;
&lt;/div&gt;
&lt;p&gt;
We've been working on our search engine lately. We've tried &lt;a href="http://acts-as-solr.rubyforge.org/"&gt;acts_as_solr&lt;/a&gt; in the past, and have been using &lt;a href="http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/files/README.html"&gt;UltraSphinx&lt;/a&gt; lately. For reasons I'll detail in a later post, we've considered moving back to solr. Rob Kaufman of &lt;a href="http://notch8.com"&gt;Notch 8&lt;/a&gt; has done a lot of great work writing &lt;a href="http://github.com/notch8/tanning_bed/tree/master"&gt;Tanning Bed&lt;/a&gt;, a ORM agnostic interface for Solr. From his github page:
&lt;/p&gt;
&lt;blockquote&gt;
Tanning Bed is a generic Solr interface for models, because models are too sexy to get the their tans from the sun directly.
&lt;/blockquote&gt;
&lt;p&gt;
We'll be moving back to Solr in the next few months, and we'll be using Tanning Bed. Check it out.
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/12/14/tanning-bed</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-10-10:1384</id>
    <published>2008-10-10T22:40:00Z</published>
    <updated>2008-10-10T22:41:21Z</updated>
    <category term="Ruby on Rails" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/96-tlGdDIz0/merb-camp" rel="alternate" type="text/html" />
    <title>Merb Camp</title>
<content type="html">
            &lt;div&gt;
&lt;img src="/assets/2008/10/10/merb_camp.gif" alt="ruby gem" /&gt;
&lt;/div&gt;
&lt;p&gt;
I just wanted to write a quick blog post about &lt;a href="http://merbcamp.com"&gt;MerbCamp&lt;/a&gt; this weekend. MerbCamp is the first Merb conference. So what is Merb? Well, from &lt;a href="http://merbivore.com"&gt;the Merb website&lt;/a&gt;:
&lt;blockquote&gt;
Merb is an MVC framework that is ORM-agnostic, JavaScript library agnostic, and template language agnostic, preferring plugins that add in support for a particular feature rather than trying to produce a monolithic library with everything in the core.
&lt;/blockquote&gt;
I've been playing with Merb a lot lately, and I'm really excited it.
&lt;/p&gt;
&lt;p&gt;
The Merb sprint is under way right now and &lt;a href="http://merbist.com"&gt;Matt&lt;/a&gt;, &lt;a href="http://notch8.com"&gt;Rob&lt;/a&gt; and &lt;a href="http://www.aisleten.com"&gt;Ryan&lt;/a&gt; tell me that 1.0 RC1 will be released this weekend at the conference.
&lt;/p&gt;
&lt;p&gt;It looks like it will be a great conference, so go install Merb, and hopefully I'll see you there!&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/10/10/merb-camp</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-08-04:736</id>
    <published>2008-08-04T00:37:00Z</published>
    <updated>2008-08-04T00:39:36Z</updated>
    <category term="Ruby on Rails" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/9_CuqxzVYoQ/upgrading-ruby-gems-to-1-2-0" rel="alternate" type="text/html" />
    <title>Upgrading Ruby Gems to 1.2.0</title>
<content type="html">
            &lt;div&gt;
&lt;img src="/assets/2008/8/4/ruby_gem.jpg" alt="ruby gem" /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;
I just finished deploying the latest version of the website, and I ran into some trouble related to the gems we use, specifically the version of rubygems we use. I'm posting this here in case anyone runs across a similar problem.
&lt;/p&gt;
&lt;p&gt;
It started when I tried to do the following
&lt;pre&gt;&lt;code&gt;cap deploy:migrations&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
I got the following error:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  * executing "cd /mnt/apps/web/releases/20080802232104; rake RAILS_ENV=production  db:migrate"
    servers: ["ec2-67-202-49-9.compute-1.amazonaws.com"]
    [ec2-67-202-49-9.compute-1.amazonaws.com] executing command
 ** [out :: ec2-67-202-49-9.compute-1.amazonaws.com] (in /mnt/apps/web/releases/20080802232104)
 ** [out :: ec2-67-202-49-9.compute-1.amazonaws.com] rake aborted!
 ** [out :: ec2-67-202-49-9.compute-1.amazonaws.com] undefined method `collect' for #&amp;lt;Gem::Version::Requirement:0xb77cdcf8&amp;gt;
 ** [out :: ec2-67-202-49-9.compute-1.amazonaws.com] 
 ** [out :: ec2-67-202-49-9.compute-1.amazonaws.com] (See full trace by running task with --trace)
    command finished
    command "cd /mnt/apps/web/releases/20080802232104; rake RAILS_ENV=production  db:migrate" failed on ec2-67-202-49-9.compute-1.amazonaws.com&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
We use a number of gems in our project, and since the error included
&lt;pre&gt;&lt;code&gt;undefined method `collect' for #&amp;lt;Gem::Version::Requirement:0xb77cdcf8&amp;gt;&lt;/code&gt;&lt;/pre&gt;
I figured the configuration of those gems was a good place to start. We have a block in our environment.rb that looks like:
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;config.gem &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;acts_as_versioned&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;config.gem &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;chronic&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:version&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;0.2.3&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;config.gem &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;pdf-labels&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:version&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;2.0.0&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:lib&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;pdf/label&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;config.gem &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;shipping&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:version&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1.5.1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;config.gem &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;rubyist-aasm&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:lib&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;aasm&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

As an aside, if I removed all the ":version =&gt; x.y.x" I got a different error:
&lt;pre&gt;&lt;code&gt;undefined method `collect' for nil:NilClass&lt;/code&gt;&lt;/pre&gt;
I guess that makes sense. After getting nowhere for a while, I emailed Rob from &lt;a href="http://notch8.com"&gt;Notch8&lt;/a&gt; who out of the goodness of his heart emailed me back even though he was on vacation. He suggested upgrading ruby gems itself.
&lt;pre&gt;&lt;code&gt;sudo gem update --system&lt;/code&gt;&lt;/pre&gt;
Interestingly, after the update, /usr/bin/gem didn't work because it was pointing to the old gem libraries. I found the following fixed that.
&lt;pre&gt;&lt;code&gt;sudo rm /usr/bin/gem
sudo ln -s /usr/bin/gem1.8 /usr/bin/gem&lt;/code&gt;&lt;/pre&gt;
At this point, my deploy is almost working, however, when it tries restart mongrel I get the following error.
&lt;pre&gt;&lt;code&gt;ERROR RUNNING 'cluster::restart': Plugin /cluster::restart does not exist in category /commands&lt;/code&gt;&lt;/pre&gt;
Since upgrading got me this far, I tried upgrading mongrel_cluster
&lt;pre&gt;&lt;code&gt;sudo gem install mongrel_cluster&lt;/code&gt;&lt;/pre&gt;
Which worked, and I was able to successfully deploy the application. Thank goodness we have staging server, doing all of that on production would have been a non-starter.
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/8/4/upgrading-ruby-gems-to-1-2-0</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-05-29:256</id>
    <published>2008-05-29T21:14:00Z</published>
    <updated>2008-05-29T21:21:37Z</updated>
    <category term="Miscellanea" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/B8odoi6tu8A/powermed" rel="alternate" type="text/html" />
    <title>Powermed</title>
<content type="html">
            &lt;img class="headline" src="http://blog.assaydepot.com/assets/2008/5/29/powerset.png" /&gt;
&lt;p&gt;
By now I'm sure you've tried or at least heard of &lt;a href="http://www.powerset.com"&gt;Powerset&lt;/a&gt;. In their own words:
&lt;blockquote&gt;
&lt;a href="http://www.powerset.com"&gt;Powerset's&lt;/a&gt; goal is to change the way people interact with technology by enabling computers to understand our language.
&lt;/blockquote&gt;
What that means to you is; instead of just doing a keyword search, &lt;a href="http://www.powerset.com"&gt;Powerset&lt;/a&gt; understands what you ask it and returns results based on what you mean. Take the following query as an example: "who wrote mongrel". When you ask &lt;a href="http://www.google.com"&gt;Google&lt;/a&gt;, you get the following:
&lt;/p&gt;
&lt;img class="body" src="http://blog.assaydepot.com/assets/2008/5/29/who_wrote_mongrel_google.png" alt="Who wrote mongrel - Google" /&gt;
&lt;p&gt;
Which gives you the information you are looking for, but when you ask &lt;a href="http://www.powerset.com"&gt;Powerset&lt;/a&gt; the same question you get:
&lt;/p&gt;
&lt;img class="body" src="http://blog.assaydepot.com/assets/2008/5/29/who_wrote_mongrel_powerset_1.png" alt="Who wrote mongrel - Powerset" /&gt;
&lt;p&gt;
Interestingly Powerset tells us, right at the top of the page, "Zed A. Shaw wrote Mongrel". Pretty cool.
&lt;/p&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;
Currently &lt;a href="http://www.powerset.com"&gt;Powerset&lt;/a&gt; only searches &lt;a href="http://www.wikipedia.org"&gt;Wikipedia&lt;/a&gt; and &lt;a href="http://freebase.com"&gt;Freebase&lt;/a&gt;. The reason, according to their website is:
&lt;blockquote&gt;
Wikipedia is a primary destination for millions of people worldwide who want to find high-quality, detailed information on a wide array of topics. By initially focusing on the Wikipedia collection, Powerset showcases how our technology not only improves search results, but provides new ways to aggregate, summarize and navigate information. Of course Wikipedia is only a starting point. In the coming months, Powerset will expand our product offerings with additional premium content and exciting new features.
&lt;/blockquote&gt;
I suspect another reason for starting with &lt;a href="http://www.wikipedia.org"&gt;Wikipedia&lt;/a&gt; and &lt;a href="http://freebase.com"&gt;Freebase&lt;/a&gt; is, they are both clean datasets. Basically they have a lot of information in a standard format.
&lt;/p&gt;
&lt;h2&gt;Enter PubMed&lt;/h2&gt;
&lt;p&gt;
Another dataset I can think of that is very clean and has lot of useful information is &lt;a href="http://www.ncbi.nlm.nih.gov/pubmed/"&gt;Pubmed&lt;/a&gt;. I think if &lt;a href="http://www.powerset.com"&gt;Powerset&lt;/a&gt; would index &lt;a href="http://www.ncbi.nlm.nih.gov/pubmed/"&gt;Pubmed&lt;/a&gt; it would enable some very interesting searches. For that matter you could index the &lt;a href="http://www.uspto.gov/"&gt;USPTO database&lt;/a&gt; or &lt;a href="http://www.doaj.org/"&gt;all the open access journals&lt;/a&gt;. There are a lot of possibilities.
&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
I have to say, I've never found anything with &lt;a href="http://www.powerset"&gt;Powerset&lt;/a&gt; that I couldn't find with &lt;a href="http://ww.google.com"&gt;Google&lt;/a&gt;. That being said, I still like the idea and see the power of it. However, it is possible that if you are asking a question that is so specific or semantically tricky that a keyword search won't work, you probably already have a good idea of the type of information you are looking for. My point is, vertical search is an interesting niche for &lt;a href="http://www.powerset.com"&gt;Powerset&lt;/a&gt;. That doesn't preclude them from eventually indexing the entire internet, but I'd love to see a Powermed.com. 
&lt;/p&gt;
&lt;p&gt;
Ok, back to RailsConf.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Update&lt;/b&gt; Deepak Singh over at bbgm often writes about &lt;a href="http://mndoci.com/blog/2008/05/15/deriving-information-from-structured-data/"&gt;deriving value from structured data&lt;/a&gt;.
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/5/29/powermed</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-05-23:196</id>
    <published>2008-05-23T05:04:00Z</published>
    <updated>2008-05-30T19:07:32Z</updated>
    <category term="Ruby on Rails" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/isO_V84TULQ/upgrade-to-rails-2-1-0_rc1" rel="alternate" type="text/html" />
    <title>Upgrade to Rails 2.1.0_RC1</title>
<content type="html">
            &lt;p&gt;
  &lt;div&gt;
    &lt;a href="http://www.brawndo.com"&gt;
      &lt;img src="http://blog.assaydepot.com/assets/2008/5/23/upgrayedd.jpg" alt="upgrayedd" /&gt;
    &lt;/a&gt;
    &lt;br /&gt;
    &lt;b&gt;upgrade (with 2 Ds)&lt;/b&gt;
  &lt;/div&gt;
  Today seemed like a good day for an upgrade, so I decided to update our app to Rails 2.1.0_RC1. (The real reason is, I wanted to use &lt;code&gt;has_one :through&lt;/code&gt;, but it wasn't in my version of Rails!)
&lt;/p&gt;
&lt;p&gt;
I've detailed the steps I took to get our app up and running, this isn't an exhaustive list by any means, but I hope it helps.
&lt;/p&gt;

&lt;h2&gt;Download Rails 2.1.0_RC1&lt;/h2&gt;
&lt;p&gt;
  Rail is on &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; now, which is a great move. Unfortunately, our app is still under subversion and piston doesn't yet support Git, so I downloaded RC1 from &lt;a href="http://github.com/rails/rails/commits/v2.1.0_RC1"&gt;http://github.com/rails/rails/commits/v2.1.0_RC1&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
  Since I can't manage it with Piston anymore, I completely removed rails from my vendor directory and replaced it with the downloaded version.
&lt;/p&gt;
&lt;p&gt;
  Now its time to run
  &lt;pre&gt;&lt;code&gt;  rake spec
  &lt;/code&gt;&lt;/pre&gt;
  and see where we are.
&lt;/p&gt;
&lt;p&gt;
  &lt;hr /&gt;
  &lt;em&gt;STATUS:&lt;/em&gt; Dead in the water
  &lt;hr /&gt;
&lt;/p&gt;

&lt;h2&gt;ActionView::Base to ActionView::Template&lt;/h2&gt;
&lt;p&gt;
  At this point I can't even run rake, I just get the following error:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; 
  ERROR
  &gt; rake spec
  (in /Users/cpetersen/project)
  rake aborted!
  undefined method `register_template_handler' for ActionView::Base:Class

  (See full trace by running task with --trace)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  It turns out we are registering a template handler for PDFs in our environment. Looks like they moved that functionality out of &lt;code&gt;ActionView::Base&lt;/code&gt; into &lt;code&gt;ActionView::Template&lt;/code&gt;, to fix all we needed to do is change the following line your &lt;code&gt;config/environment.rb&lt;/code&gt;:
  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;    &lt;span class="co"&gt;ActionView&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;.register_template_handler &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="co"&gt;ActionView&lt;/span&gt;::&lt;span class="co"&gt;PDFRender&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

  to:
  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;    &lt;span class="co"&gt;ActionView&lt;/span&gt;::&lt;span class="co"&gt;Template&lt;/span&gt;.register_template_handler &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="co"&gt;ActionView&lt;/span&gt;::&lt;span class="co"&gt;PDFRender&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

  and you can at least start running your specs again.
&lt;/p&gt;
&lt;p&gt;
  &lt;hr /&gt;
  &lt;em&gt;STATUS:&lt;/em&gt; LOTS of errors, 706 failures in 1014 tests
  &lt;hr /&gt;
&lt;/p&gt;

&lt;h2&gt;will_paginate&lt;/h2&gt;
&lt;p&gt;
  We use the wonderful &lt;a href="http://errtheblog.com/posts/47-i-will-paginate"&gt;will_paginate&lt;/a&gt; plugin to handle pagination in our app. However, when I run my specs, I now get the following:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ERROR
  705)
  ActionView::TemplateError in 'CatalogController bin should show a compound'
  stack level too deep
  In catalog/compound.html.erb


      vendor/plugins/will_paginate/lib/will_paginate/finder.rb:138:in `method_missing_without_paginate'
      vendor/plugins/will_paginate/lib/will_paginate/finder.rb:139:in `method_missing'
      app/models/ware.rb:67:in `suggested_bins'
      spec/models/bin_spec.rb:32&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  It turns out, we weren't on the latest release. You can get the latest release &lt;a href="http://github.com/mislav/will_paginate"&gt;here&lt;/a&gt;. Once again, its from &lt;a href="http://github.com"&gt;the hub&lt;/a&gt;. The same process I used for installing Rails from github applies here.
&lt;/a&gt;
&lt;p&gt;
  &lt;hr /&gt;
  &lt;em&gt;STATUS:&lt;/em&gt; fewer errors, 30 failures in 1014 tests
  &lt;hr /&gt;
&lt;/p&gt;

&lt;h2&gt;acts_as_versioned&lt;/h2&gt;
&lt;p&gt;
  Not bad, the tests run, and only about 3% are failing. What next?
&lt;/p&gt;
&lt;p&gt;
Almost all of the remaining errors look like this one:
&lt;pre&gt;&lt;code&gt;  ERROR
  30)
  NoMethodError in '/survey_templates/edit should render survey template edit page'
  You have a nil object when you didn't expect it!
  You might have expected an instance of Array.
  The error occurred while evaluating nil.include?
  ./spec/views/survey_templates/edit.html.erb_spec.rb:6:in `new'
  ./spec/views/survey_templates/edit.html.erb_spec.rb:6:&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
    We are using the &lt;a href="http://wiki.rubyonrails.org/rails/pages/ActsAsVersioned"&gt;acts_as_versioned&lt;/a&gt; plugin for versioning a lot of our content.
&lt;/p&gt;
&lt;p&gt;
  It turns out the core team has done a lot of work on &amp;quot;dirty&amp;quot; objects for this release. Ryan Daigle does a good job &lt;a href="http://ryandaigle.com/articles/2008/3/31/what-s-new-in-edge-rails-dirty-objects"&gt;explaining it&lt;/a&gt;. It turns out this functionality breaks &lt;a href="http://wiki.rubyonrails.org/rails/pages/ActsAsVersioned"&gt;acts_as_versioned&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Luckily for us, &lt;a href="http://blog.codafoo.com/"&gt;codafoo&lt;/a&gt; is able to help. He forked &lt;a href="http://wiki.rubyonrails.org/rails/pages/ActsAsVersioned"&gt;acts_as_versioned&lt;/a&gt; and made it work with RC1 and dirty objects. You can get his version &lt;a href="http://github.com/codafoo/acts_as_versioned"&gt;here&lt;/a&gt;. Since I had frozen &lt;a href="http://wiki.rubyonrails.org/rails/pages/ActsAsVersioned"&gt;acts_as_versioned&lt;/a&gt; into my &lt;code&gt;vendor/gems&lt;/code&gt; directory, I just had to replace it with codafoo's version. Your milage may vary.
&lt;/p&gt;
&lt;p&gt;
  You'll notice, its &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; once again. Note to self, switch to git.
&lt;/p&gt;
&lt;p&gt;
  &lt;hr /&gt;
  &lt;em&gt;STATUS:&lt;/em&gt; almost there, 2 failures in 1014 tests
  &lt;hr /&gt;
&lt;/p&gt;

&lt;h2&gt;Proper has_one Validation&lt;/h2&gt;
&lt;p&gt;
  Now we are getting down to some nitty gritty errors. It turns out my last two errors were only working before by accident.
&lt;/p&gt;
&lt;p&gt;
  Prior to RC1, &lt;code&gt;has_one&lt;/code&gt; relationships weren't being validated properly on save. I apparently had my fixtures in an inconsistent state, causing my test to fail. My fault, RC1 helped me find a problem with my fixtures. Here is the &lt;a href="http://dev.rubyonrails.org/ticket/10518"&gt;ticket&lt;/a&gt;. I fixed my fixtures, and on to the next/last.
&lt;/p&gt;
&lt;p&gt;
  &lt;hr /&gt;
  &lt;em&gt;STATUS:&lt;/em&gt; last one, 1 failure in 1014 tests
  &lt;hr /&gt;
&lt;/p&gt;

&lt;h2&gt;Minor ActiveRecord::Base.find Change&lt;/h2&gt;
&lt;p&gt;
  Finally, there was a change to &lt;code&gt;ActiveRecord::Base.find&lt;/code&gt;. I have a &lt;code&gt;has_many :through&lt;/code&gt; relationship and I am doing a non-trivial find. I was including the table &lt;code&gt;order_states&lt;/code&gt; and referencing its &lt;code&gt;order_status_id&lt;/code&gt; column in my conditions. However, I wasn't including the table name in my conditions. Here's the code:
  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;    &lt;span class="iv"&gt;@orders&lt;/span&gt; = &lt;span class="co"&gt;Order&lt;/span&gt;.find(&lt;span class="sy"&gt;:all&lt;/span&gt;, &lt;span class="sy"&gt;:conditions&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;order_status_id &amp;gt; 1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:include&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;order_states&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:order&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;orders.created_at   DESC&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

  Prior to the RC1 upgrade that worked, but I should be using the table name. One more case of RC1 finding potential problems in my code. I changed it to:
  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;    &lt;span class="iv"&gt;@orders&lt;/span&gt; = &lt;span class="co"&gt;Order&lt;/span&gt;.find(&lt;span class="sy"&gt;:all&lt;/span&gt;, &lt;span class="sy"&gt;:conditions&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;order_states.order_status_id &amp;gt; 1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:include&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;order_states&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:order&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;orders.created_at DESC&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

  and it worked like a charm. I'm not sure what caused this change, but it &lt;b&gt;may&lt;/b&gt; have been part of this &lt;a href="http://dev.rubyonrails.org/ticket/10698"&gt;change&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;hr /&gt;
  &lt;em&gt;STATUS:&lt;/em&gt; finished.
  &lt;hr /&gt;
&lt;/p&gt;
&lt;p&gt;
  Thanks to &lt;a href="http://notch8.com"&gt;Rob&lt;/a&gt; and &lt;a href="http://aisleten.com"&gt;Ryan&lt;/a&gt; for helping my through this process.
&lt;/p&gt;
&lt;p&gt;
  See you at &lt;a href="http://en.oreilly.com/rails2008"&gt;RailsConf&lt;/a&gt;!
&lt;/p&gt;

&lt;h2&gt;Update - attachment_fu&lt;/h2&gt;
&lt;p&gt;
After I wrote this post, I realized that &lt;a href="http://svn.techno-weenie.net/projects/plugins/attachment_fu/"&gt;attachment_fu&lt;/a&gt; had stopped working (yet all the tests passed, troublesome). When I tried to upload something, I received the following stack trace:
&lt;/p&gt;
&lt;code&gt;
NoMethodError (undefined method `after_attachment_saved_callback_chain' for #&amp;lt;class:0x52030dc&gt;):
    /vendor/rails/activerecord/lib/active_record/base.rb:1645:in `method_missing_without_paginate'
    /vendor/plugins/will_paginate/lib/will_paginate/finder.rb:164:in `method_missing'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:272:in `send'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:272:in `run_callbacks'
    /vendor/rails/activerecord/lib/active_record/callbacks.rb:298:in `callback'
    /vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb:377:in `after_process_attachment'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:173:in `send'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:173:in `evaluate_method'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:161:in `call'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:93:in `run'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `each'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `send'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:92:in `run'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:272:in `run_callbacks'
    /vendor/rails/activerecord/lib/active_record/callbacks.rb:298:in `callback'
    /vendor/rails/activerecord/lib/active_record/callbacks.rb:208:in `create_or_update'
    /vendor/rails/activerecord/lib/active_record/base.rb:2176:in `save_without_validation'
    /vendor/rails/activerecord/lib/active_record/validations.rb:901:in `save_without_dirty'
    /vendor/rails/activerecord/lib/active_record/dirty.rb:75:in `save_without_transactions'
    /vendor/rails/activerecord/lib/active_record/transactions.rb:106:in `save'
    /vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:66:in `transaction'
    /vendor/rails/activerecord/lib/active_record/transactions.rb:79:in `transaction'
    /vendor/rails/activerecord/lib/active_record/transactions.rb:98:in `transaction'
    /vendor/rails/activerecord/lib/active_record/transactions.rb:106:in `save'
    /vendor/rails/activerecord/lib/active_record/transactions.rb:118:in `rollback_active_record_state!'
    /vendor/rails/activerecord/lib/active_record/transactions.rb:106:in `save'
    /app/controllers/assets_controller.rb:54:in `create'
    /vendor/rails/actionpack/lib/action_controller/mime_responds.rb:106:in `call'
    /vendor/rails/actionpack/lib/action_controller/mime_responds.rb:106:in `respond_to'
    /app/controllers/assets_controller.rb:53:in `create'
    /vendor/rails/actionpack/lib/action_controller/base.rb:1161:in `send'
    /vendor/rails/actionpack/lib/action_controller/base.rb:1161:in `perform_action_without_filters'
    /vendor/rails/actionpack/lib/action_controller/filters.rb:580:in `call_filters'
    /vendor/rails/actionpack/lib/action_controller/filters.rb:601:in `run_before_filters'
    /app/controllers/application.rb:17:in `set_current'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:173:in `send'
    /vendor/rails/activesupport/lib/active_support/callbacks.rb:173:in `evaluate_method'
    /vendor/rails/actionpack/lib/action_controller/filters.rb:395:in `call'
    /vendor/rails/actionpack/lib/action_controller/filters.rb:598:in `run_before_filters'
    /vendor/rails/actionpack/lib/action_controller/filters.rb:578:in `call_filters'
    /vendor/rails/actionpack/lib/action_controller/filters.rb:573:in `perform_action_without_benchmark'
    /vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
    /usr/local/lib/ruby/1.8/benchmark.rb:293:in `measure'
    /vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
    /vendor/rails/actionpack/lib/action_controller/rescue.rb:201:in `perform_action_without_caching'
    /vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:13:in `perform_action'
&lt;/code&gt;
&lt;p&gt;
The solution for us was just to update attachment_fu to trunk. Voila, everything started working again.
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/5/23/upgrade-to-rails-2-1-0_rc1</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-05-17:153</id>
    <published>2008-05-17T01:33:00Z</published>
    <updated>2008-05-17T01:34:58Z</updated>
    <category term="Miscellanea" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/fEO1j5F3BPA/great-visualizations" rel="alternate" type="text/html" />
    <title>Great Visualizations</title>
<content type="html">
            &lt;p&gt;
Visualizing complex data can be hard. How do you get your point across when the data you have to present doesn't fit nicely into a bar chart, pie chart, line graph or histogram?
&lt;/p&gt;
&lt;p&gt;
Over the last couple of weeks, I've come across a number of great visualizations. They cover a range of topics, but they all effectively convey complex data in a very accessible way. &lt;a href="http://www.edwardtufte.com/tufte/"&gt;Edward Tufte&lt;/a&gt; would be proud.
&lt;/p&gt;
&lt;h2&gt;Water Distribution&lt;/h2&gt;
&lt;p&gt;
This is a great visualization, it shows where water is located on earth. It could have been displayed in a bar chart, however, it would have effectively gone to zero by the time you got to fresh water. This method effectively conveys relative distribution down to rivers and plants and animals.
&lt;/p&gt;
&amp;lt;center&gt;
     &lt;a href="http://www.unep.org/geo/geo4/media/graphics/Zoom/4.1.jpg"&gt;&lt;img src="http://blog.assaydepot.com/assets/2008/5/17/water_distribution.jpg" /&gt;&lt;/a&gt;
&amp;lt;/center&gt;
&lt;h2&gt;Early Adopters&lt;/h2&gt;
&lt;p&gt;
The following graphic shows us the price of a piece of technology relative to its market penetration over time. As if three variables wasn't enough, it shows all that for 6 separate pieces of technology relative to each other.
&lt;/p&gt;
&amp;lt;center&gt;
     &lt;a href="http://www.wired.com/images/article/magazine/test2007/st_infoporn_f.jpg"&gt;&lt;img src="http://blog.assaydepot.com/assets/2008/5/17/living_on_the_edge.jpg" /&gt;&lt;/a&gt;
&amp;lt;/center&gt;
&lt;h2&gt;Global GDPs&lt;/h2&gt;
&lt;p&gt;
The final visualization shows the GDP of the world's four largest economies after the United States, relative to the US. There are a lot of unanswered questions about this visualization, like is the US economy exactly as big as these four combined? The visualization implies so, but I don't know for sure. Additionally, are the economies distributed on a dollar = geographic size only, or does it imply that the UK has the same GDP as the Southeast United States? Again, I assume the former, but the latter is a possibility. At any rate, the graphic is very effective at conveying the relative size of the worlds top five economies.
&lt;/p&gt;
&amp;lt;center&gt;
     &lt;a href="http://flickr.com/photos/22994175@N03/2205172655/sizes/l/"&gt;&lt;img src="http://blog.assaydepot.com/assets/2008/5/17/gdp.jpg" /&gt;&lt;/a&gt;
&amp;lt;/center&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/5/17/great-visualizations</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>achen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-05-05:144</id>
    <published>2008-05-05T19:52:00Z</published>
    <updated>2008-05-05T21:02:59Z</updated>
    <category term="Miscellanea" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/jiPc5xausEA/torrey-pines-hike" rel="alternate" type="text/html" />
    <title>Torrey Pines Hike</title>
<content type="html">
            &lt;p&gt;
On Thursday, Assay Depot took a hike through the Torrey Pines State Reserve. Our three conferences were marketing successes and yielded what seemed like nonstop mornings and nights of hard work, so we decided to take an afternoon off. The reserve is home to one of the rarest pines in the world, the Torrey Pine.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.assaydepot.com/assets/2008/5/5/Hill.jpg" alt="Torrey Pines perched on the hill" /&gt;
&lt;br /&gt;
&lt;b&gt;Torrey Pines perched on the hill&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
It is probably one of the few natural reserves in the state where you can also get superior mobile phone reception. 
&lt;/p&gt;
&lt;p&gt;
There is a path from the frontyard of our office that leads right to the coast. It was an enjoyable two mile walk on what was an unmatched spring day. However, mild treachery did arise. It seemed that some parts of the path were constructed for hobbits. Had Frodo only gone through this path while being chased by the henchmen of Sauron, he would have guaranteed his safety. 
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.assaydepot.com/assets/2008/5/5/Hobbit.jpg" alt="A three foot high tunnel. No horses allowed. " /&gt;
&lt;br /&gt;
&lt;b&gt;A three foot high tunnel. No horses allowed.&lt;/b&gt;
&lt;/p&gt;
&lt;p&gt;
Thankfully, this treachery only lasted for about one minute and paled in comparison to the blooming shrubbery, cactus, and black beetles of Mother Earth.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.assaydepot.com/assets/2008/5/5/White.jpg" /&gt;
&lt;br /&gt;
&lt;img src="http://blog.assaydepot.com/assets/2008/5/5/Slant.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
After an hour, we made it to the coast.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.assaydepot.com/assets/2008/5/5/View.jpg" /&gt;
&lt;br /&gt;
&lt;img src="http://blog.assaydepot.com/assets/2008/5/5/Waves.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
We are seen here relaxing around refreshments and string cheese.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.assaydepot.com/assets/2008/5/5/Everybody.jpg" /&gt;
&lt;/p&gt;
&lt;p&gt;
Sorry, but no boogie boarding, wakeboarding, or surfing. However, if you know us, you know that anything can happen. Stay tuned!
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/5/5/torrey-pines-hike</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-05-02:143</id>
    <published>2008-05-02T21:48:00Z</published>
    <updated>2008-07-08T00:29:31Z</updated>
    <category term="EC2" />
    <category term="Ruby on Rails" />
    <category term="Virtual Computing" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/8LZPNBgF1QY/sdruby-ec2" rel="alternate" type="text/html" />
    <title>SDRuby EC2</title>
<content type="html">
            &lt;p&gt;
Last night I had the opportunity to give a presentation on EC2 to &lt;a href="http://sdruby.com"&gt;San Diego Ruby User Group&lt;/a&gt;. In an effort to keep the talk accessible, I intentionally kept the slides simple and promised to supplement them with a EC2 cheat sheet. Well here it is:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.slideshare.net/cpetersen/ec2"&gt;&lt;img src="/assets/2008/7/8/powerpoint_icon.png" alt="The slides from the talk" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="/assets/2008/5/2/EC2_Handout.pdf"&gt;&lt;img src="/assets/2008/5/2/pdf_icon.jpg" alt="The eBook version" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://podcast.sdruby.com/2008/6/20/episode-049-intro-to-ec2"&gt;&lt;img src="/assets/2008/7/8/quicktime-icon.jpg" alt="The video podcast of the talk" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;
Like I mentioned in my talk, this was intended to be a 1-2 page, maybe 3 page cheat sheet. As I was writing it quickly became a 20 page eBook. I hope you find it useful.
&lt;/p&gt;
&lt;p&gt;
Many thanks to &lt;a href="http://mokolabs.com/"&gt;Patrick Crowley&lt;/a&gt; for organizing it and to &lt;a href="http://glu.ttono.us/"&gt;Kevin Clark&lt;/a&gt; who also presented that evening. I will update this page when the Podcast is available.
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/5/2/sdruby-ec2</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-03-27:15</id>
    <published>2008-03-27T15:37:00Z</published>
    <updated>2008-04-04T17:58:27Z</updated>
    <category term="Marketing" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/TAP-sjuB1i0/life-scientists-and-social-media" rel="alternate" type="text/html" />
    <title>Life Scientists and Social Media</title>
<content type="html">
            &lt;p&gt;
I just got an email from &lt;a href="http://www.gene2drug.com/"&gt;BioInformatics LLC&lt;/a&gt; advertising their new &lt;a href="http://lifesciencesocialmedia.com/?dnum=11"&gt;new report, &lt;i&gt;The New Collaboration: Social Media and the Life Science Opportunity&lt;/i&gt;&lt;/a&gt;. It is a great report, and is closely related to what we are doing here at the Assay Depot. A few things jumped out at me while reading it.
&lt;/p&gt;
&lt;h2&gt;Product Information&lt;/h2&gt;
&lt;p&gt;
According to the report, third party online portals are the least trusted source of product information, while company websites are the most trusted. I can understand that, when I'm looking for a computer, I check out Apple's website before I check Amazon. Now I wouldn't characterize Amazon (or the Assay Depot for that matter) as online portals, but we are both marketplaces that act as third parties in transactions between customers and companies.
&lt;/p&gt;
&lt;p&gt;
To mitigate this trust issue, and to make things as easy as possible for our users, wherever possible, we will link the products on our website to the companies own web page about that product.
&lt;/p&gt;
&lt;h2&gt;Objective Feedback&lt;/h2&gt;
&lt;p&gt;
If social media isn't the most trusted source of product information, it is the most trusted source for objective feedback. 45% of respondents said so. This complements our strategy of providing peer reviews of the services and products we offer.
&lt;/p&gt;
&lt;h2&gt;Influence on Purchasing Decision&lt;/h2&gt;
&lt;p&gt;
Section 8 of the report touches on how social media has influenced purchasing decisions. Interestingly it seems that social media has made them more informed regarding their purchasing decisions, but it hasn't made purchasing faster, or changed the purchasing process.
&lt;/p&gt;
&lt;p&gt;
I strongly believe this is going to change. Currently their are no tools that combine social media and purchasing, it is a bit of a disjointed process. People search for information (often using social media) about what they are purchasing. Then they go back to the old system of calling to negotiate prices and legal contracts and faxing purchase orders back and forth. I'm trying not to make this post too much of a "sales pitch", but that is what we are trying to do. Make the purchasing of research services easy by combining e-commerce with customer reviews, links to the actual supplier, and eventually more community and social media capabilities. We just want to make scientists lives easier.
&lt;/p&gt;
&lt;h2&gt;Finally...&lt;/h2&gt;
&lt;p&gt;
There are two more quotes in the report that I found interesting:
&lt;blockquote&gt;
Social Media appeals to the fundamental values of science - communication contribution and collaborating.
&lt;/blockquote&gt;
I couldn't agree more...
&lt;/p&gt;
&lt;p&gt;
and:
&lt;blockquote&gt;
In an environment where the average scientist buys products from a dozen or more vendors, making it easier for them to open a dialog with you can can only strengthen their loyalty.
&lt;/blockquote&gt;
right on again...
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/3/27/life-scientists-and-social-media</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-03-24:14</id>
    <published>2008-03-24T13:28:00Z</published>
    <updated>2008-04-04T17:51:07Z</updated>
    <category term="Marketing" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/z-Jm4Z8qYqA/sot-2008" rel="alternate" type="text/html" />
    <title>SOT 2008</title>
<content type="html">
            &lt;p&gt;
Last week was the &lt;a href="http://www.toxicology.org/"&gt;Society of Toxicology (SOT)&lt;/a&gt; meeting in Seattle Washington. It the first conference where the Assay Depot had a booth, and in my opinion it was a huge success! We met a lot of great people, started to get the message out and talked to a bunch of service providers many of whom sound like promising leads.
&lt;/p&gt;&lt;p&gt;
Like I said, we don't launch until next month, and as such SOT was a learning experience for us and we learned a lot... for instance:
&lt;ol&gt;
&lt;li&gt;Spend the extra money and get the thicker carpet, if you are standing for 2 or 3 days straight, it makes a difference&lt;/li&gt;
&lt;li&gt;Post-it notes are great give aways, everyone needs them, and if they use them, they are basically posting your logo/url/name for you&lt;/li&gt;
&lt;li&gt;It must be good to be in the conference business, I mean $161 to rent a table for 3 days... seriously?!&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt;
We will be applying these lessons and more next month at &lt;a href="http://www.sbsonline.org/sbscon/2008/index.php"&gt;the Society for Biomolecular Screening meeting (SBS)&lt;/a&gt;, &lt;a href="http://portal.acs.org/portal/acs/corg/content?_nfpb=true&amp;_pageLabel=PP_TRANSITIONMAIN&amp;node_id=857&amp;use_sec=false&amp;sec_url_var=region1"&gt;the American Chemical Society meeting (ACS)&lt;/a&gt; and &lt;a href="http://www.eb2008.org/"&gt;the Experimental Biology meeting (EB)&lt;/a&gt;. If you are going to any of those meeting, come check us out!
&lt;/p&gt;
&lt;h2&gt;A Picture is Worth a Thousand Words&lt;/h2&gt;
&lt;p&gt;
I brought my camera so we could record the event... unfortunately I miscalculated and only brought my &lt;a href="http://www.usa.canon.com/consumer/controller?act=ModelInfoAct&amp;fcategoryid=152&amp;modelid=7307"&gt;fixed focal length lens&lt;/a&gt;, so the photos are a little more zoomed in than I would like, but you can judge for yourselves.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Kevin and myself (as well as the laptop I'm typing on right now) in front of our booth&lt;/b&gt;
&lt;br /&gt;
&lt;img src="/assets/2008/4/3/kevin_chris.jpg" alt="Kevin and Chris" /&gt;
&lt;br /&gt;
&lt;b&gt;Mei, Andy and Charles also in front of our booth&lt;/b&gt;
&lt;br /&gt;
&lt;img src="/assets/2008/4/3/mei_andy_charles.jpg" alt="Mei, Andy and Charles" /&gt;
&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
While we were there, we met some great people, including our booth neighbors. Here are a few of them:
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Srinivas Ventrapragada, the CEO of &lt;a href="http://www.clintoxbio.com/"&gt;Clintox&lt;/a&gt; in front of his booth at SOT 2008&lt;/b&gt;
&lt;br /&gt;
&lt;img src="/assets/2008/4/3/clintox.jpg" alt="Clintox" /&gt;
&lt;br /&gt;

&lt;b&gt;Mike DeGraaf of &lt;a href="http://www.pharmoptima.com/"&gt;PharmOptima&lt;/a&gt; in front of his booth at SOT 2008&lt;/b&gt;
&lt;br /&gt;
&lt;img src="/assets/2008/4/3/pharmoptima.jpg" alt="PharmOptima" /&gt;
&lt;br /&gt;

&lt;b&gt;Colin Burton of &lt;a href="http://www.mds-usa.com/"&gt;MDS-USA&lt;/a&gt; in front of his booth at SOT 2008&lt;/b&gt;
&lt;br /&gt;
&lt;img src="/assets/2008/4/3/mds-usa.jpg" alt="MDS-USA" /&gt;
&lt;br /&gt;

It was great hanging out with you guys, Pike st. was a blast!
&lt;/p&gt;
&lt;p&gt;
And last but certainly not least, I got a chance to speak with Deepak from &lt;a href="http://mndoci.com/blog/"&gt;Business|Bytes|Genes|Molecules&lt;/a&gt; in person which was great.
&lt;/p&gt;
&lt;p&gt;
Thank you everyone for a great conference.
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/3/24/sot-2008</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2008-03-10:13</id>
    <published>2008-03-10T19:40:00Z</published>
    <updated>2008-04-04T17:51:07Z</updated>
    <category term="EC2" />
    <category term="Ubuntu" />
    <category term="Virtual Computing" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/KK5Z09vg8vA/create-your-own-ec2-image" rel="alternate" type="text/html" />
    <title>Create Your Own EC2 Image</title>
<content type="html">
            &lt;p&gt;
  We have been working day and night preparing for our beta launch in April, which is just one of the many excuses I have for not posting in so long. Part of preparing for that launch is setting up the platform that we are going to deploy to. For numerous reasons, we’ve chosen &lt;a href="http://aws.amazon.com/ec2"&gt;Amazon’s &lt;span class="caps"&gt;EC2&lt;/span&gt;&lt;/a&gt; for our production system. &lt;span class="caps"&gt;EC2&lt;/span&gt; is a great service, and getting up and running with it isn’t hard at all. However, when it comes to creating your own image, I ran into some barriers, I thought I’d share how we overcame them. I hope you find it useful.
&lt;/p&gt;
&lt;p&gt;
  &lt;i&gt;(Side note: Deepak Singh over at business|byte|genes|molecules blogged about an &lt;a href="http://mndoci.com/blog/2008/03/03/jeff-barr-on-amazon-web-services/"&gt;interview with Jeff Barr, an Amazon Web Services Evangelist&lt;/a&gt; which I found interesting).&lt;/i&gt;
&lt;/p&gt;
&lt;h2&gt;Assumptions&lt;/h2&gt;
&lt;p&gt;
  For the purpose of this post, I am assuming your have a working &lt;span class="caps"&gt;EC2&lt;/span&gt; account, your rsa key is installed properly, and have the basic tools working, ie:
  &lt;pre&gt;&lt;code&gt;    ec2din
    ec2dim
  &lt;/code&gt;&lt;/pre&gt;
  &lt;a href="http://docs.amazonwebservices.com/AWSEC2/2007-08-29/GettingStartedGuide/?ref=get-started"&gt;Here is a good tutorial on how to get up and running.&lt;/a&gt;
&lt;/p&gt;
&lt;h2&gt;Starting with &lt;span class="caps"&gt;EC2&lt;/span&gt; on Rails&lt;/h2&gt;
&lt;p&gt;
  In my search for a deployment platform, I came across the &lt;a href="http://ec2onrails.rubyforge.org/"&gt;&lt;span class="caps"&gt;EC2&lt;/span&gt; on Rails project&lt;/a&gt;. It has a bunch of nice things built in, but for various reasons, their standard image wouldn’t work for us. Nevertheless, we decided to use their image as our starting point. You can get their current &lt;span class="caps"&gt;AMI&lt;/span&gt;’s by running the following command (assuming you have the ec2onrails gem installed):
  &lt;pre&gt;&lt;code&gt;    cap ec2onrails:ami_ids
  &lt;/code&gt;&lt;/pre&gt;
Currently, the 32-bit &lt;span class="caps"&gt;AMI&lt;/span&gt; is ami-e620c58f. Next we start an instance and login:
  &lt;pre&gt;&lt;code&gt;    ec2run ami-e620c58f --instance-type m1.small -k gsg-keypair
    ec2din
    ssh -i ~/.ssh/id_rsa-gsg-keypair admin@ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com
  &lt;/code&gt;&lt;/pre&gt;
  In order to rebundle the image, you will need your pk and cert on the server. I store mine in the /mnt/aws-config directory, so lets create that directory. From &lt;i&gt;the server&lt;/i&gt; run:
  &lt;pre&gt;&lt;code&gt;    sudo mkdir /mnt/aws-config
    sudo chown admin.admin /mnt/aws-config
  &lt;/code&gt;&lt;/pre&gt;
  Next, upload the files from your &lt;i&gt;local computer&lt;/i&gt;
  &lt;pre&gt;&lt;code&gt;    scp -i ~/.ssh/id_rsa-gsg-keypair ~/.ec2/*.pem admin@ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com:/mnt/aws-config
  &lt;/code&gt;&lt;/pre&gt;
  To make things easier in the coming steps, I add the pk and cert filenames to my environment. On the server, edit your .profile to include the following lines (I add them before ./usr/local/ec2onrails/config, but I’m not sure it matters):
  &lt;pre&gt;&lt;code&gt;    KEY_FILE_NAME=pk-[your pk filename].pem
    CERT_FILE_NAME=cert-[your cert filename].pem
    AWS_ACCOUNT_ID=[your account id]
  &lt;/code&gt;&lt;/pre&gt;
  Next we have to prepare to rebundle. The &lt;span class="caps"&gt;EC2&lt;/span&gt; on Rails image comes with a rebundle script. However, I was never able to make it work, so I broke out the necessary steps here:
  &lt;pre&gt;&lt;code&gt;    curl http://s3.amazonaws.com/ec2-downloads/ec2-api-tools.zip &gt; /tmp/ec2-api-tools.zip
    sudo unzip /tmp/ec2-api-tools.zip -d /usr/local
    sudo chmod -R go-w /usr/local/ec2-api-tools*
    sudo ln -sf /usr/local/ec2-api-tools-* /usr/local/ec2-api-tools
    sudo aptitude install -y sun-java6-jre
  &lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Insert your configuration here&lt;/h2&gt;
&lt;p&gt;
  At this point, you are ready to configure the sever however you see fit. For us it was installing some support software, etc. Although you may want to complete the tutorial first and make sure you can rebundle properly before investing too much time!
&lt;/p&gt;
&lt;h2&gt;The /mnt directory&lt;/h2&gt;
&lt;p&gt;
  So at this point you have your perfect server, all you need to do is store the image so you can preserve it forever. There is one last item to deal with, the mnt directory. Whenever you ec2kill an instance and start a new one from the image, the /mnt directory get cleared, which makes sense. You need some place to store all the transient data (like logfiles and deployment versions) that don’t belong in the image. However, somethings in there (like directories for log files) need to exists for the image to start properly. So what’s a person to do? Well I decided on a scheme where I tar up a skeleton on the mnt directory, and wrote an install script for it. That way when I start a new instance, I log in, run ./install.sh and I’m up and running.
&lt;/p&gt;
&lt;h2&gt;Create your mnt directory skeleton&lt;/h2&gt;
&lt;p&gt;
  Next I copy the /mnt directory to my home directory and get it just the way I like it (at least get rid of the openssh_id.pub and lost+found).
  &lt;pre&gt;&lt;code&gt;    sudo cp -R /mnt ~
    cd ~/mnt
    sudo rm lost+found
    sudo rm openssh_id.pub
  &lt;/code&gt;&lt;/pre&gt;
  Now tar up your directory:
  &lt;pre&gt;&lt;code&gt;    sudo tar cvfz ~/mnt.tgz ~/mnt
  &lt;/code&gt;&lt;/pre&gt;
  Next we need to write the install script. Mine looks something like (don’t forget to make it executable):
  &lt;pre&gt;&lt;code&gt;    #!/bin/sh

    sudo tar xvfz mnt.tgz
    cd mnt
    sudo chown app.app -R app
    sudo chown mysql.mysql -R mysql_data
    cd log
    sudo chown syslog.adm *
    sudo chown www-data.www-data -R apache2
    sudo chown mysql.mysql -R mysql
    sudo chown root.root -R fsck
    cd ..
    sudo mv * /mnt

    sudo /etc/init.d/mysql start
    sudo /etc/init.d/apache2 start
  &lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
  That’s it, your instance is now configured and ready, now for the good stuff.
&lt;/p&gt;
&lt;h2&gt;Finally, its time to bundle&lt;/h2&gt;
&lt;p&gt;
  First we create the image:
  &lt;pre&gt;&lt;code&gt;    sudo ec2-bundle-vol -u $AWS_ACCOUNT_ID -c /mnt/aws-config/$CERT_FILE_NAME -k /mnt/aws-config/$KEY_FILE_NAME
  &lt;/code&gt;&lt;/pre&gt;
  Next, we need to upload the image to S3, (you must create an S3 bucket prior to this step):
  &lt;pre&gt;&lt;code&gt;  
    ec2-upload-bundle -b [your-bucket] -m /tmp/image.manifest.xml -a [your access key] -s [your secret access key]
  &lt;/code&gt;&lt;/pre&gt;
  The final step is to register your image with Amazon and get your &lt;span class="caps"&gt;AMI&lt;/span&gt;:
  &lt;pre&gt;&lt;code&gt;  
    ec2-register -K /mnt/aws-config/$KEY_FILE_NAME -C /mnt/aws-config/$CERT_FILE_NAME [your-bucket]/image.manifest.xml
  &lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;h2&gt;Putting it all together (AKA, the test)&lt;/h2&gt;
&lt;p&gt;
  So you’ve now created your bundle. The true test is, can you start it, login, run your install script, and have a fully functional server. From your &lt;i&gt;local machine&lt;/i&gt;:
  &lt;pre&gt;&lt;code&gt;    ec2dim # You should see your new AMI
    ec2run [AMI from previous command] --instance-type m1.small -k gsg-keypair
    ec2din
    ssh -i ~/.ssh/id_rsa-gsg-keypair admin@ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com
  &lt;/code&gt;&lt;/pre&gt;
  Now run the install script from the &lt;i&gt;remote machine&lt;/i&gt;:
  &lt;pre&gt;&lt;code&gt;    ./install.sh
  &lt;/code&gt;&lt;/pre&gt;
  You should now have a fully functional server.
&lt;/p&gt;
&lt;h2&gt;Bonus&lt;/h2&gt;
&lt;p&gt;
  I created two aliases on my local machine that i found very helpful, maybe you will too:
  &lt;pre&gt;&lt;code&gt;    alias ec2ssh="ssh -i ~/.ssh/id_rsa-gsg-keypair" 
    alias ec2scp="scp -i ~/.ssh/id_rsa-gsg-keypair" 
  &lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;h2&gt;Coming Attractions&lt;/h2&gt;
&lt;p&gt;
  Like I said earlier, we are launching our beta in April, so expect to see a lot of changes to the site shortly. One of those changes will include moving from WordPress to &lt;a href="http://mephistoblog.com/"&gt;Mephisto&lt;/a&gt;. if your feed reader resets, I apologize in advance.
&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2008/3/10/create-your-own-ec2-image</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2007-11-21:12</id>
    <published>2007-11-21T14:23:00Z</published>
    <updated>2008-04-04T17:51:07Z</updated>
    <category term="Ruby on Rails" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/qS9I3Lq-6Q8/geocoding-in-ruby" rel="alternate" type="text/html" />
    <title>Geocoding in Ruby</title>
<content type="html">
            &lt;h1&gt;The Geocode Module&lt;/h1&gt;
&lt;p&gt;
Have you ever needed to turn a partial address into a full one? Have you ever wanted to get the latitude or longitude for a particular address? Maybe you want to plot addresses on a Google Map, or maybe, like a colleague of mine, you find it redundant to ask for city, state AND zip when creating a form. If any of these apply to you, you might be interested in geocoding.
&lt;/p&gt;
&lt;p&gt;
Geocoding is the process of turning an address (or in some cases a partial address) into latitude and longitude. Often times during the process you get more information about the address. For instance if you geocode "1000 5th Ave, 92101", not only with you get the latitude and longitude (32.715714, -117.160158), you also find out that it's in San Diego, CA.
&lt;/p&gt;
There are many services out there that will geocode addresses for you. For instance the &lt;a href="http://cartographer.rubyforge.org/"&gt;Cartographer plugin&lt;/a&gt; provides a couple of nice Geocoding modules. One for &lt;a href="http://geocoder.us/"&gt;Geocoder.us&lt;/a&gt; and one for &lt;a href="http://www.ontok.com/geocode/"&gt;Ontok&lt;/a&gt;. Both are great alternatives for geocoding. However, I wanted to use Google, and I didn't want to use the full &lt;a href="http://cartographer.rubyforge.org/"&gt;Cartographer plugin&lt;/a&gt;. So I wrote the following module that allows you to geocode addresses in Ruby using Google's service.
&lt;/p&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;35&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;45&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Geocode&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;geocode&lt;/span&gt;(input)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    uri = &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/maps/geo?q=&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;input.gsub(&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="ch"&gt;\s&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;%20&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;&amp;amp;output=xml&amp;amp;key=&amp;lt;your google map's key&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    res = &lt;span class="co"&gt;Net&lt;/span&gt;::&lt;span class="co"&gt;HTTP&lt;/span&gt;.start(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;maps.google.com&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) {|http|&lt;tt&gt;
&lt;/tt&gt;      http.get(uri)&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      doc = &lt;span class="co"&gt;REXML&lt;/span&gt;::&lt;span class="co"&gt;Document&lt;/span&gt;.new(res.body)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;if&lt;/span&gt; doc &amp;amp;&amp;amp; doc.root&lt;tt&gt;
&lt;/tt&gt;        coordinateNode = doc.root.get_elements(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;//coordinates&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).first&lt;tt&gt;
&lt;/tt&gt;        addressNode = doc.root.get_elements(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;//ThoroughfareName&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).first&lt;tt&gt;
&lt;/tt&gt;        stateNode = doc.root.get_elements(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;//AdministrativeAreaName&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).first&lt;tt&gt;
&lt;/tt&gt;        cityNode = doc.root.get_elements(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;//SubAdministrativeAreaName&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).first&lt;tt&gt;
&lt;/tt&gt;        cityNode = doc.root.get_elements(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;//LocalityName&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).first &lt;span class="r"&gt;unless&lt;/span&gt; cityNode&lt;tt&gt;
&lt;/tt&gt;        zipcodeNode = doc.root.get_elements(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;//PostalCodeNumber&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).first&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;        longitude,latitude = coordinateNode.text.split(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;if&lt;/span&gt; coordinateNode&lt;tt&gt;
&lt;/tt&gt;        address = addressNode.text &lt;span class="r"&gt;if&lt;/span&gt; addressNode&lt;tt&gt;
&lt;/tt&gt;        state = stateNode.text &lt;span class="r"&gt;if&lt;/span&gt; stateNode&lt;tt&gt;
&lt;/tt&gt;        city = cityNode.text &lt;span class="r"&gt;if&lt;/span&gt; cityNode&lt;tt&gt;
&lt;/tt&gt;        zipcode = zipcodeNode.text &lt;span class="r"&gt;if&lt;/span&gt; zipcodeNode&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;return&lt;/span&gt; {&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:latitude&lt;/span&gt; =&amp;gt; latitude.to_f,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:longitude&lt;/span&gt; =&amp;gt; longitude.to_f,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:description&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:original_address&lt;/span&gt; =&amp;gt; input,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:score&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:street_number&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:prefix&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:street_name&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:street_type&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:suffix&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:address1&lt;/span&gt; =&amp;gt; address,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:city&lt;/span&gt; =&amp;gt; city,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:state&lt;/span&gt; =&amp;gt; state,&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="sy"&gt;:zipcode&lt;/span&gt; =&amp;gt; zipcode&lt;tt&gt;
&lt;/tt&gt;        }&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;rescue&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;# Do something useful...&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# if nothing has returned yet, then return nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;return&lt;/span&gt; &lt;span class="pc"&gt;nil&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;
You'll notice a few returned items that are always nil, that's because it is a drop in replacement for the Geocoding modules in Cartographer. So even if you use the Cartographer plugin, you can still use this module.
&lt;/p&gt;
&lt;h1&gt;Using the Geocode Module&lt;/h1&gt;
&lt;p&gt;
To use the Geocode module, simply include it, and pass it an address or partial address.
&lt;/p&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;include &lt;span class="co"&gt;Geocode&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;result = geocode(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;92121&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;result[&lt;span class="sy"&gt;:address1&lt;/span&gt;]&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;, &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;result[&lt;span class="sy"&gt;:city&lt;/span&gt;]&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;, &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;result[&lt;span class="sy"&gt;:state&lt;/span&gt;]&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;, &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;result[&lt;span class="sy"&gt;:zipcode&lt;/span&gt;]&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;result[&lt;span class="sy"&gt;:latitude&lt;/span&gt;]&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;, &lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;result[&lt;span class="sy"&gt;:longitude&lt;/span&gt;]&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2007/11/21/geocoding-in-ruby</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2007-11-18:11</id>
    <published>2007-11-18T15:19:00Z</published>
    <updated>2008-04-04T17:51:07Z</updated>
    <category term="Ruby on Rails" />
    <category term="Statistics" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/mSz81tqY2ug/stats-on-rails" rel="alternate" type="text/html" />
    <title>Stats on Rails</title>
<content type="html">
            &lt;h1&gt;The Stats Module&lt;/h1&gt;
Have you ever had an array of numbers and needed to know if one was a statistical outlier? Ever needed the standard deviation of those numbers? Well, I was recently working on an app, where I did. I packaged up the functionality as the following Module.
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;35&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;45&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;54&lt;tt&gt;
&lt;/tt&gt;55&lt;tt&gt;
&lt;/tt&gt;56&lt;tt&gt;
&lt;/tt&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;61&lt;tt&gt;
&lt;/tt&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;64&lt;tt&gt;
&lt;/tt&gt;65&lt;tt&gt;
&lt;/tt&gt;66&lt;tt&gt;
&lt;/tt&gt;67&lt;tt&gt;
&lt;/tt&gt;68&lt;tt&gt;
&lt;/tt&gt;69&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;70&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;71&lt;tt&gt;
&lt;/tt&gt;72&lt;tt&gt;
&lt;/tt&gt;73&lt;tt&gt;
&lt;/tt&gt;74&lt;tt&gt;
&lt;/tt&gt;75&lt;tt&gt;
&lt;/tt&gt;76&lt;tt&gt;
&lt;/tt&gt;77&lt;tt&gt;
&lt;/tt&gt;78&lt;tt&gt;
&lt;/tt&gt;79&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;80&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;81&lt;tt&gt;
&lt;/tt&gt;82&lt;tt&gt;
&lt;/tt&gt;83&lt;tt&gt;
&lt;/tt&gt;84&lt;tt&gt;
&lt;/tt&gt;85&lt;tt&gt;
&lt;/tt&gt;86&lt;tt&gt;
&lt;/tt&gt;87&lt;tt&gt;
&lt;/tt&gt;88&lt;tt&gt;
&lt;/tt&gt;89&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;90&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;91&lt;tt&gt;
&lt;/tt&gt;92&lt;tt&gt;
&lt;/tt&gt;93&lt;tt&gt;
&lt;/tt&gt;94&lt;tt&gt;
&lt;/tt&gt;95&lt;tt&gt;
&lt;/tt&gt;96&lt;tt&gt;
&lt;/tt&gt;97&lt;tt&gt;
&lt;/tt&gt;98&lt;tt&gt;
&lt;/tt&gt;99&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;100&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;101&lt;tt&gt;
&lt;/tt&gt;102&lt;tt&gt;
&lt;/tt&gt;103&lt;tt&gt;
&lt;/tt&gt;104&lt;tt&gt;
&lt;/tt&gt;105&lt;tt&gt;
&lt;/tt&gt;106&lt;tt&gt;
&lt;/tt&gt;107&lt;tt&gt;
&lt;/tt&gt;108&lt;tt&gt;
&lt;/tt&gt;109&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;110&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;111&lt;tt&gt;
&lt;/tt&gt;112&lt;tt&gt;
&lt;/tt&gt;113&lt;tt&gt;
&lt;/tt&gt;114&lt;tt&gt;
&lt;/tt&gt;115&lt;tt&gt;
&lt;/tt&gt;116&lt;tt&gt;
&lt;/tt&gt;117&lt;tt&gt;
&lt;/tt&gt;118&lt;tt&gt;
&lt;/tt&gt;119&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;120&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;121&lt;tt&gt;
&lt;/tt&gt;122&lt;tt&gt;
&lt;/tt&gt;123&lt;tt&gt;
&lt;/tt&gt;124&lt;tt&gt;
&lt;/tt&gt;125&lt;tt&gt;
&lt;/tt&gt;126&lt;tt&gt;
&lt;/tt&gt;127&lt;tt&gt;
&lt;/tt&gt;128&lt;tt&gt;
&lt;/tt&gt;129&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;130&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;131&lt;tt&gt;
&lt;/tt&gt;132&lt;tt&gt;
&lt;/tt&gt;133&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Stats&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;mean_stdev_n&lt;/span&gt;(numbers)&lt;tt&gt;
&lt;/tt&gt;    sum = &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    sumsq = &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    n = &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    numbers.each &lt;span class="r"&gt;do&lt;/span&gt; |num|&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;if&lt;/span&gt; num&lt;tt&gt;
&lt;/tt&gt;        sum += num&lt;tt&gt;
&lt;/tt&gt;        sumsq += (num*num)&lt;tt&gt;
&lt;/tt&gt;        n = n&lt;span class="i"&gt;+1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;if&lt;/span&gt; n==&lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;return&lt;/span&gt; &lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;span class="pc"&gt;nil&lt;/span&gt;,&lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      mean = sum/n&lt;tt&gt;
&lt;/tt&gt;      stddev = &lt;span class="co"&gt;Math&lt;/span&gt;::sqrt(sumsq/n - mean * mean)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;return&lt;/span&gt; mean, stddev, n&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;outlier?&lt;/span&gt;(value, mean, stddev, n)&lt;tt&gt;
&lt;/tt&gt;    grubbs = grubbs_outlier_test(value, mean, stddev)&lt;tt&gt;
&lt;/tt&gt;    z = critical_z(n)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;return&lt;/span&gt; grubbs &amp;gt; z&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;grubbs_outlier_test&lt;/span&gt;(value, mean, stddev)&lt;tt&gt;
&lt;/tt&gt;    ((mean - value)/stddev).abs&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;critical_z&lt;/span&gt;(n)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;case&lt;/span&gt;(n)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;3&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;1.15&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;4&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;1.48&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;5&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;1.71&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;6&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;1.89&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;7&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.02&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;8&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.13&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;9&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.21&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;10&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.29&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;11&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.34&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;12&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.41&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;13&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.46&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;14&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.51&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;15&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.55&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;16&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.59&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;17&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.62&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;18&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.65&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;19&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.68&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;20&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.71&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;21&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.73&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;22&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.76&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;23&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.78&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;24&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.80&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;25&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.82&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;26&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.84&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;27&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.86&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;28&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.88&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;29&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.89&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;30&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.91&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;31&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.92&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;32&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.94&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;33&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.95&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;34&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.97&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;35&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.98&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;36&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;2.99&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;37&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.00&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;38&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.01&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;39&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.03&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;40&lt;/span&gt;..&lt;span class="i"&gt;49&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.04&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;50&lt;/span&gt;..&lt;span class="i"&gt;59&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.13&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;60&lt;/span&gt;..&lt;span class="i"&gt;69&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.20&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;70&lt;/span&gt;..&lt;span class="i"&gt;79&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.26&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;80&lt;/span&gt;..&lt;span class="i"&gt;89&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.31&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;90&lt;/span&gt;..&lt;span class="i"&gt;99&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.35&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;100&lt;/span&gt;..&lt;span class="i"&gt;109&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.38&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;110&lt;/span&gt;..&lt;span class="i"&gt;119&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.42&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;120&lt;/span&gt;..&lt;span class="i"&gt;129&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.44&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="i"&gt;130&lt;/span&gt;..&lt;span class="i"&gt;139&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.47&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="fl"&gt;3.49&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


If you are unfamiliar with the grubbs test... well you're not alone, neither was I. I found &lt;a href="http://www.graphpad.com/articles/outlier.htm"&gt;this page&lt;/a&gt; to be especially helpful.

&lt;h1&gt;Usage&lt;/h1&gt;
To use the module, simply include it, calculate mean, stddev and n, then use the outlier? funtion.
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;include(&lt;span class="co"&gt;Stats&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;numbers = &lt;span class="c"&gt;# some array of numbers&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;mean, stddev, n = mean_stdev_n(numbers)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;if&lt;/span&gt; outlier?(&lt;span class="i"&gt;5&lt;/span&gt;, mean, stddev, n)&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;5 is an outlier&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;5 is not an outlier&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2007/11/18/stats-on-rails</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>amartin</name>
    </author>
    <id>tag:blog.assaydepot.com,2007-11-17:10</id>
    <published>2007-11-17T11:43:00Z</published>
    <updated>2008-04-04T17:51:07Z</updated>
    <category term="Miscellanea" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/Wx4zXCccY6c/uninterrupted-sirius-stream-greasemonkey-for-ie" rel="alternate" type="text/html" />
    <title>Uninterrupted Sirius Stream - Greasemonkey for IE</title>
<content type="html">
            &lt;h1&gt;Introduction&lt;/h1&gt;
I’ve been a fan of satellite radio for a few years now.  When we opened the doors to our lab space, it wasn’t after the first computer was plugged in that we had Sirius radio streaming.

	&lt;p&gt;Recently Sirius rolled out an updated version of their web-based player with the introduction of a timeout feature.  Every few hours your have to click on the window to continue listening.  Let’s see if we can’t get rid of this new feature for a click-free listening experience that will last all day long.&lt;/p&gt;


	&lt;p&gt;For those already familiar with tools like Greasemonkey this example is trivial; however, if you have never played with client-side javascript tweaks it might be worth a look.  If you are a developer writing production javascript, this just reinforces the public nature of content or logic you send client-side.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.greasespot.net/"&gt;Greasemonkey&lt;/a&gt; was designed as a plugin for Firefox and there are hundreds of scripts available through &lt;a href="http://userscripts.org"&gt;userscripts.org&lt;/a&gt;.  The plugin allows you to query/add/modify web content via javascript as you see fit.&lt;/p&gt;


	&lt;p&gt;We’re pretty much a Firefox shop at assaydepot, but Sirius is something I’ve always played through IE.  It used to be the case that only IE was supported although that’s no longer true.  One reason I justify leaving Sirius on IE is the frequent restarts I usually make with Firefox during the week.  With a few dozen tabs, Firebug, and who knows that else running Firefox has a habit of getting a little out of control with its memory usage.  Restarting Firefox doesn’t interrupt my IE listening experience :)&lt;/p&gt;


	&lt;p&gt;There is a &lt;a href="http://www.gm4ie.com/index.html"&gt;Greasemonkey for IE&lt;/a&gt; adaptation that is somewhat different from the Firefox version, but nonetheless effective.  That’s what I used for this project.&lt;/p&gt;


&lt;h1&gt;The Fix&lt;/h1&gt;
A quick look at Sirius’s javascript shows the use of a timeout

&lt;code&gt;window.setTimeout("isUserStillListening()", stillListeningTimeout);
...
function isUserStillListening() {
...display a div and require user-interaction to continue listening...
}
&lt;/code&gt;

	&lt;p&gt;This callback displays a hidden div that the user then clicks on.  My first hack checked the display style attribute of this timeout div, if inline it then clicked on the div continuing playback.  I then woke up and just overrode the callback with a null function that leaves the player running.  &lt;span class="caps"&gt;GM4IE&lt;/span&gt; scripts are executed at the end of the page – sirius sends a full featured function that &lt;span class="caps"&gt;GM4IE&lt;/span&gt; overwrites with nothing at the end of the page.&lt;/p&gt;


&lt;code&gt;
function isUserStillListening(){}
&lt;/code&gt;

	&lt;p&gt;That’s it.  To install this one line of js I installed &lt;span class="caps"&gt;GM4IE&lt;/span&gt;, created a &lt;span class="caps"&gt;GM4IE&lt;/span&gt; config file and the javascript file with this function.&lt;/p&gt;


	&lt;p&gt;The &lt;span class="caps"&gt;GM4IE&lt;/span&gt; script installer from File didn’t work right for me so I manually edited the extention.list and whella – uninterrupted tunes once again!&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://developer.assaydepot.com/wp-content/uploads/2007/11/siriuscontinue.zip" title="GM4IE Sirius Continue Listening script"&gt;&lt;span class="caps"&gt;GM4IE&lt;/span&gt; Sirius Continue Listening script&lt;/a&gt;&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2007/11/17/uninterrupted-sirius-stream-greasemonkey-for-ie</feedburner:origLink></entry>
  <entry xml:base="http://blog.assaydepot.com/">
    <author>
      <name>cpetersen</name>
    </author>
    <id>tag:blog.assaydepot.com,2007-10-07:9</id>
    <published>2007-10-07T20:56:00Z</published>
    <updated>2008-04-04T17:51:07Z</updated>
    <category term="Ruby on Rails" />
    <link href="http://feedproxy.google.com/~r/AssayDepotDevelopment/~3/BfV7Eh-PPWY/instantly-add-wiki-functionality-to-your-rails-app" rel="alternate" type="text/html" />
    <title>Instantly add wiki functionality to your Rails app</title>
<content type="html">
            &lt;h1&gt;Introduction&lt;/h1&gt;
Its been a while since we've posted. That's because we've been busy preparing for our beta launch. Toward that end, we've hired Rob Kaufman of &lt;a href="http://www.notch8.com"&gt;Notch8&lt;/a&gt; to strengthen our development effort. This post is about one of the plugins that has come out of that work, &lt;a href="http://code.google.com/p/wiki-column/"&gt;wiki_column&lt;/a&gt;. 

&lt;a href="http://code.google.com/p/wiki-column/"&gt;wiki_column&lt;/a&gt;, allows you to add wiki functionality to any (textual) attribute of any model. Wiki links in that text will then refer to the model that you define as your wiki, the wiki model defaults to WikiPage. Any attribute you define as a wiki_column, will also get &lt;a href="http://textism.com/tools/textile/"&gt;textile&lt;/a&gt; formatting automatically, for this reason &lt;a href="http://code.google.com/p/wiki-column/"&gt;wiki_column&lt;/a&gt; requires the &lt;a href="http://whytheluckystiff.net/ruby/redcloth/"&gt;RedCloth&lt;/a&gt; gem.

&lt;h1&gt;How to install it&lt;/h1&gt;

Let's assume you want to add a wiki to your Rails app (why else would you be here?). Let's also assume that you have a Product model that has a description attribute that would like wiki enabled. Given those assumptions, we'll start at the beginning. First install the &lt;a href="http://whytheluckystiff.net/ruby/redcloth/"&gt;RedCloth&lt;/a&gt; gem:
&lt;pre&gt;&lt;code&gt;sudo gem install RedCloth&lt;/code&gt;&lt;/pre&gt;

Next install the &lt;a href="http://code.google.com/p/wiki-column/"&gt;wiki_column&lt;/a&gt; plugin.
&lt;pre&gt;&lt;code&gt;./script/plugin install http://wiki-column.googlecode.com/svn/trunk/wiki_column&lt;/code&gt;&lt;/pre&gt;

Next generate your WikiPage model and your Product model.
&lt;pre&gt;&lt;code&gt;./script/generate scaffold_resource WikiPage slug:string body:text created_at:datetime updated_at:datetime
./script/generate scaffold_resource Product name:string description:text price:decimal created_at:datetime updated_at:datetime&lt;/code&gt;&lt;/pre&gt;

Don't forget to migrate.
&lt;pre&gt;&lt;code&gt;rake db:migrate&lt;/code&gt;&lt;/pre&gt;

Now we add the wiki functionality to your models, and validate that our slugs are unique. In your WikiPage model, add the following lines.
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;validates_uniqueness_of &lt;span class="sy"&gt;:slug&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;wiki_column &lt;span class="sy"&gt;:body&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


Similarly, add the following line to your Product model.
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;wiki_column &lt;span class="sy"&gt;:description&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


Next we need to change the show views. &lt;a href="http://code.google.com/p/wiki-column/"&gt;wiki_column&lt;/a&gt; adds a new method to your model called wiki_#{column}. So in your show.rhtml for WikiPage, change:
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;lt;%=h &lt;span class="iv"&gt;@wiki_page&lt;/span&gt;.body &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


to
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;lt;%= &lt;span class="iv"&gt;@wiki_page&lt;/span&gt;.wiki_body &lt;span class="s"&gt;&lt;span class="dl"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


Do the same for Product descriptions so they will link directly to your new wiki.

Lastly, want our url to make sense to users. Our scaffold resource is called WikiPage, because we are adding/editing and viewing individual pages. However, to a user viewing our site, the following url would make more sense.
&lt;pre&gt;&lt;code&gt;http://company.com/wiki/1&lt;/code&gt;&lt;/pre&gt;

Thus, the last step is to add a new resource to the routes.rb file
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;map.resources &lt;span class="sy"&gt;:wiki&lt;/span&gt;, &lt;span class="sy"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;wiki_pages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


That's it, you should now have a functioning wiki and your products should integrate with it nicely.

&lt;h1&gt;How to use it&lt;/h1&gt;

Now that your application is wiki enabled, how do you make use of this new found functionality?

You already know you can use the full range of &lt;a href="http://textism.com/tools/textile/"&gt;textile&lt;/a&gt; commands, &lt;a href="http://hobix.com/textile/"&gt;they do a better job of explaining their syntax than I could.&lt;/a&gt;

What &lt;a href="http://code.google.com/p/wiki-column/"&gt;wiki_column&lt;/a&gt; adds is the ability to specify wiki words. Those wiki words should be surrounded by square braces. For example, if you wanted to link to a page with the slug ProductionInformation, your code would look like 
&lt;pre&gt;&lt;code&gt;[ProductInformation]&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;
We designed &lt;a href="http://code.google.com/p/wiki-column/"&gt;wiki_column&lt;/a&gt; to be easily integrated into new or existing Ruby on Rails applications, as well as to be easy for your customers to use. As alway your comments, critiques, suggestions, and especially patches are welcome. Please post below.
          </content>  <feedburner:origLink>http://blog.assaydepot.com/2007/10/7/instantly-add-wiki-functionality-to-your-rails-app</feedburner:origLink></entry>
</feed>
