<?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:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>RailsTips - Home</title>
  <id>tag:railstips.org,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  
  <link href="http://railstips.org/" rel="alternate" type="text/html" />
  <updated>2009-06-28T19:24:26Z</updated>
  <geo:lat>41.650672</geo:lat><geo:long>-86.160028</geo:long><link rel="self" href="http://feeds.feedburner.com/railstips" type="application/atom+xml" /><feedburner:emailServiceId>railstips</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-06-27:9131</id>
    <published>2009-06-27T16:59:00Z</published>
    <updated>2009-06-28T19:24:26Z</updated>
    <category term="database" />
    <category term="mongo" />
    <category term="mongomapper" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/c4H0HNLQ3Uw/mongomapper-the-rad-mongo-wrapper" rel="alternate" type="text/html" />
    <title>MongoMapper, The Rad Mongo Wrapper</title>
<summary type="html">&lt;p&gt;In which I formally release MongoMapper, a high level wrapper similar to ActiveRecord, but for MongoDB.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I formally release MongoMapper, a high level wrapper similar to ActiveRecord, but for MongoDB.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/jnunemaker/mongomapper/"&gt;&lt;img class="image right" src="http://static.railstips.org/images/mongomapper_logo.gif" alt="MongoMapper" /&gt;&lt;/a&gt;
A few weeks ago, I &lt;a href="http://railstips.org/2009/6/3/what-if-a-key-value-store-mated-with-a-relational-database-system"&gt;wrote about Mongo&lt;/a&gt; and how awesome it is. Towards the end of the article (and in the slideshow) I mentioned MongoMapper, a project I’ve been working on.&lt;/p&gt;


	&lt;p&gt;Over the past few weeks my buddies at &lt;a href="http://squeejee.com/"&gt;Squeejee&lt;/a&gt; and &lt;a href="http://collectiveidea.com/"&gt;Collective Idea&lt;/a&gt; have started using MongoMapper and they’ve helped me squash a few bugs and add a few features.&lt;/p&gt;


	&lt;p&gt;Despite the fact that I would call it far from finished, I’ve decided to release it in hopes that people can start playing with it, finding bugs, adding features and submitting pull requests. The documentation is sparse to none, but there are plenty of tests and the code is pretty readable, I believe.&lt;/p&gt;


	&lt;h2&gt;Installation&lt;/h2&gt;


&lt;pre&gt;&lt;code&gt;# from rubyforge
sudo gem install mongomapper
# or from github
sudo gem install jnunemaker-mongomapper&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Usage&lt;/h2&gt;


	&lt;p&gt;So how do you use this thing? It’s pretty simple. MongoMapper uses a default connection from the Ruby driver. This means if you are using Mongo on the standard port and localhost, you don’t have to give it connection information. If you aren’t, you can do it like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;MongoMapper.connection = XGen::Mongo::Driver::Mongo.new('hostname')&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Connection accepts any valid Mongo ruby driver connection. The only other setup you need to do is to tell MongoMapper what the default database is. This is pretty much the same as setting up the connection:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;MongoMapper.database = 'mydatabasename'&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;These two operations only define the default connection and database information. &lt;strong&gt;Both of these can be overridden&lt;/strong&gt; on a per model basis so that you can hook up to multiple databases on different servers.&lt;/p&gt;


	&lt;h3&gt;Include Instead of Inherit&lt;/h3&gt;


	&lt;p&gt;To create a new model, I went with the include pattern, instead of inheritance. In ActiveRecord, you would define a new model like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Person &amp;lt; ActiveRecord::Base
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In MongoMapper, you would do the following:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Person
  include MongoMapper::Document
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Just like ActiveRecord, this makes assumptions. It assumes you have a collection named people. Oh, and &lt;strong&gt;the good news is you don’t need a migration for it&lt;/strong&gt;. The first time you try to create a person document, the collection will be created automatically. Heck yeah! I mentioned that you can override the default connection and database on a per document level. If you need to do that, it would look like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Person
  include MongoMapper::Document

  connection XGen::Mongo::Driver::Mongo.new('hostname')
  database 'otherdatabase'
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Defining Keys&lt;/h3&gt;


	&lt;p&gt;Each document is made up of keys. Keys are named and type-casted so you know your data is stored in the correct format. Lets fill out our Person document a bit.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Person
  include MongoMapper::Document

  key :first_name, String
  key :last_name, String
  key :age, Integer
  key :born_at, Time
  key :active, Boolean
  key :fav_colors, Array
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now that we have defined our schema, we can create, update and delete documents.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;person = Person.create({
  :first_name =&amp;gt; 'John',
  :last_name =&amp;gt; 'Nunemaker',
  :age =&amp;gt; 27,
  :born_at =&amp;gt; Time.mktime(1981, 11, 25, 2, 30),
  :active =&amp;gt; true,
  :fav_colors =&amp;gt; %w(red green blue)
})

person.first_name = 'Johnny'
person.save

person.destroy
# or you could do this to destroy
Person.destroy(person.id)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Looks pretty familiar, eh? Where it made sense, I tried to stay close to ActiveRecord in &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;


	&lt;h3&gt;Validations&lt;/h3&gt;


	&lt;p&gt;But wait you say, how do I validate my data? Well, you can do it pretty much the same way as ActiveRecord.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Person
  include MongoMapper::Document

  key :first_name, String
  key :last_name, String
  key :age, Integer
  key :born_at, Time
  key :active, Boolean
  key :fav_colors, Array

  validates_presence_of :first_name
  validates_presence_of :last_name
  validates_numericality_of :age
  # etc, etc
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;But, if you find that a bit tedious as I do, you can use some shortcuts that I’ve added in.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Person
  include MongoMapper::Document

  key :first_name, String, :required =&amp;gt; true
  key :last_name, String, :required =&amp;gt; true
  key :age, Integer, :numeric =&amp;gt; true
  key :born_at, Time
  key :active, Boolean
  key :fav_colors, Array
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Most of the validations from Rails are supported. I still need to build in support for validates_uniqueness of and some of the options that rails supports might not be right now, but it is a good first pass.&lt;/p&gt;


	&lt;h3&gt;Callbacks&lt;/h3&gt;


	&lt;p&gt;Did you hear that? I swear I just heard someone whisper about callbacks. Umm, yeah, we got that too. The good news? I just used ActiveSupport’s callbacks so &lt;strong&gt;they are identical to Rails&lt;/strong&gt; and most of Rails defined callbacks are supported such as before_save and the like.&lt;/p&gt;


	&lt;h3&gt;Embedded Documents&lt;/h3&gt;


	&lt;p&gt;So the cool thing about Mongo is that you can embed documents in other documents. Let’s say our person has multiple addresses. To handle that, we would create an embedded address document to go along with our person document.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Address
  include MongoMapper::EmbeddedDocument

  key :address, String
  key :city,    String
  key :state,   String
  key :zip,     Integer
end

class Person
  include MongoMapper::Document

  many :addresses
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now we can add addresses to the person like so:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;person = Person.new
person.addresses &amp;lt;&amp;lt; Address.new(:city =&amp;gt; 'South Bend', :state =&amp;gt; 'IN')
person.addresses &amp;lt;&amp;lt; Address.new(:city =&amp;gt; 'Chicago', :state =&amp;gt; 'IL')
person.save&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Doing this actually saves the address right inside the person document. &lt;strong&gt;Yep, no joins&lt;/strong&gt;. Yay! Cheers resound from the heavens! You can even query for documents based on these embedded documents. For example, if you wanted to find all people that are in the city Chicago, you could do this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Person.all(:conditions =&amp;gt; {'addresses.city' =&amp;gt; 'Chicago'})&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Finding Documents&lt;/h3&gt;


	&lt;p&gt;The find &lt;span class="caps"&gt;API&lt;/span&gt; is very similar to AR as well. Below are a bunch of other examples:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Person.find(1)
Person.find(1,2,3,4)
Person.find(:first)
Person.first
Person.find(:last)
Person.last
Person.find(:all)
Person.all
Person.all(:conditions =&amp;gt; {:last_name =&amp;gt; 'Nunemaker'}, :order =&amp;gt; 'first_name')&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;For more information about how to provide criteria to find, you can see the stuff covered in the &lt;a href="http://github.com/jnunemaker/mongomapper/blob/1831798fe3b8b2aea398435a4b1ea6f29f1a63c5/test/test_finder_options.rb"&gt;finder options&lt;/a&gt;. If you need to, you can even throw custom mongo stuff into the mix and it just gets passed through to the mongo ruby driver (ie: $gt, $gte, $lt, $lte, etc.).&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;&lt;strong&gt;We take ActiveRecord for granted&lt;/strong&gt;. It really has a lot of handy features and does a pretty good job at modeling our applications. I never realized how much it does, until I decided to create MongoMapper. That said, the experience has been fun thus far and I’m excited to see what people use it for.&lt;/p&gt;


	&lt;p&gt;There is a ton more I could talk about, but frankly, this article is long enough. Rest assured that I think Mongo is cool and that &lt;strong&gt;MongoMapper is headed in the right direction, but far from complete&lt;/strong&gt;. I haven’t actually built anything with MongoMapper yet, but I will be soon. I’m sure that will lead to a lot of handy new features.&lt;/p&gt;


	&lt;p&gt;Any general discussion can happen in the comments below while they are open or over at the &lt;a href="http://groups.google.com/group/mongomapper"&gt;google group&lt;/a&gt;. If you find a bug or have a feature idea, &lt;a href="http://github.com/jnunemaker/mongomapper/issues/"&gt;create an issue&lt;/a&gt; at github.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=c4H0HNLQ3Uw:srBxXMaSxhU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=c4H0HNLQ3Uw:srBxXMaSxhU:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=c4H0HNLQ3Uw:srBxXMaSxhU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/c4H0HNLQ3Uw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/6/27/mongomapper-the-rad-mongo-wrapper</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-06-22:9129</id>
    <published>2009-06-22T22:44:00Z</published>
    <updated>2009-06-22T22:45:39Z</updated>
    <category term="javascript" />
    <category term="json" />
    <category term="jsonquery" />
    <category term="testing" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/DT1WIKIEYs8/jsonquerying-your-rails-responses" rel="alternate" type="text/html" />
    <title>JSONQuerying Your Rails Responses</title>
<summary type="html">&lt;p&gt;In which I show how to use a Ruby implementation of JSONQuery to test &lt;span class="caps"&gt;JSON&lt;/span&gt; in Rails apps.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I show how to use a Ruby implementation of JSONQuery to test &lt;span class="caps"&gt;JSON&lt;/span&gt; in Rails apps.&lt;/p&gt;
&lt;p&gt;I’m writing an application right now that is really &lt;span class="caps"&gt;JSON&lt;/span&gt; heavy. Some of the functional tests are cucumber and some of them are just rails functional tests using shoulda.&lt;/p&gt;


	&lt;p&gt;I hit a point today where I wanted to verify that the &lt;span class="caps"&gt;JSON&lt;/span&gt; getting output was generally what I want. I could have just &lt;span class="caps"&gt;JSON&lt;/span&gt; parsed the response body and compared that with what I was looking for, but a little part of me thought this might be a cool application of JSONQuery.&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;JSONQuery provides a comprehensive set of data querying tools including filtering, recursive search, sorting, mapping, range selection, and flexible expressions with wildcard string comparisons and various operators.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;The quote above is fancy and can be boiled down to “a query language for &lt;span class="caps"&gt;JSON&lt;/span&gt;”. If you want to read more about JSONPath and JSONQuery here are some posts:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.sitepen.com/blog/2008/03/17/jsonpath-support/"&gt;JSONPath Support&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.sitepen.com/blog/2008/07/16/jsonquery-data-querying-beyond-jsonpath/"&gt;JSONQuery: Data Querying Beyond JSONPath&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Finding a Ruby JSONQuery Implementation&lt;/h2&gt;


	&lt;p&gt;I knew there was a &lt;a href="http://github.com/JasonSmith/jsonquery/tree/master"&gt;JavaScript implementation&lt;/a&gt; of JSONQuery and that &lt;a href="http://blog.joncrosby.me/"&gt;Jon Crosby&lt;/a&gt; has been doing some cool stuff with it in &lt;a href="http://getcloudkit.com/"&gt;CloudKit&lt;/a&gt;, but I couldn’t find a Ruby implemenation that didn’t require &lt;a href="http://github.com/jbarnette/johnson/tree/master"&gt;johnson&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;After some googling and Github searching, I came across &lt;a href="http://github.com/jcoglan/siren/tree/master"&gt;Siren&lt;/a&gt;. Siren was pretty much what I wanted, so I started playing around with it. I &lt;a href="http://github.com/jnunemaker/siren/tree/master"&gt;forked it&lt;/a&gt;, &lt;a href="http://github.com/jnunemaker/siren/commit/78887187e1e6d963507aed8c64fbaa427f1710df"&gt;gem’d it&lt;/a&gt; and wrapped it with some shoulda goodness.&lt;/p&gt;


	&lt;p&gt;What I ended up with was pretty specific to my needs at the moment, but I post it here in hopes that it sparks some ideas.&lt;/p&gt;


	&lt;h2&gt;Bringing It All Together&lt;/h2&gt;


	&lt;p&gt;First, I added the following to my environments/test.rb file.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;config.gem 'jnunemaker-siren',
            :lib     =&amp;gt; 'siren',
            :version =&amp;gt; '0.1.1',
            :source  =&amp;gt; 'http://gems.github.com'&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Then I added the following in my test helper (actually put it in separate module and file and included it but I’m going for simplicity in this post).&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class ActiveSupport::TestCase
  def self.should_query_json(expression, string_or_regex)
    should "have json response matching #{expression}" do
      assert_jsonquery expression, string_or_regex
    end
  end

  def assert_jsonquery(expression, string_or_regex)
    json = ActiveSupport::JSON.decode(@response.body)
    query = Siren.query(expression, json)

    if string_or_regex.kind_of?(Regexp)
      assert_match string_or_regex, query, "JSONQuery expression #{expression} value did not match regex" 
    else
      assert_equal string_or_regex, query, "Expression #{expression} value #{query} did not equal #{string_or_regex}" 
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The code is quick and dirty. The first thing you’ll notice is that assert_jsonquery actually uses @response.body, which means it can only be used in a controller test. I could easily expand it, but, like I said above, I just got it working for what I needed right now. The cool part is that now in my functional tests, I can do stuff like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;context "on POST to :create" do
  setup { post :create, :status =&amp;gt; {'action' =&amp;gt; 'In', 'body' =&amp;gt; 'Working on PB' }

  # ... code removed for brevity ...
  should_query_json "$['replace']['#current_status']", /Working on PB/
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That is a really basic query. Trust me you can do a heck of a lot more. Check out the &lt;a href="http://github.com/jnunemaker/siren/blob/aad4890a6449f4f8a8ecab8a10fd567450efc246/test/test_siren.rb#L69-110"&gt;Siren tests&lt;/a&gt; if you don’t believe me.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Overall, working with siren was a little rough because I wasn’t familiar with JSONQuery syntax. Also, siren  tends to return nil instead of a more helpful error message about my expression compilation failing, but I’m kind of excited to see how this works out in the long run.&lt;/p&gt;


	&lt;p&gt;What are you doing to test &lt;span class="caps"&gt;JSON&lt;/span&gt; in your apps? Does something like this seem cool or overkill? Just kind of curious.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=DT1WIKIEYs8:9UCUOVUM9JQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=DT1WIKIEYs8:9UCUOVUM9JQ:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=DT1WIKIEYs8:9UCUOVUM9JQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/DT1WIKIEYs8" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/6/22/jsonquerying-your-rails-responses</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-06-08:9114</id>
    <published>2009-06-08T18:31:00Z</published>
    <updated>2009-06-08T18:34:42Z</updated>
    <category term="productivity" />
    <category term="simplicity" />
    <category term="thoughts" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/JmDAfLpwwxs/what-is-the-simplest-thing-that-could-possibly-work" rel="alternate" type="text/html" />
    <title>What Is The Simplest Thing That Could Possibly Work?</title>
<summary type="html">&lt;p&gt;In which I summarize my favorite points from an old, but awesome article.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I summarize my favorite points from an old, but awesome article.&lt;/p&gt;
&lt;p&gt;I am always amazed when I read an article from 2004 and find interesting goodies. I’m probably late to the game on a lot of these articles, as I didn’t really dive into programming as a career until 2005, but I just read &lt;a href="http://www.artima.com/intv/simplestP.html"&gt;The Simplest Thing that Could Possibly Work&lt;/a&gt;, a conversation with Ward Cunningham by Bill Venners. The article was published on January 19, 2004, but it is truly timeless.&lt;/p&gt;


	&lt;h2&gt;The Shortest Path&lt;/h2&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Simplicity is the shortest path to a solution.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;“Shortest” doesn’t necessarily refer to lines of code or number of characters, but I see it more as the path that requires &lt;strong&gt;the least amount of complexity&lt;/strong&gt;. As he mentions in the article, if someone releases a 20 page proof to a math problem and then later on, someone releases a 10 page proof for the same problem, the 10 page proof is not necessarily more simple.&lt;/p&gt;


	&lt;p&gt;The 10 page proof could use some form of mathematics that is not widely used in the community and takes some time to comprehend. This means the 10 page version could be less simple as it requires learning to understand,  whereas the 20 page uses generally understood concepts.&lt;/p&gt;


	&lt;p&gt;I think this is a balance that we always fight with as programmers. What is simple? I can usually say simple or not simple when I look at code, but it is &lt;strong&gt;hard to define the rules for simplicity&lt;/strong&gt;.&lt;/p&gt;


	&lt;h2&gt;Work Today Makes You Better Tomorrow&lt;/h2&gt;


	&lt;blockquote&gt;
		&lt;p&gt;The effort you expend today to understand the code will make you a more powerful programmer tomorrow.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;This is one of the concepts that has made the biggest different in my programming knowledge over the past few years. The first time that I really did this was when I wrote about &lt;a href="http://railstips.org/2006/11/18/class-and-instance-variables-in-ruby"&gt;class and instance variables&lt;/a&gt; a few years back. Ever since then, when I come across something that I don’t understand, that I feel I should, I spend the time to understand it. I have grown immensely because of this and would recommend that you do the same if you aren’t already.&lt;/p&gt;


	&lt;h2&gt;Narrow What You Think About&lt;/h2&gt;


	&lt;blockquote&gt;
		&lt;p&gt;We had been thinking about too much at once, trying to achieve too complicated a goal, trying to code it too well.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;This is something that I have been practicing a lot lately. You know how sometimes you just feel overwhelmed and don’t want to start a feature or project? What I’ve found is that when I feel this way it is because I’m trying to think about too much at once.&lt;/p&gt;


	&lt;p&gt;Ward encourages over and over in the article, think about what is the most simple &lt;strong&gt;possible&lt;/strong&gt; thing that could work. Notice he did not say what is the simplest thing that &lt;strong&gt;would&lt;/strong&gt; work, but rather what &lt;strong&gt;could&lt;/strong&gt; work.&lt;/p&gt;


	&lt;p&gt;This is something that I’ve noticed recently while pairing with &lt;a href="http://opensoul.org"&gt;Brandon Keepers&lt;/a&gt;. Both of us almost apologize for some of the code we first implement, as we are afraid the other will think that is all we are capable of. What is funny, is that we both realize that you have to start with &lt;strong&gt;something&lt;/strong&gt; and thus never judge. It is far easier to incrementally work towards a brilliant solution than to think it in your head and instantly code it.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Start with a test. Make the test pass. Rinse and repeat.&lt;/strong&gt; Small, tested changes that solve only the immediate problem at hand always end up with a more simple solution than trying to do it all in one fell swoop. I’ve also found I’m more productive this way as I have less moments of wondering what to do next. The failing test tells me.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Anyway&lt;/strong&gt;, I thought the article was interesting enough that I would post some of the highlights here and encourage you all to read it. If you know of some oldie, but goodie articles, link them up in the comments below.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=JmDAfLpwwxs:0euBBmbNz0Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=JmDAfLpwwxs:0euBBmbNz0Y:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=JmDAfLpwwxs:0euBBmbNz0Y:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/JmDAfLpwwxs" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/6/8/what-is-the-simplest-thing-that-could-possibly-work</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-06-03:9100</id>
    <published>2009-06-03T16:22:00Z</published>
    <updated>2009-06-03T17:48:21Z</updated>
    <category term="database" />
    <category term="mongo" />
    <category term="mongomapper" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/AnkA1kCzxpE/what-if-a-key-value-store-mated-with-a-relational-database-system" rel="alternate" type="text/html" />
    <title>What If A Key/Value Store Mated With A Relational Database System?</title>
<summary type="html">&lt;p&gt;In which I provide an intro to MongoDB and it’s awesomeness.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I provide an intro to MongoDB and it’s awesomeness.&lt;/p&gt;
&lt;p&gt;Last night, the folks from the Grand Rapids ruby group were kind enough to allow me to present on &lt;a href="http://www.mongodb.org"&gt;MongoDB&lt;/a&gt;. The talk went great. I’ve been excited about Mongo for a couple weeks now, so it was cool to see that it wasn’t just me.&lt;/p&gt;


	&lt;p&gt;The funny thing is, at nearly the same time, Wynn Netherland &lt;a href="http://locomotivation.squeejee.com/post/117119353/mongodb-ruby-friendly-document-storage-that-doesnt-rhyme"&gt;presented on MongoDB&lt;/a&gt; to the Dallas ruby group. We discovered that he wrote part 1 and I wrote part 2 of the presentation despite not working together on it so we ended up showing each other’s slides as well.&lt;/p&gt;


	&lt;p&gt;I figured since I spent the time to throw some slides together, I might as well put an intro up here too. First, the slides (they probably won’t mean a lot as they were mostly outlines for me to speak from).&lt;/p&gt;


&lt;div&gt;&amp;lt;object height="355" width="425"&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongodbgrandrapids-090603001046-phpapp01&amp;amp;#38;stripped_title=mongodb-grand-rapids-rug" height="355" width="425"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;&lt;/div&gt;

	&lt;h2&gt;Intro to MongoDB&lt;/h2&gt;


	&lt;p&gt;Ok, so what the crap is Mongo? I find the best way to describe Mongo is the best features of key/values stores, document databases and &lt;span class="caps"&gt;RDBMS&lt;/span&gt; in one. No way, you say. That sounds perfect. Well, Mongo is not perfect, but I think it brings something kind of new to the database table.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Mongo is built for &lt;a href="http://bcbio.wordpress.com/2009/05/10/evaluating-key-value-and-document-stores-for-short-read-data/"&gt;speed&lt;/a&gt;&lt;/strong&gt;. Anything that would slow it down (aka transactions) have been left on the chopping block. Instead of &lt;span class="caps"&gt;REST&lt;/span&gt;, they chose sockets and have written drivers for several languages (of course one for Ruby).&lt;/p&gt;


	&lt;h2&gt;Collections&lt;/h2&gt;


	&lt;p&gt;It is collection/document oriented. &lt;strong&gt;Collections are like tables&lt;/strong&gt; in MySQL (they are even grouped in databases) and serve the purpose of breaking up the top level entities in your application (User, Article, Account, etc.) by type and thus into smaller query sets, to make queries faster.&lt;/p&gt;


	&lt;h2&gt;Documents&lt;/h2&gt;


	&lt;p&gt;&lt;strong&gt;Inside of each collection, you store documents&lt;/strong&gt;. Documents are basically objects that have no schema. The lack of schema may be scary to some, but I look at it this way. You have to know your application schema at the app level, so why put the schema in the database and in your app. Why not just put the schema in your app and have the database store whatever you put in it? This way, you database schema is kind of versioned with your application code. I think that is pretty cool.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Documents are stored in &lt;span class="caps"&gt;BSON&lt;/span&gt;&lt;/strong&gt; (&lt;a href="http://blog.mongodb.org/post/114440717/bson"&gt;blog post&lt;/a&gt;), which is binary encoded &lt;span class="caps"&gt;JSON&lt;/span&gt; that is built to be more efficient and also to include a few more data types than &lt;span class="caps"&gt;JSON&lt;/span&gt;. This means that if you send Mongo a document that has values of different types, such as String, Integer, Date, Array, Hash, etc., Mongo knows exactly how to deal with those types and actually stores them in the database as that type. This differs from traditional key/value stores, which just give you a key and a string value and leave you to handle serialization yourself.&lt;/p&gt;


	&lt;h2&gt;Object Relationships&lt;/h2&gt;


	&lt;p&gt;&lt;strong&gt;There are two ways to relate documents in Mongo&lt;/strong&gt;. The first, is to simply embed a document into another document. An example of this would be tags embedded in article. Let’s take a look.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;{
  title: 'Mongolicious', 
  body: 'I could teach you, but I would have to charge...', 
  tags: ['mongo', 'databases', 'awesome']
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you can see, tags are just a key in the article document. The benefits of this are that you never have to do any joins when you show the article and it’s tags as they are all stored in the same place. The other cool thing is that Mongo can index the tags and understand indexing keys that have multiple values (such as arrays and hashes). This means if you index tags, you can find all documents tagged with ‘foo’ and it will be performant. Embedded documents work great for some things, but other things wouldn’t make sense embedded.&lt;/p&gt;


	&lt;p&gt;Let’s imagine that you have an client document and you want the client to have multiple contacts. If you embedded the contacts for the client with it in a document, it would be inefficient to have a page that listed all the contacts. To have a contact list, you would have to pull out every client and collect all the contacts and then sort them. Also, if a contact should be associated with multiple clients, you would have to duplicate their information for each client.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;In &lt;span class="caps"&gt;SQL&lt;/span&gt;&lt;/strong&gt;, you would have a clients table and a contacts table and then a join model between them so that any contact would be in the system once and could be associated with one or more clients without duplicate. So how would you do this in Mongo? The same way…kind of.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;In Mongo&lt;/strong&gt;, you’d have a client collection and a contact collection. To associate a contact to a client, you just create a &lt;a href="http://www.mongodb.org/display/DOCS/Schema+Design"&gt;db reference&lt;/a&gt; to to the contact from the client.&lt;/p&gt;


	&lt;h2&gt;Dynamic Queries&lt;/h2&gt;


	&lt;p&gt;Yep, Mongo has dynamic queries. It actually has a kind of quirky, yet lovable syntax for defining criteria. Below are a few examples from my presentation which are mostly self-explanatory. These are examples of what you would run in Mongo’s JavaScript shell.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;# finds all Johns
db.collection.find({‘first_name’: ‘John’})

# finds all documents with first_name 
# starting with J using a regex
db.collection.find({‘first_name’: /^J/}) 

# finds first with _id of 1
db.collection.find_first({‘_id’:1})

# finds possible drinkers (age &amp;gt; 21)
db.collection.find({‘age’: {‘$gt’: 21}})

# searches in embedded document author for 
# author that has first name of John
db.collection.find({‘author.first_name’:‘John’})

# worse case scenario, or if you need "or" 
# queries you can drop down to JavaScript
db.collection.find({$where:‘this.age &amp;gt;= 6 &amp;&amp; this.age &amp;lt;= 18’})&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;You can also sort by one or more keys, limit the number of results, offset a number of results (for pagination), and define which keys you want to select. The other thing that is slick is Mongo supports count and group. &lt;a href="http://www.mongodb.org/display/DOCS/Aggregation"&gt;Count&lt;/a&gt; is the same idea as MySQL’s count. It returns the number of documents that match provided criteria. &lt;a href="http://www.mongodb.org/display/DOCS/Aggregation"&gt;Group&lt;/a&gt; is the same concept, but is accomplished with map/reduce.&lt;/p&gt;


	&lt;p&gt;To really get a feel for all that you can do with queries, check out Mongo’s &lt;a href="http://www.mongodb.org/display/DOCS/Advanced+Queries"&gt;advanced query documentation&lt;/a&gt;.&lt;/p&gt;


	&lt;h2&gt;Random Awesomeness&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Capped+Collections"&gt;Capped collections&lt;/a&gt; (&lt;a href="http://blog.mongodb.org/post/116405435/capped-collections"&gt;blog post&lt;/a&gt;): Think memcache. You can set a limit for a collection to a certain number of documents or size of space. When the number or size goes over limit the old document gets pushed out. For more info, see &lt;a href="http://www.10gen.com/blog/2009/2/mongo-db-and-caching"&gt;MongoDB and Caching&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Updates"&gt;Upserts&lt;/a&gt;: Think find or create in one call. You provide criteria and the document details and Mongo determines if the document exists or not and either inserts or updates it. You can also do special things like incrementers with $inc. For more, read &lt;a href="http://www.10gen.com/blog/2009/3/using-mongo-for-real-time-analytics"&gt;Using mongo for real time analytics&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Multikeys"&gt;Multikeys&lt;/a&gt;: for indexing arrays of keys. Think tagging.&lt;/li&gt;
		&lt;li&gt;GridFS and &lt;a href="http://www.10gen.com/wiki/info.sharding"&gt;auto-sharding&lt;/a&gt;: Storing files in the database in a way that doesn’t suck. They have mentioned in &lt;a href="irc://irc.freenode.net/#mongodb"&gt;&lt;span class="caps"&gt;IRC&lt;/span&gt;&lt;/a&gt; that they might even make Apache/Nginx modules that server files straight from GridFS so requests can go straight from web server to Mongo instead of traveling through your app server. For more, read &lt;a href="http://www.10gen.com/blog/2008/7/you-don-t-need-a-file-system"&gt;You don’t need a file system&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;How do I use it with Ruby?&lt;/h2&gt;


	&lt;p&gt;If you have made it this far, you are probably intrigued and are wondering how you can use Mongo with Ruby. There is an official &lt;a href="http://github.com/mongodb/mongo-ruby-driver/tree/master"&gt;mongo-ruby-driver&lt;/a&gt; on GitHub for starters. It supports most of Mongo’s features, if not all, and gets the job done, but it is really low level. It would be like writing an application using the MySQL gem. You can do it, but it won’t be fun. I’ve even started &lt;a href="http://github.com/mongodb/mongo-ruby-driver/commit/f73b76e5e750a5b2857c8f8ff65d3a782697e3f4"&gt;giving back&lt;/a&gt; to the driver.&lt;/p&gt;


	&lt;p&gt;There are two “ORM’s” for Mongo and both are on GitHub. The first is an &lt;a href="http://github.com/mongodb/activerecord-mongo-adapter/tree/master"&gt;ActiveRecord adapter&lt;/a&gt; and the second is &lt;a href="http://github.com/mongodb/mongo-activerecord-ruby/tree/master"&gt;MongoRecord&lt;/a&gt;. I took a look at both of these, and decided to write my own. Why?&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Mongo is not a &lt;span class="caps"&gt;RDBMS&lt;/span&gt; (like MySQL) so why use &lt;span class="caps"&gt;RDBMS&lt;/span&gt; wrappers (like the AR adapter)?&lt;/li&gt;
		&lt;li&gt;I think the &lt;span class="caps"&gt;DSL&lt;/span&gt; for modeling your application should teach you Mongo.&lt;/li&gt;
		&lt;li&gt;Mongo is perfect for the &lt;a href="http://orderedlist.com/tags/harmony"&gt;website management system&lt;/a&gt; I’m building and I just didn’t like the other wrappers. Why would I want to build something with something that I didn’t like?&lt;/li&gt;
		&lt;li&gt;It sounded fun!&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;MongoMapper&lt;/h2&gt;


	&lt;p&gt;I started the Friday of Memorial weekend and was able to crank out most of the functionality. Since then, I’ve been working on it whenever I get time and it is really close to being ready for a first release. That said, it is not public yet. Don’t worry, as soon as it is ready for prime time, I’ll be posting more here. So what features does MongoMapper have built in?&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Typecasting&lt;/li&gt;
		&lt;li&gt;Callbacks (uses ActiveSupport callbacks)&lt;/li&gt;
		&lt;li&gt;Validations (uses &lt;a href="http://github.com/jnunemaker/validatable/"&gt;my fork&lt;/a&gt; of validatable)&lt;/li&gt;
		&lt;li&gt;Connection and database can differ per document&lt;/li&gt;
		&lt;li&gt;Create, update, delete, delete_all, destroy, destroy_all that work just like ActiveRecord&lt;/li&gt;
		&lt;li&gt;Find with id, multiple ids, :all, :first, :last, etc. Also supports Mongo specific find critieria like $gt, $lt, $in, $nin, etc.&lt;/li&gt;
		&lt;li&gt;Associations&lt;/li&gt;
		&lt;li&gt;Drop in Rails compatibility&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So out of the features listed above, &lt;strong&gt;all are complete but the last two&lt;/strong&gt; at the time of this post. I’m currently working through associations and then I’m going to start making a Rails app with MongoMapper to figure out what I need for “drop in and forget” Rails compatibility. I have a few other smart people helping me so my guess is that it will be out in the next two weeks.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Let me know with a comment below what you like and don’t like about Mongo&lt;/strong&gt;. I’m very curious what other Rails developers think after reading this intro and the articles I’ve linked to. I’m stoked, but I’m sure it is not for everyone.&lt;/p&gt;


	&lt;h2&gt;Links&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://twitter.com/mongodb"&gt;MongoDB on Twitter&lt;/a&gt; (I also follow a &lt;a href="http://search.twitter.com/search?q=mongodb"&gt;search&lt;/a&gt;)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://blog.mongodb.org/"&gt;MongoDB Blog&lt;/a&gt; Brand new and some good stuff is showing up.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.10gen.com/blog/"&gt;10Gen Blog&lt;/a&gt; Lots of good articles on mongo.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Downloads"&gt;MongoDB Downloads&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://groups.google.com/group/mongodb-user"&gt;Google Group&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=AnkA1kCzxpE:0Y4-YVq92W0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=AnkA1kCzxpE:0Y4-YVq92W0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=AnkA1kCzxpE:0Y4-YVq92W0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/AnkA1kCzxpE" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/6/3/what-if-a-key-value-store-mated-with-a-relational-database-system</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-05-18:9088</id>
    <published>2009-05-18T22:11:00Z</published>
    <updated>2009-05-18T22:12:49Z</updated>
    <category term="gems" />
    <category term="httparty" />
    <category term="twitter" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/YJL3t-Vlr9k/swine-flu-and-the-twitter-gem" rel="alternate" type="text/html" />
    <title>Swine Flu and the Twitter Gem</title>
<summary type="html">&lt;p&gt;In which I wax poetic about the trendy new addition to the Twitter gem.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I wax poetic about the trendy new addition to the Twitter gem.&lt;/p&gt;
&lt;p&gt;I had some extra time today and I’ve been spotty on open source work over the past few weeks, so I decided to add support for the Twitter trends &lt;span class="caps"&gt;API&lt;/span&gt; to my &lt;a href="http://railstips.org/2009/4/5/twitter-gem-reborn-with-fewer-features-and-100-more-oauth"&gt;Twitter gem&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Using &lt;a href="http://railstips.org/2008/7/29/it-s-an-httparty-and-everyone-is-invited"&gt;HTTParty&lt;/a&gt;, the code for this turned out to be insanely simple, so short, in fact, that I’ll just put it inline here so you don’t even have to &lt;a href="http://github.com/jnunemaker/twitter/blob/19000eae773da4cdb76ef8b324d7c86ed45f3b0c/lib/twitter/trends.rb"&gt;go over&lt;/a&gt; to Github. Aww, I’m so nice.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module Twitter
  class Trends
    include HTTParty
    base_uri 'search.twitter.com/trends'
    format :json

    # :exclude =&amp;gt; 'hashtags' to exclude hashtags
    def self.current(options={})
      mashup(get('/current.json', :query =&amp;gt; options))
    end

    # :exclude =&amp;gt; 'hashtags' to exclude hashtags
    # :date =&amp;gt; yyyy-mm-dd for specific date
    def self.daily(options={})
      mashup(get('/daily.json', :query =&amp;gt; options))
    end

    # :exclude =&amp;gt; 'hashtags' to exclude hashtags
    # :date =&amp;gt; yyyy-mm-dd for specific date
    def self.weekly(options={})
      mashup(get('/weekly.json', :query =&amp;gt; options))
    end

    private
      def self.mashup(response)
        response['trends'].values.flatten.map { |t| Mash.new(t) }
      end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Pure &lt;span class="caps"&gt;TDD&lt;/span&gt;&lt;/h2&gt;


	&lt;p&gt;I am most definitely a tester, but I’ll admit I usually write code and then write the test. Of late, I’ve been reversing this trend and actually practicing &lt;span class="caps"&gt;TDD&lt;/span&gt; in full force by writing a small test, then only enough code to make it pass, followed by another test or more code for the existing test, finished with just enough code to make the new addition pass.&lt;/p&gt;


	&lt;p&gt;It is a different mindset to code in this way, compared to my code first and then make sure my butt is covered method and I’ve loving it. I thought I would find pure &lt;span class="caps"&gt;TDD&lt;/span&gt; tedious, but on the contrary, &lt;strong&gt;I think I’m coding faster and cleaner&lt;/strong&gt;.&lt;/p&gt;


	&lt;h2&gt;The Tests&lt;/h2&gt;


	&lt;p&gt;So how did I test the code above? Again, inline for your viewing pleasure, are the tests I added to make sure I don’t break something in the future and get yelled at. Feel free to take a gander and I’ll meet back up with you at the bottom of it.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;require File.dirname(__FILE__) + '/../test_helper'

class TrendsTest &amp;lt; Test::Unit::TestCase
  include Twitter

  context "Getting current trends" do
    should "work" do
      stub_get('http://search.twitter.com:80/trends/current.json', 'trends_current.json')
      trends = Trends.current
      trends.size.should == 10
      trends[0].name.should == '#musicmonday'
      trends[0].query.should == '#musicmonday'
      trends[1].name.should == '#newdivide'
      trends[1].query.should == '#newdivide'
    end

    should "be able to exclude hashtags" do
      stub_get('http://search.twitter.com:80/trends/current.json?exclude=hashtags', 'trends_current_exclude.json')
      trends = Trends.current(:exclude =&amp;gt; 'hashtags')
      trends.size.should == 10
      trends[0].name.should == 'New Divide'
      trends[0].query.should == %Q(\"New Divide\")
      trends[1].name.should == 'Star Trek'
      trends[1].query.should == %Q(\"Star Trek\")
    end
  end

  context "Getting daily trends" do
    should "work" do
      stub_get('http://search.twitter.com:80/trends/daily.json?', 'trends_daily.json')
      trends = Trends.daily
      trends.size.should == 480
      trends[0].name.should == '#3turnoffwords'
      trends[0].query.should == '#3turnoffwords'
    end

    should "be able to exclude hastags" do
      stub_get('http://search.twitter.com:80/trends/daily.json?exclude=hashtags', 'trends_daily_exclude.json')
      trends = Trends.daily(:exclude =&amp;gt; 'hashtags')
      trends.size.should == 480
      trends[0].name.should == 'Star Trek'
      trends[0].query.should == %Q(\"Star Trek\")
    end

    should "be able to get for specific date (with date string)" do
      stub_get 'http://search.twitter.com:80/trends/daily.json?date=2009-05-01', 'trends_daily_date.json'
      trends = Trends.daily(:date =&amp;gt; '2009-05-01')
      trends.size.should == 440
      trends[0].name.should == 'Swine Flu'
      trends[0].query.should == %Q(\"Swine Flu\")
    end

    should "be able to get for specific date (with date object)" do
      stub_get 'http://search.twitter.com:80/trends/daily.json?date=2009-05-01', 'trends_daily_date.json'
      trends = Trends.daily(:date =&amp;gt; Date.new(2009, 5, 1))
      trends.size.should == 440
      trends[0].name.should == 'Swine Flu'
      trends[0].query.should == %Q(\"Swine Flu\")
    end
  end

  context "Getting weekly trends" do
    should "work" do
      stub_get('http://search.twitter.com:80/trends/weekly.json?', 'trends_weekly.json')
      trends = Trends.weekly
      trends.size.should == 210
      trends[0].name.should == 'Happy Mothers Day'
      trends[0].query.should == %Q(\"Happy Mothers Day\" OR \"Mothers Day\")
    end

    should "be able to exclude hastags" do
      stub_get('http://search.twitter.com:80/trends/weekly.json?exclude=hashtags', 'trends_weekly_exclude.json')
      trends = Trends.weekly(:exclude =&amp;gt; 'hashtags')
      trends.size.should == 210
      trends[0].name.should == 'Happy Mothers Day'
      trends[0].query.should == %Q(\"Happy Mothers Day\" OR \"Mothers Day\")
    end

    should "be able to get for specific date (with date string)" do
      stub_get 'http://search.twitter.com:80/trends/weekly.json?date=2009-05-01', 'trends_weekly_date.json'
      trends = Trends.weekly(:date =&amp;gt; '2009-05-01')
      trends.size.should == 210
      trends[0].name.should == 'TGIF'
      trends[0].query.should == 'TGIF'
    end

    should "be able to get for specific date (with date object)" do
      stub_get 'http://search.twitter.com:80/trends/weekly.json?date=2009-05-01', 'trends_weekly_date.json'
      trends = Trends.weekly(:date =&amp;gt; Date.new(2009, 5, 1))
      trends.size.should == 210
      trends[0].name.should == 'TGIF'
      trends[0].query.should == 'TGIF'
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So, yeah, nothing earth shattering. It feels a bit repetitive, but I don’t mind some amount of repetition in my tests. The fixture files were created quite simply using curl.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;cd test/fixtures
curl http://search.twitter.com:80/trends/weekly.json?date=2009-05-01 &amp;gt; trends_weekly_date.json
# rinse and repeat for each file&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The stub_get method is a simple wrapper around &lt;a href="http://fakeweb.rubyforge.org/"&gt;FakeWeb&lt;/a&gt; and looks something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;def stub_get(url, filename, status=nil)
  options = {:string =&amp;gt; fixture_file(filename)}
  options.merge!({:status =&amp;gt; status}) unless status.nil?
  FakeWeb.register_uri(:get, url, options)
end

def fixture_file(filename)
  file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
  File.read(file_path)
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I’m lazy and find that stub_get is much shorter than FakeWeb.register_uri blah, blah, blah. The tests use FakeWeb, &lt;a href="http://railstips.org/2009/2/21/shoulda-looked-at-it-sooner"&gt;shoulda&lt;/a&gt; and &lt;a href="http://railstips.org/2009/3/24/custom-matchers-for-matchy"&gt;my fork&lt;/a&gt; of matchy, in case you are curious.&lt;/p&gt;


	&lt;h2&gt;Example Uses&lt;/h2&gt;


	&lt;p&gt;So what can you do with the new trends addition? Below are some examples of how you can obtain trend information.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Twitter::Trends.current
Twitter::Trends.current(:exclude =&amp;gt; 'hashtags')

Twitter::Trends.daily # current day
Twitter::Trends.daily(:exclude =&amp;gt; 'hashtags')
Twitter::Trends.daily(:date =&amp;gt; Date.new(2009, 5, 1))

Twitter::Trends.weekly # current day
Twitter::Trends.weekly(:exclude =&amp;gt; 'hashtags')
Twitter::Trends.weekly(:date =&amp;gt; Date.new(2009, 5, 1))&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That’s all for now. Enjoy the new trends and build something cool. Oh, and if you want to play with trends, but don’t have an idea, I have one and most likely won’t have time to build it. I’d be happy to collaborate.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=YJL3t-Vlr9k:NVjHdvo4iAI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=YJL3t-Vlr9k:NVjHdvo4iAI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=YJL3t-Vlr9k:NVjHdvo4iAI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/YJL3t-Vlr9k" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/5/18/swine-flu-and-the-twitter-gem</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-05-15:9046</id>
    <published>2009-05-15T05:13:00Z</published>
    <updated>2009-05-17T02:06:22Z</updated>
    <category term="beginner" />
    <category term="extend" />
    <category term="include" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/eq7ocx0aVEs/include-verse-extend-in-ruby" rel="alternate" type="text/html" />
    <title>Include vs Extend in Ruby</title>
<summary type="html">&lt;p&gt;In which I show the difference between include and extend when working with modules in Ruby.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I show the difference between include and extend when working with modules in Ruby.&lt;/p&gt;
&lt;p&gt;Now that we know the difference between &lt;a href="http://railstips.org/2009/5/11/class-and-instance-methods-in-ruby"&gt;an instance method and a class method&lt;/a&gt;, let’s cover the difference between include and extend in regards to modules. Include is for adding methods to an instance of a class and extend is for adding class methods. Let’s take a look at a small example.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module Foo
  def foo
    puts 'heyyyyoooo!'
  end
end

class Bar
  include Foo
end

Bar.new.foo # heyyyyoooo!
Bar.foo # NoMethodError: undefined method ‘foo’ for Bar:Class

class Baz
  extend Foo
end

Baz.foo # heyyyyoooo!
Baz.new.foo # NoMethodError: undefined method ‘foo’ for #&amp;lt;Baz:0x1e708&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As you can see, include makes the foo method available to an instance of a class and extend makes the foo method available to the class itself.&lt;/p&gt;


	&lt;h2&gt;Include Example&lt;/h2&gt;


	&lt;p&gt;If you want to see more examples of using include to share methods among models, you can read my article on how I &lt;a href="http://railstips.org/2009/4/20/how-to-add-simple-permissions-into-your-simple-app-also-thoughtbot-rules"&gt;added simple permissions&lt;/a&gt; to an app. The permissions module in that article is then included in a few models thus sharing the methods in it. That is all I’ll say here, so if you want to see more check out that article.&lt;/p&gt;


	&lt;h2&gt;Extend Example&lt;/h2&gt;


	&lt;p&gt;I’ve also got a simple example of using extend that I’ve plucked from the Twitter gem. Basically, Twitter supports two methods for authentication—httpauth and oauth. In order to share the maximum amount of code when using these two different authentication methods, I use a lot of delegation. Basically, the Twitter::Base class takes an instance of a “client”. A client is an instance of either Twitter::HTTPAuth or Twitter::OAuth.&lt;/p&gt;


	&lt;p&gt;Anytime a request is made from the Twitter::Base object, either get or post is called on the client. The Twitter::HTTPAuth client defines the get and post methods, but the Twitter::OAuth client does not. Twitter::OAuth is just a thin wrapper around the OAuth gem and the OAuth gem actually provides get and post methods on the access token, which automatically handles passing the OAuth information around with each request.&lt;/p&gt;


	&lt;p&gt;The implementation looks something like this (&lt;a href="http://github.com/jnunemaker/twitter/blob/9b880c4be0a43bf3ea6fd4f5ec1d6c120e6c2b11/lib/twitter/oauth.rb"&gt;full file&lt;/a&gt; on github):&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module Twitter
  class OAuth
    extend Forwardable
    def_delegators :access_token, :get, :post

    # a bunch of code removed for clarity
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Rather than define get and post, I simply delegate the get and post instance methods to the access token, which already has them defined. I do that by extending the Forwardable module onto the Twitter::OAuth class and then using the def_delegators class method that it provides. This may not be the most clear example, but it was the first that came to mind so I hope it is understandable.&lt;/p&gt;


	&lt;h2&gt;A Common Idiom&lt;/h2&gt;


	&lt;p&gt;Even though include is for adding instance methods, a common idiom you’ll see in Ruby is to use include to append both class and instance methods. The reason for this is that include has a self.included hook you can use to modify the class that is including a module and, to my knowledge, extend does not have a hook. It’s highly debatable, but often used so I figured I would mention it. Let’s look at an example.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module Foo
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def bar
      puts 'class method'
    end
  end

  def foo
    puts 'instance method'
  end
end

class Baz
  include Foo
end

Baz.bar # class method
Baz.new.foo # instance method
Baz.foo # NoMethodError: undefined method ‘foo’ for Baz:Class
Baz.new.bar # NoMethodError: undefined method ‘bar’ for #&amp;lt;Baz:0x1e3d4&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;There are a ton of projects that use this idiom, including Rails, DataMapper, &lt;a href="http://railstips.org/2008/7/29/it-s-an-httparty-and-everyone-is-invited"&gt;HTTParty&lt;/a&gt;, and &lt;a href="http://railstips.org/2008/11/17/happymapper-making-xml-fun-again"&gt;HappyMapper&lt;/a&gt;. For example, when you use HTTParty, you do something like this.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class FetchyMcfetcherson
  include HTTParty
end

FetchyMcfetcherson.get('http://foobar.com')&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;When you add the include to your class, HTTParty appends class methods, such as get, post, put, delete, base_uri, default_options and format. I think this idiom is what causes a lot of confusion in the include verse extend understanding. Because you are using include it seems like the HTTParty methods would be added to an instance of the FetchyMcfetcherson class, but they are actually added to the class itself.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Hope this helps those struggling with include verse extend. Use include for instance methods and extend for class methods. Also, it is sometimes ok to use include to add both instance and class methods. Both are really handy and allow for a great amount of code reuse. They also allow you to avoid deep inheritance, and instead just modularize code and include it where needed, which is much more the ruby way.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=eq7ocx0aVEs:s6F9awrCNdY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=eq7ocx0aVEs:s6F9awrCNdY:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=eq7ocx0aVEs:s6F9awrCNdY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/eq7ocx0aVEs" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/5/15/include-verse-extend-in-ruby</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-05-11:9045</id>
    <published>2009-05-11T19:03:00Z</published>
    <updated>2009-05-15T05:18:05Z</updated>
    <category term="beginner" />
    <category term="class" />
    <category term="instance" />
    <category term="methods" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/WP0uNQZo9Zg/class-and-instance-methods-in-ruby" rel="alternate" type="text/html" />
    <title>Class and Instance Methods in Ruby</title>
<summary type="html">&lt;p&gt;In which I show the difference between a class method and an instance method.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I show the difference between a class method and an instance method.&lt;/p&gt;
&lt;p&gt;The other day I was explaining the difference between class and instance methods to a friend and I realized that I should probably write up a post. I figured since I’m on a plane headed back home, now was as good of time as ever. If you want a little history, you can read about the difference between &lt;a href="http://railstips.org/2006/11/18/class-and-instance-variables-in-ruby"&gt;class and instance variables&lt;/a&gt;.&lt;/p&gt;


	&lt;h2&gt;One Line Summary&lt;/h2&gt;


	&lt;p&gt;Class methods are methods that are called on a class and instance methods are methods that are called on an instance of a class. Here is a quick example and then we’ll go into a bit more detail.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Foo
  def self.bar
    puts 'class method'
  end

  def baz
    puts 'instance method'
  end
end

Foo.bar # =&amp;gt; "class method" 
Foo.baz # =&amp;gt; NoMethodError: undefined method ‘baz’ for Foo:Class

Foo.new.baz # =&amp;gt; instance method
Foo.new.bar # =&amp;gt; NoMethodError: undefined method ‘bar’ for #&amp;lt;Foo:0x1e820&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;See the difference? bar is a &lt;strong&gt;class method&lt;/strong&gt;, so calling bar on the Foo class works fine. baz is an &lt;strong&gt;instance method&lt;/strong&gt;, so calling baz on the Foo class raises a NoMethodError. Then, on the next couple lines, we call both methods on an &lt;strong&gt;instance&lt;/strong&gt; of Foo (Foo.new).&lt;/p&gt;


	&lt;p&gt;Now that we have a base, let’s show a few of the ways you can create class and instance methods and examples of what they would be used for.&lt;/p&gt;


	&lt;h2&gt;Class Methods&lt;/h2&gt;


	&lt;p&gt;Ruby is very flexible and as such it allows several ways to define a class method. The following is a sample of the most commonly used ways.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;# Way 1
class Foo
  def self.bar
    puts 'class method'
  end
end

Foo.bar # "class method" 

# Way 2
class Foo
  class &amp;lt;&amp;lt; self
    def bar
      puts 'class method'
    end
  end
end

Foo.bar # "class method" 

# Way 3
class Foo; end
def Foo.bar
  puts 'class method'
end

Foo.bar # "class method"&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The first way is my preference. When I see self.method_name it is immediately apparent to me that this is a class method. A lot of people use way #2 and it is pretty heavily used in Rails.&lt;/p&gt;


	&lt;p&gt;There is nothing wrong with it, but when you have a class with a lot of class methods in a &lt;code&gt;class &amp;lt;&amp;lt; self&lt;/code&gt; block, it can be hard to tell if the method is a class or instance method because it is defined the same (&lt;code&gt;def bar&lt;/code&gt;). If this doesn’t make sense, feel free to use it for a while and you’ll probably run into what I’m talking about.&lt;/p&gt;


	&lt;p&gt;Way 3 is not that common as far as I have seen and is more often a way to quickly add methods on the fly to a class. These are not the only three ways to define class methods, but they seem to be the ones that I see the most.&lt;/p&gt;


	&lt;p&gt;So when would you use a class method? Class methods are for anything that does not deal with an individual instance of a class. ActiveRecord::Base#find is one example. If you look in ActiveRecord::Base, you’ll see something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module ActiveRecord
  class Base
    # some stuff
    class &amp;lt;&amp;lt; self
      def find(...)
        # blah
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Looks familiar, eh? Some other uses of class methods in Rails are validations and associations in ActiveRecord and before/after/around filters in ActionPack. The way this works is something like this (simplified for clarity):&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module ActiveRecord
  class Base
    def self.validates_presence_of(...)
      # make sure present
    end
  end
end

class Foo &amp;lt; ActiveRecord::Base
  validates_presence_of :bar
end&lt;/code&gt;&lt;/pre&gt; 

	&lt;p&gt;When you say validates_presence_of, the class method in AR::Base is what gets called.&lt;/p&gt;


	&lt;h2&gt;Instance Methods&lt;/h2&gt;


	&lt;p&gt;Enough about class methods, lets move on. Instance methods are a bit more simple. Here are a few common ways that instance methods are defined.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;# Way 1
class Foo
  def baz
    puts 'instance method'
  end
end

Foo.new.baz # "instance method" 

# Way 2
class Foo
  attr_accessor :baz
end

foo = Foo.new
foo.baz = 'instance method'
puts foo.baz

# Way 3
class Foo; end

foo = Foo.new
def foo.bar
  puts 'instance method'
end

Foo.new.baz # "instance method"&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The key difference is instance methods only work with an instance and thus you have to create a new instance to use them (Foo.new). Again, there are more ways to define instance methods than this, especially if you look into meta programming.&lt;/p&gt;


	&lt;p&gt;So what are some examples uses of instance methods in Rails, to give you a better idea? Ever do a find in a destroy action and then call destroy on the found instance? destroy is an instance method.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class FoosController &amp;lt; ActionController
  def destroy
    foo = Foo.find(params[:id])
    foo.destroy
    redirect_to foos_url
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So are save and update_attributes, which you have definitely used before if you’ve done any Rails.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;foo = Foo.new(:title =&amp;gt; 'Bar')
foo.save # is an instance method&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;Class methods can only be called on classes and instance methods can only be called on an instance of a class. It’s simple when you understand it, but I remember being confused when I was learning Ruby. Hope this helps. If I was unclear or incorrect at any point above, let me know.&lt;/p&gt;


	&lt;p&gt;The next article that I also wrote on the plane ride home from Railsconf is &lt;a href="http://railstips.org/2009/5/15/include-verse-extend-in-ruby"&gt;Include verse Extend&lt;/a&gt;, which builds on this article.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=WP0uNQZo9Zg:pNqrC0hrhXY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=WP0uNQZo9Zg:pNqrC0hrhXY:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=WP0uNQZo9Zg:pNqrC0hrhXY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/WP0uNQZo9Zg" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/5/11/class-and-instance-methods-in-ruby</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-05-03:9030</id>
    <published>2009-05-03T20:33:00Z</published>
    <updated>2009-05-03T20:39:11Z</updated>
    <category term="conferences" />
    <category term="railsconf" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/TgsJ6hrSLpE/railsconf-2009" rel="alternate" type="text/html" />
    <title>RailsConf 2009</title>
<summary type="html">&lt;p&gt;In which I note that I’ll be at RailsConf 2009.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I note that I’ll be at RailsConf 2009.&lt;/p&gt;
&lt;p&gt;This week is RailsConf and I decided kind of last minute to attend. Steve, the other half of &lt;a href="http://orderedlist.com"&gt;Ordered List&lt;/a&gt;, will also be there, though mostly just to hang out.&lt;/p&gt;


	&lt;p&gt;My first RailsConf was in 2007 and I blogged my little heart out (&lt;a href="http://railstips.org/2007/5/23/my-must-read-summary-of-railsconf2007"&gt;summary&lt;/a&gt;). Last year, I took a &lt;a href="http://railstips.org/2008/6/4/railsconf-2008"&gt;different approach&lt;/a&gt; and just posted a summary of the whole thing.&lt;/p&gt;


	&lt;p&gt;This year I’m going to take a different approach than the previous two. I’m planning on mostly just walking around with a moleskin and my &lt;a href="http://www.flickr.com/photos/johnnunemaker/3337835603/"&gt;new camera&lt;/a&gt;. I found the moleskin approach worked pretty well for the sessions I used it with at RubyConf &lt;a href="http://railstips.org/2008/11/11/rubyconf-wrapup"&gt;last year&lt;/a&gt;, so I’m going to give it a shot for a whole conference. I took better notes and was less distracted than if I used my computer.&lt;/p&gt;


	&lt;h2&gt;Say Hi!&lt;/h2&gt;


	&lt;p&gt;If you see me and I don’t see you, be sure to say hi. Each conference I meet more and more people and I want this one to be no different. Meeting people really is the best part of any conference. If you don’t know what I look like, here is a picture of me enjoying a blueberry dessert a la mode. I’m guessing from this you can figure out what I look like without the blueberry dessert. :)&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/oaknd1/2818279201/"&gt;&lt;img class="image" src="http://farm4.static.flickr.com/3149/2818279201_cbfbf57d2d.jpg" alt="John Nunemaker" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Don’t worry, though I look angry in the picture, I am actually blissfully happy. Also, I spend about 95% of the time with a smile on my face.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=TgsJ6hrSLpE:jdojNp4nnNo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=TgsJ6hrSLpE:jdojNp4nnNo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=TgsJ6hrSLpE:jdojNp4nnNo:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/TgsJ6hrSLpE" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/5/3/railsconf-2009</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-04-24:9008</id>
    <published>2009-04-24T02:57:00Z</published>
    <updated>2009-04-24T02:57:58Z</updated>
    <category term="news" />
    <category term="site updates" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/jEljDwQFt8E/now-with-navigation-and-charted-archives" rel="alternate" type="text/html" />
    <title>Now With Navigation and Charted Archives</title>
<summary type="html">&lt;p&gt;In which I discuss some recent updates to the site.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I discuss some recent updates to the site.&lt;/p&gt;
&lt;p&gt;Every couple weeks, I sit down and try to think of things that will make this site better. Rather than post each time I come up with something, I typically wait until I have a few to share and then post about it. This is another one of those posts.&lt;/p&gt;


	&lt;h2&gt;Charted Archives&lt;/h2&gt;


	&lt;p&gt;A few weeks ago, I thought it would be cool to show my archives by month in a bar chart. My thought process was that someone new to the site could see the graph and very easily get a feel for the frequency of my posting. Below is a little screenshot for archival purposes and those in a feed reader. You can also just scroll towards the bottom of any page to see it live.&lt;/p&gt;


	&lt;p&gt;&lt;img class="image" src="http://static.railstips.org/images/articles/archives.jpg" alt="Archives" /&gt;&lt;/p&gt;


	&lt;h2&gt;Navigation and Search&lt;/h2&gt;


	&lt;p&gt;I’ve always put a lot of emphasis &lt;a href="http://railstips.org/2009/1/3/look-at-the-size-of-my-footer"&gt;on my footer&lt;/a&gt;. From there you can get to pretty much anywhere on the site, but I thought it was high time that I finally put some navigation at the top. Then I thought, while I was at it, I might as well add some new content, so there are now two new pages to peruse.&lt;/p&gt;


	&lt;p&gt;The first page is dedicated to all my &lt;a href="http://railstips.org/projects/"&gt;projects&lt;/a&gt;. It lists those that I care about, along with a little history and such. I think sometimes our Github profiles and a websites get too disconnected, so I think this will help connect the two a bit.&lt;/p&gt;


	&lt;p&gt;The second page I am simply referring to as “dude”: http://railstips.org/dude/. Whenever I find something new and fall in love with it, I’m always telling my friends, “Dude, you have to check this out.” That theory along with the success of my &lt;a href="http://railstips.org/2009/1/5/my-setup-and-software"&gt;setup and software&lt;/a&gt; post, led me to believe I should have a page here at RailsTips dedicated solely to the things that make me say “dude!”.&lt;/p&gt;


	&lt;p&gt;The other tweak I did is I moved the search box to the top of the page from the sidebar. The reason for the move is that I think the search box is easily overlooked in the sidebar, but should do fine up at the top. It also helps balance the content above the navigation a bit.&lt;/p&gt;


	&lt;p&gt;Again, for archival purposes, I’m including a picture of the nav and search tweaks.&lt;/p&gt;


	&lt;p&gt;&lt;img class="image" src="http://static.railstips.org/images/articles/nav_search.jpg" alt="Navigation and Search" /&gt;&lt;/p&gt;


	&lt;p&gt;The only other addition worth noting is that I’ve switched from sections/categories to tags for articles. More a semantic change than anything, but I thought I would mention it. One of the next tweaks I’ll do is add a tag page where you can view all the tags listed alphabetically to get an idea for the topics covered here.&lt;/p&gt;


	&lt;p&gt;That is all for now. Just thought I would mention the updates for those who read the posts from their feed reader and for those that might be new to the site. I hope they make it even easier to find and discover the content I’ve been posting.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=jEljDwQFt8E:jb-m-BjVcNI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=jEljDwQFt8E:jb-m-BjVcNI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=jEljDwQFt8E:jb-m-BjVcNI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/jEljDwQFt8E" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/4/24/now-with-navigation-and-charted-archives</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-04-20:8988</id>
    <published>2009-04-20T14:53:00Z</published>
    <updated>2009-05-18T22:17:49Z</updated>
    <category term="clearance" />
    <category term="factory girl" />
    <category term="paperclip" />
    <category term="shoulda" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/xjEXt3SRWqQ/how-to-add-simple-permissions-into-your-simple-app-also-thoughtbot-rules" rel="alternate" type="text/html" />
    <title>How to Add Simple Permissions into Your Simple App. Also, Thoughtbot Rules!</title>
<summary type="html">&lt;p&gt;In which I discuss how I added simple permissions into flightcontrolled.com an app I created and how cool clearance, shoulda, factory girl and paperclip are.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I discuss how I added simple permissions into flightcontrolled.com an app I created and how cool clearance, shoulda, factory girl and paperclip are.&lt;/p&gt;
&lt;p&gt;Last week, in a few hours, I whipped together &lt;a href="http://flightcontrolled.com"&gt;flightcontrolled.com&lt;/a&gt; for Flight Control, a super fun iPhone game. The site allows users to upload screenshots of their high scores. I thought I would provide a few details here as some may find it interesting.&lt;/p&gt;


	&lt;p&gt;It is a pretty straightforward and simple site, but it did need a few permissions. I wanted users to be able to update their own profile, scores and photos, but not anyone else’s. On top of that, I, as an admin, should be able to update anything on the site. I’m sure there is a better way, but this is what I did and it is working just fine.&lt;/p&gt;


	&lt;h2&gt;Add admin to users&lt;/h2&gt;


	&lt;p&gt;I added an admin boolean to the users table. You may or may not know this, but Active Record adds handy boolean methods for all your columns. For example, if the user model has an email column and an admin column, you can do the following.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;user = User.new
user.email? # =&amp;gt; false
user.email = 'foobar@foobar.com'
user.email? # =&amp;gt; true

user.admin? # =&amp;gt; false
user.admin = true
user.admin? # =&amp;gt; true&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Simple permissions module&lt;/h2&gt;


	&lt;p&gt;Next up, I created a module called permissions, that looks something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module Permissions
  def changeable_by?(other_user)
    return false if other_user.nil?
    user == other_user || other_user.admin?
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I put this in app/concerns/ and added that directory to the load path, but it will work just fine in lib/.&lt;/p&gt;


	&lt;h2&gt;Mixin the permission module&lt;/h2&gt;


	&lt;p&gt;Then in the user, score and photo models, I just include that permission module.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Score &amp;lt; ActiveRecord::Base
  include Permissions
end

class Photo &amp;lt; ActiveRecord::Base
  include Permissions
end

class User &amp;lt; ActiveRecord::Base
  include Permissions
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Add checks in controllers/views&lt;/h2&gt;


	&lt;p&gt;Now, in the view I can check if a user has permission before showing the edit and delete links.&lt;/p&gt;


&lt;pre&gt;&lt;code class="erb"&gt;&amp;lt;%- if score.changeable_by?(current_user) -%&amp;gt;
  &amp;lt;li class="actions"&amp;gt;
    &amp;lt;%= link_to 'Edit', edit_score_url(score) %&amp;gt;
    &amp;lt;%= link_to 'Delete', score, :method =&amp;gt; :delete %&amp;gt;
  &amp;lt;/li&amp;gt;
&amp;lt;%- end -%&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;And in the controller, I can do the same.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class ScoresController &amp;lt; ApplicationController
  before_filter :authorize, :only =&amp;gt; [:edit, :update, :destroy]

  private
    def authorize
      unless @score.changeable_by?(current_user)
        render :text =&amp;gt; 'Unauthorized', :status =&amp;gt; :unauthorized
      end
    end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Macro for model tests&lt;/h2&gt;


	&lt;p&gt;I didn’t forget about testing either. I created a quick macro for &lt;a href="http://railstips.org/2009/2/21/shoulda-looked-at-it-sooner"&gt;shoulda&lt;/a&gt; like this (also uses factory girl and &lt;a href="http://railstips.org/2009/3/24/custom-matchers-for-matchy"&gt;matchy&lt;/a&gt;):&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class ActiveSupport::TestCase
  def self.should_have_permissions(factory)
    should "know who has permission to change it" do
      object     = Factory(factory)
      admin      = Factory(:admin)
      other_user = Factory(:user)
      object.changeable_by?(other_user).should be(false)
      object.changeable_by?(object.user).should be(true)
      object.changeable_by?(admin).should be(true)
      object.changeable_by?(nil).should be(false)
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Which I can then call from my various model tests:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class ScoreTest &amp;lt; ActiveSupport::TestCase
  should_have_permissions :score
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Looking at it now, I probably could just infer the score factory as I’m in the ScoreTest, but for whatever reason, I didn’t go that far.&lt;/p&gt;


	&lt;h2&gt;A sprinkle of controller tests&lt;/h2&gt;


	&lt;p&gt;I also did something like the following to test the controllers:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class ScoresControllerTest &amp;lt; ActionController::TestCase  
  context "A regular user" do
    setup do
      @user = Factory(:email_confirmed_user)
      sign_in_as @user
    end

    context "on GET to :edit" do
      context "for own score" do
        setup do
          @score = Factory(:score, :user =&amp;gt; @user)
          get :edit, :id =&amp;gt; @score.id
        end

        should_respond_with :success
      end

      context "for another user's score" do
        setup do
          @score = Factory(:score)
          get :edit, :id =&amp;gt; @score.id
        end

        should_respond_with :unauthorized
      end
    end
  end

  context "An admin user" do
    setup do
      @admin = Factory(:admin)
      sign_in_as @admin
    end

    context "on GET to :edit" do
      context "for own score" do
        setup do
          @score = Factory(:score, :user =&amp;gt; @admin)
          get :edit, :id =&amp;gt; @score.id
        end

        should_respond_with :success
      end

      context "for another user's score" do
        setup do
          @score = Factory(:score)
          get :edit, :id =&amp;gt; @score.id
        end

        should_respond_with :success
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Summary of Tools&lt;/h2&gt;


	&lt;p&gt;I should call &lt;a href="http://flightcontrolled.com"&gt;flightcontrolled&lt;/a&gt;, the &lt;a href="http://www.thoughtbot.com/"&gt;thoughtbot&lt;/a&gt; project as I used several of their awesome tools. I used &lt;a href="http://giantrobots.thoughtbot.com/2009/2/9/clearance-rails-authentication-for-developers-who-write-tests"&gt;clearance&lt;/a&gt; for authentication, &lt;a href="http://www.thoughtbot.com/projects/shoulda"&gt;shoulda&lt;/a&gt; and &lt;a href="http://www.thoughtbot.com/projects/factory_girl"&gt;factory girl&lt;/a&gt; for testing, and &lt;a href="http://www.thoughtbot.com/projects/paperclip"&gt;paperclip&lt;/a&gt; for file uploads. This was the first project that I used factory girl on and I really like it. Again, I didn’t get the fuss until I used it, and then I was like “Oooooh! Sweet!”.&lt;/p&gt;


	&lt;p&gt;One of the cool things about paperclip is you can pass straight up convert options to imagemagick. Flight Control is a game that is played horizontally, so I knew all screenshots would need to be rotated 270 degress. I just added the following convert options (along with strip) to the paperclip call:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;has_attached_file :image, 
  :styles =&amp;gt; {:thumb =&amp;gt; '100&amp;gt;', :full =&amp;gt; '480&amp;gt;'},
  :default_style =&amp;gt; :full,
  :convert_options =&amp;gt; {:all =&amp;gt; '-rotate 270 -strip'}&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;You don’t need some fancy plugin or a lot of code to add some basic permissions into your application. A simple module can go a long way. Also, start using Thoughtbot’s projects. I’m really impressed with the developer tools they have created thus far.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=xjEXt3SRWqQ:_wRbmPUqVMg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=xjEXt3SRWqQ:_wRbmPUqVMg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=xjEXt3SRWqQ:_wRbmPUqVMg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/xjEXt3SRWqQ" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/4/20/how-to-add-simple-permissions-into-your-simple-app-also-thoughtbot-rules</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-04-05:8974</id>
    <published>2009-04-05T18:14:00Z</published>
    <updated>2009-04-20T14:49:42Z</updated>
    <category term="clearance" />
    <category term="oauth" />
    <category term="twitter" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/gCSwkM2-whc/twitter-gem-reborn-with-fewer-features-and-100-more-oauth" rel="alternate" type="text/html" />
    <title>Twitter Gem Reborn with Fewer Features and 100% More OAuth</title>
<summary type="html">&lt;p&gt;In which I show off the rewritten Twitter gem and an example app that takes advantage of it.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I show off the rewritten Twitter gem and an example app that takes advantage of it.&lt;/p&gt;
&lt;p&gt;The Twitter gem is kind of my baby. It was pretty much the first gem I created and as such I care for it a little more. When I originally created it, I knew nothing. I sucked. Now over time, I suck less and Twitter’s addition of OAuth seemed like the perfect time to completely rewrite it. Yay for rewrites!&lt;/p&gt;


	&lt;p&gt;The gem is now leaner, meaner and works swell with OAuth. I would imagine as I use OAuth a bit more, I’ll figure out some ways to make it even easier in the twitter gem but it works for now.&lt;/p&gt;


	&lt;h2&gt;The Cuts&lt;/h2&gt;


	&lt;p&gt;One of the biggest headaches and coolest things about the Twitter gem was the command line interface. It allowed for multiple accounts and was SQLite database backed. That was cool and all but it is ridiculous to have main and active record as dependencies for someone who just wanted the &lt;span class="caps"&gt;API&lt;/span&gt; wrapping aspects of the gem.&lt;/p&gt;


	&lt;p&gt;Knowing this, I have finally killed the &lt;span class="caps"&gt;CLI&lt;/span&gt;. Fear not, &lt;span class="caps"&gt;CLI&lt;/span&gt; fans, it will make a triumphant return, but that return will be in a separate gem that merely relies on the Twitter gem. The Twitter gem itself will be only a wrapper for the &lt;span class="caps"&gt;REST&lt;/span&gt; and Search APIs that Twitter provides. No more extra cruft.&lt;/p&gt;


	&lt;h2&gt;OAuth&lt;/h2&gt;


	&lt;p&gt;As I said, the main reason for the rewrite was that Twitter now supports OAuth. I thought about it long and hard and decided to not continue support for &lt;span class="caps"&gt;HTTP&lt;/span&gt; Authentication. Twitter has not discontinued support for &lt;span class="caps"&gt;HTTP&lt;/span&gt; Authentication, but they will in the future and I didn’t want to add a bunch of hours to releasing the updated gem simply to support something that is going to be deprecated.&lt;/p&gt;


	&lt;p&gt;So how does one use the OAuth stuff in the Twitter gem? First off, &lt;a href="http://railstips.org/2009/3/29/oauth-explained-and-what-it-is-good-for"&gt;familiarize yourself with OAuth&lt;/a&gt;. Then, you can check out the example below pulled straight from the examples directory included in the gem (or &lt;a href="http://github.com/jnunemaker/twitter/blob/789aa38fb2b5ec4f2ea05c193a3ccc248bbe599d/examples/connect.rb"&gt;over here&lt;/a&gt; on github).&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
require File.join(File.dirname(__FILE__), 'helpers', 'config_store')
require 'pp'

config = ConfigStore.new("#{ENV['HOME']}/.twitter")
oauth = Twitter::OAuth.new(config['token'], config['secret'])

if config['atoken'] &amp;&amp; config['asecret']
  oauth.authorize_from_access(config['atoken'], config['asecret'])
  twitter = Twitter::Base.new(oauth)
  pp twitter.friends_timeline

elsif config['rtoken'] &amp;&amp; config['rsecret']  
  oauth.authorize_from_request(config['rtoken'], config['rsecret'])
  twitter = Twitter::Base.new(oauth)
  pp twitter.friends_timeline

  config.update({
    'atoken'  =&amp;gt; oauth.access_token.token,
    'asecret' =&amp;gt; oauth.access_token.secret,
  }).delete('rtoken', 'rsecret')
else
  config.update({
    'rtoken'  =&amp;gt; oauth.request_token.token,
    'rsecret' =&amp;gt; oauth.request_token.secret,
  })

  # authorize in browser
  %x(open #{oauth.request_token.authorize_url})
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The &lt;a href="http://github.com/jnunemaker/twitter/blob/789aa38fb2b5ec4f2ea05c193a3ccc248bbe599d/examples/helpers/config_store.rb"&gt;ConfigStore&lt;/a&gt; is a simple class that allows me to save the request and access token and secrets as I’m completing the handshakes between the script and Twitter.&lt;/p&gt;


	&lt;p&gt;As you can see, it is pretty simple. Get a request token, then use that to create an access token. From there, you can reuse the access token to authorize future requests.&lt;/p&gt;


	&lt;h2&gt;An Example App&lt;/h2&gt;


	&lt;p&gt;Now one might think, based on that previous example, “Thanks so much John! I really appreciate you getting the ball rolling for me with a simple example.” Friends do I have news for you. I didn’t stop there. I whipped together a little &lt;a href="http://github.com/jnunemaker/twitter-app/tree/master"&gt;sample app&lt;/a&gt;, that I have been using for a few days now. Eventually, it will become a full Twitter client, but for now it is pretty basic and dirty.&lt;/p&gt;


	&lt;p&gt;It uses &lt;a href="http://giantrobots.thoughtbot.com/2009/2/9/clearance-rails-authentication-for-developers-who-write-tests"&gt;Clearance&lt;/a&gt; for authentication for authentication and automatically sends you to Twitter to authorize after firing it up (if you haven’t previously). I used Rails rescue_from to automatically send you to Twitter if any of the authorization stuff gets messed up at a later point to.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;rescue_from Twitter::Unauthorized, :with =&amp;gt; :twitter_unauthorized  
private
  def twitter_unauthorized(exception)
    redirect_to new_authorization_url
  end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Anytime the Twitter gem throws the Twitter::Unauthorized exception, you are redirected to new_authorization_url, which is powered by the AuthorizationsController, which looks like this.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class AuthorizationsController &amp;lt; ApplicationController
  def new
    oauth = current_user.oauth
    session['rtoken'] = oauth.request_token.token
    session['rsecret'] = oauth.request_token.secret
    redirect_to oauth.request_token.authorize_url
  end

  def show
    oauth = current_user.oauth
    oauth.authorize_from_request(session['rtoken'], session['rsecret'])

    session['rtoken'] = nil
    session['rsecret'] = nil

    current_user.update_attributes({
      :atoken =&amp;gt; oauth.access_token.token, 
      :asecret =&amp;gt; oauth.access_token.secret,
    })

    redirect_to root_path
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The new action stores the request token and secret and then redirects you to Twitter to authorize the app. Over at Twitter, I have registered an application and set the redirect url to go to /authorization in the app, which as you can see above, obtains the access token and secret and stores them with the current user.&lt;/p&gt;


	&lt;p&gt;You’ll probably notice that I am calling current_user.oauth and current_user.client throughout the app. These are helper methods I added to the user model to shorten up what was happening in the controller.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class User &amp;lt; ActiveRecord::Base
  include Clearance::App::Models::User

  attr_accessible :atoken, :asecret

  def authorized?
    !atoken.blank? &amp;&amp; !asecret.blank?
  end

  def oauth
    @oauth ||= Twitter::OAuth.new(ConsumerConfig['token'], ConsumerConfig['secret'])
  end

  def client
    @client ||= begin
      oauth.authorize_from_access(atoken, asecret)
      Twitter::Base.new(oauth)
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I could shorten up the controllers even more (and will at some point) by delegating several methods on user to user.client. I’ll post more on that later when I get around to it. Also, at some point, I’m going to remove the atoken and asecret from the user and allow support for multiple Twitter accounts for one user in the app. This should be pretty easy, but I wanted to get something working first before I complicated things.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;From a user standpoint, OAuth is really nice. I love not having to put in my username and password. From a developer standpoint, OAuth is also pretty nice. Basically, you register your application with Twitter, provide the consumer token and key in a config file and this example app is ready to go.&lt;/p&gt;


	&lt;p&gt;As with any rewrite there are bound to be bugs. I have fixed one already that someone caught. If you catch any weird bugs using the rewritten Twitter gem, there is group and ticket information on the &lt;a href="http://twitter.rubyforge.org"&gt;Twitter gem website&lt;/a&gt;.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=gCSwkM2-whc:jArvYEA1bOU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=gCSwkM2-whc:jArvYEA1bOU:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=gCSwkM2-whc:jArvYEA1bOU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/gCSwkM2-whc" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/4/5/twitter-gem-reborn-with-fewer-features-and-100-more-oauth</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-04-01:8961</id>
    <published>2009-04-01T04:20:00Z</published>
    <updated>2009-04-03T18:38:20Z</updated>
    <category term="gems" />
    <category term="json" />
    <category term="xml" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/ZqNoNXdlIZU/crack-the-easiest-way-to-parse-xml-and-json" rel="alternate" type="text/html" />
    <title>Crack, The Easiest Way to Parse XML and JSON</title>
<summary type="html">&lt;p&gt;In which I release a new gem that allows parsing &lt;span class="caps"&gt;XML&lt;/span&gt; or &lt;span class="caps"&gt;JSON&lt;/span&gt; with a simple, consistent &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I release a new gem that allows parsing &lt;span class="caps"&gt;XML&lt;/span&gt; or &lt;span class="caps"&gt;JSON&lt;/span&gt; with a simple, consistent &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;An astute reader will remember that a while back, &lt;a href="http://railstips.org/2008/7/29/it-s-an-httparty-and-everyone-is-invited"&gt;HTTParty&lt;/a&gt; divorced both &lt;a href="http://railstips.org/2008/12/7/httparty-divorces-activesupport"&gt;ActiveSupport&lt;/a&gt; and the &lt;a href="http://railstips.org/2009/1/31/httparty-divorces-json"&gt;&lt;span class="caps"&gt;JSON&lt;/span&gt;&lt;/a&gt; gem in order to make it easier to use all around. With the &lt;span class="caps"&gt;JSON&lt;/span&gt; gem went the last gem dependency, which was kind of cool.&lt;/p&gt;


	&lt;p&gt;A few days back, it occurred to me that the parsing of &lt;span class="caps"&gt;XML&lt;/span&gt; and &lt;span class="caps"&gt;JSON&lt;/span&gt; that HTTParty used might be handy outside of HTTParty. In the spirit of sharing, I whipped together a new gem, named &lt;a href="http://github.com/jnunemaker/crack/tree/master"&gt;crack&lt;/a&gt;, that contains the &lt;span class="caps"&gt;XML&lt;/span&gt; and &lt;span class="caps"&gt;JSON&lt;/span&gt; parsers that formerly were bundled in HTTParty.&lt;/p&gt;


	&lt;h2&gt;Why Crack?&lt;/h2&gt;


	&lt;p&gt;I figured the name was easy and memorable, which is a requirement for anything I’m going to release. When I thought about parsing &lt;span class="caps"&gt;XML&lt;/span&gt; and &lt;span class="caps"&gt;JSON&lt;/span&gt;, for some reason, &lt;strong&gt;crack&lt;/strong&gt;ing the code came to mind and thus crack had a name.&lt;/p&gt;


	&lt;h2&gt;Credits&lt;/h2&gt;


	&lt;p&gt;&lt;strong&gt;First, I’d like to make it abundantly obvious that I did not author any of this code&lt;/strong&gt;. I tweaked it a bit and made sure it had tests, but the &lt;span class="caps"&gt;XML&lt;/span&gt; parsing was extracted from Merb (extlib) and the &lt;span class="caps"&gt;JSON&lt;/span&gt; parsing from Rails (ActiveSupport). &lt;strong&gt;I merely packaged them together for all to enjoy&lt;/strong&gt;. Ok, now that we have that out of the way, let’s move onward.&lt;/p&gt;


	&lt;p&gt;So I ripped the two parsers out of HTTParty and put them in their own gem and then just set that as a dependency for HTTParty. HTTParty will still work the exact same, but if all you need is a really simple way to parse &lt;span class="caps"&gt;JSON&lt;/span&gt; or &lt;span class="caps"&gt;XML&lt;/span&gt;, crack is his name and parsing is his game.&lt;/p&gt;


	&lt;h2&gt;Details&lt;/h2&gt;


	&lt;p&gt;As always these days, I used &lt;a href="http://railstips.org/2009/2/21/shoulda-looked-at-it-sooner"&gt;shoulda&lt;/a&gt; and &lt;a href="http://railstips.org/2009/3/24/custom-matchers-for-matchy"&gt;matchy&lt;/a&gt; for testing and &lt;a href="http://railstips.org/2009/3/25/building-api-wrapping-gems-could-not-get-much-easier"&gt;jeweler&lt;/a&gt; to make the gem maintenance easy. That is pretty much it for details on this project. It is focused and simple so there isn’t much behind the scenes.&lt;/p&gt;


	&lt;h2&gt;Installation&lt;/h2&gt;


	&lt;p&gt;I registered a rubyforge project, but I’m waiting for approval. For now, you can get the gem from &lt;a href="http://github.com/jnunemaker/crack/tree/master"&gt;Github&lt;/a&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;sudo gem install jnunemaker-crack -s http://gems.github.com&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Usage&lt;/h2&gt;


	&lt;p&gt;It has always slightly annoyed me that all the different &lt;a href="http://railstips.org/2008/8/12/parsing-xml-with-ruby"&gt;&lt;span class="caps"&gt;XML&lt;/span&gt;&lt;/a&gt; and &lt;span class="caps"&gt;JSON&lt;/span&gt; (JSON.parse, ActiveSupport::JSON.decode) parsing mechanisms available in Ruby have different APIs. I think parse is the easiest to remember and it is consistent with &lt;a href="http://railstips.org/2008/11/17/happymapper-making-xml-fun-again"&gt;HappyMapper&lt;/a&gt;, another project of mine, so whether you are working with &lt;span class="caps"&gt;XML&lt;/span&gt; or &lt;span class="caps"&gt;JSON&lt;/span&gt;, all you have to remember is parse.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;xml = '&amp;lt;posts&amp;gt;&amp;lt;post&amp;gt;&amp;lt;title&amp;gt;Foobar&amp;lt;/title&amp;gt;&amp;lt;/post&amp;gt;&amp;lt;post&amp;gt;&amp;lt;title&amp;gt;Another&amp;lt;/title&amp;gt;&amp;lt;/post&amp;gt;&amp;lt;/posts&amp;gt;'
Crack::XML.parse(xml)
# =&amp;gt; {"posts"=&amp;gt;{"post"=&amp;gt;[{"title"=&amp;gt;"Foobar"}, {"title"=&amp;gt;"Another"}]}}

json = '{"posts":[{"title":"Foobar"}, {"title":"Another"}]}'
Crack::JSON.parse(json)
# =&amp;gt; {"posts"=&amp;gt;[{"title"=&amp;gt;"Foobar"}, {"title"=&amp;gt;"Another"}]}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That is pretty much all there is to it. Given &lt;span class="caps"&gt;XML&lt;/span&gt; or &lt;span class="caps"&gt;JSON&lt;/span&gt;, you get back a hash. The repositoryhas been up for a couple days, but I thought I would mention it here as well. The keys here are simple and consistent. If you just want to get dirty and you aren’t worried about performance, crack is a perfect fit.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=ZqNoNXdlIZU:7nH0o5W8isY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=ZqNoNXdlIZU:7nH0o5W8isY:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=ZqNoNXdlIZU:7nH0o5W8isY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/ZqNoNXdlIZU" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/4/1/crack-the-easiest-way-to-parse-xml-and-json</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-03-29:8956</id>
    <published>2009-03-29T02:33:00Z</published>
    <updated>2009-04-05T21:13:22Z</updated>
    <category term="oauth" />
    <category term="twitter" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/0DpFu9ObvoI/oauth-explained-and-what-it-is-good-for" rel="alternate" type="text/html" />
    <title>OAuth Explained and What It Is Good For</title>
<summary type="html">&lt;p&gt;In which I attempt to explain OAuth in simple terms and what it is good for.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I attempt to explain OAuth in simple terms and what it is good for.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/avalonstar/3344478113/"&gt;&lt;img class="image right" src="http://farm4.static.flickr.com/3404/3344478113_5419d0d5f0_m.jpg" alt="OAuth" /&gt;&lt;/a&gt;Twitter recently announced OAuth support and that eventually they will be deprecating &lt;span class="caps"&gt;HTTP&lt;/span&gt; Basic Authentication in favor of OAuth. Knowing this, I figured it was about time to get familiar with OAuth and update the Twitter gem to use it.&lt;/p&gt;


	&lt;p&gt;Let me start by explaining my history with OAuth. I have none. There that was fast. I didn’t read the specifications or any articles on OAuth. I simply dove in code first and tried to figure out what was going on and how to make things work. I promise that what I’m about to explain will be simple and that I will not spend any time on hmac-sha1 signatures.&lt;/p&gt;


	&lt;p&gt;For the code examples below, I’ll be using the OAuth gem. Install is typical and I’ll provide it below for copy and paste.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;sudo gem install oauth&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;Tokens and Secrets&lt;/h2&gt;


	&lt;p&gt;At first, the hardest thing to figure out was all the tokens and secrets. Basically, there are three sets of made up of a token and a secret. Each set builds upon the last. The three sets are consumer, request and access.&lt;/p&gt;


	&lt;p&gt;The consumer token and secret are provided for you by the OAuth provider, when you register an application with them. These basically define what application is attempting to do the deed. You can create a new consumer like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;consumer = OAuth::Consumer.new(
  'consumer token', 
  'consumer secret', 
  {:site =&amp;gt; 'http://twitter.com'}
)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Before I go on, let me explain the end goal. The end goal with OAuth is to get an access token and secret. Once you have these, requesting a users information is much like it would be with &lt;span class="caps"&gt;HTTP&lt;/span&gt; Basic Authentication from a Ruby &lt;span class="caps"&gt;API&lt;/span&gt; point of view.&lt;/p&gt;


	&lt;h2&gt;Request Token&lt;/h2&gt;


	&lt;p&gt;In order to get the access token, you have to create a request token, keep track of it, and then redirect the user to the provider to authorize your application. You can create a new request token, using the consumer you just created, like so:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;request_token = consumer.get_request_token
puts request_token.token, request_token.secret&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The other thing that the request token provides is an authorization &lt;span class="caps"&gt;URL&lt;/span&gt;. The authorization &lt;span class="caps"&gt;URL&lt;/span&gt; is where your application redirects to, to allow the user to grant or deny you access to the their data. You can get the authorization &lt;span class="caps"&gt;URL&lt;/span&gt; in quite a predictable manner:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;request_token.authorize_url&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;If you were using Rails, you would simple redirect to this &lt;span class="caps"&gt;URL&lt;/span&gt;. Before you redirect, be sure to store the request token and secret as you’ll need those to create the access token when the user returns to your application.&lt;/p&gt;


	&lt;p&gt;Whether your app is on the web or something else, the aforementioned steps are the same. The difference is if you have a web app, you provide a redirect &lt;span class="caps"&gt;URL&lt;/span&gt; that the provider sends the user back to upon granting access, whereas if you have a desktop app, or the like, the page will just inform the user to head back to the app.&lt;/p&gt;


	&lt;h2&gt;Access Token&lt;/h2&gt;


	&lt;p&gt;Either way, once the user is back at your app, you use the request token and secret to generate the access token. In the code below, you would use the request token and secret that you stored in the session before redirecting to the authorization &lt;span class="caps"&gt;URL&lt;/span&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;request_token = OAuth::RequestToken.new(consumer, 'request token', 'request secret')
access_token = request_token.get_access_token&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Once you have the access token, you can make authenticated requests like so:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;puts access_token.get('/statuses/friends_timeline.json')&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I haven’t had to go this far yet, but I’m assuming you would store the access token and secret in the database or something for later use. Someone correct me if I’m wrong about this. Next time you need to access the user’s data, you can simply create a new access token from the token and secret, and once again make authenticated requests.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;access_token = OAuth::AccessToken.new(consumer, 'access token', 'access secret')
puts access_token.get('/statuses/friends_timeline.json')&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;The Twitter Gem&lt;/h2&gt;


	&lt;p&gt;So how does all this affect the Twitter gem? Currently, setting up the authentication for the Twitter gem is as easy as this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Twitter::Base.new('email', 'password')&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In the OAuth version of the Twitter gem, setting up the authentication will be something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Twitter::Base.new('access token', 'access secret')&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;So, pretty much the same. The only difference is that you will have to register your application with Twitter and then go through the process of getting the access token and secret. The good news is I already have a Twitter::OAuth class that will make this process as easy as possible.&lt;/p&gt;


	&lt;h2&gt;What It Is Good For&lt;/h2&gt;


	&lt;p&gt;I see three common methods for authenticating web services—HTTP Authentication, &lt;span class="caps"&gt;API&lt;/span&gt; keys and OAuth. &lt;span class="caps"&gt;HTTP&lt;/span&gt; Auth is simple, but then you end up with usernames and passwords all over the interwebs. OAuth is better in that users don’t give out passwords and can cancel at anytime with any app they have granted permission to.&lt;/p&gt;


	&lt;p&gt;The next question might be, “Wouldn’t an &lt;span class="caps"&gt;API&lt;/span&gt; key system be more simple than OAuth?” The answer is yes—for developers. &lt;strong&gt;For developers, it is easier to just tack an &lt;span class="caps"&gt;API&lt;/span&gt; key on every request&lt;/strong&gt; than to go through the process of all the aforementioned tokens and secrets. So if an &lt;span class="caps"&gt;API&lt;/span&gt; key system is easier for developers, why use OAuth?&lt;/p&gt;


	&lt;p&gt;I see OAuth as the &lt;strong&gt;easiest solution for users&lt;/strong&gt;. When determining how something will work for users, I often user the mom test. I guarantee you if my mom wanted to print a picture from flickr, she would not be able to figure out how to create an &lt;span class="caps"&gt;API&lt;/span&gt; key on Flickr and then use it with the printing site. Think about the opposite though. I definitely think that when redirected to flickr from the printing site, she could click yes to grant the printing site access.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;OAuth is easier for users and &lt;span class="caps"&gt;API&lt;/span&gt; keys are easier for developers&lt;/strong&gt;. When you go to build your &lt;span class="caps"&gt;API&lt;/span&gt;, take your primary audience into consideration and pick the solution that suites them best.&lt;/p&gt;


	&lt;p&gt;Hopefully this primer helps those (like me a day ago) who haven’t taken the time to get to know OAuth, and also those who have enjoyed the Twitter gem and are curious about what implications OAuth brings to the table. Formerly, I thought OAuth was over complicated, but now that I’ve spent a few hours with it, I’m pretty comfortable. Oh, and the other cool thing about this is now I have a base to work from for adding OAuth support to &lt;a href="http://railstips.org/2008/7/29/it-s-an-httparty-and-everyone-is-invited"&gt;HTTParty&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Any OAuth junkies out there, feel free to correct me or elaborate in the comments.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: For more on OAuth, you can read how I &lt;a href="http://railstips.org/2009/4/5/twitter-gem-reborn-with-fewer-features-and-100-more-oauth"&gt;updated the Twitter gem&lt;/a&gt; to use it.&lt;/p&gt;


	&lt;h2&gt;Some Further Reading&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://oauth.net/"&gt;OAuth website&lt;/a&gt; – Docs and history.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://oauth.rubyforge.org/"&gt;OAuth Gem&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://apiwiki.twitter.com/OAuth+Example+-+Ruby"&gt;Official Twitter OAuth Example&lt;/a&gt; – Includes pictures. Ooooh ahhh. Pictures. :)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/mbleigh/twitter-auth/tree/master"&gt;TwitterAuth&lt;/a&gt; – OAuth Twitter client (competition for the Twitter gem when I finish OAuth support for it)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/moomerman/sinitter/tree/master"&gt;Sinitter&lt;/a&gt; – Sinatra app using TwitterAuth.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://stakeventures.com/articles/2008/02/23/developing-oauth-clients-in-ruby"&gt;Developing OAuth clients in Ruby&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://stakeventures.com/articles/2007/11/26/how-to-turn-your-rails-site-into-an-oauth-provider"&gt;How to turn your Rails app into an OAuth provider&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=0DpFu9ObvoI:ut9kIUe2WB4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=0DpFu9ObvoI:ut9kIUe2WB4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=0DpFu9ObvoI:ut9kIUe2WB4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/0DpFu9ObvoI" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/3/29/oauth-explained-and-what-it-is-good-for</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-03-26:8942</id>
    <published>2009-03-26T14:00:00Z</published>
    <updated>2009-03-26T14:06:17Z</updated>
    <category term="atom" />
    <category term="feeds" />
    <category term="gems" />
    <category term="http" />
    <category term="rss" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/y7Ybj2GqMZ4/in-1492-columbus-discovered-a-feed" rel="alternate" type="text/html" />
    <title>In 1492, Columbus Discovered...A Feed</title>
<summary type="html">&lt;p&gt;In which I release a new gem named Columbus that auto-discovers feed urls.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I release a new gem named Columbus that auto-discovers feed urls.&lt;/p&gt;
&lt;p&gt;Sorry for the rush of posts the past few days. I’ve been feeling a bit inspired of late, and with the discovery of &lt;a href="http://railstips.org/2009/3/25/building-api-wrapping-gems-could-not-get-much-easier"&gt;Jeweler&lt;/a&gt;, it is now easier to make a gem than it is to just let the code sit in ~/dev/ruby/ on my computer.&lt;/p&gt;


	&lt;p&gt;A few weeks ago, I showed how to &lt;a href="http://railstips.org/2009/3/4/following-redirects-with-net-http"&gt;follow redirects using net/http&lt;/a&gt;, but I provided no context really as to why I wanted to follow redirects. Basically, that code was one piece of some code I wrote to auto-discover feed urls for a given url.&lt;/p&gt;


	&lt;p&gt;I was a little more creative with the name this time than &lt;a href="http://railstips.org/2009/3/25/building-api-wrapping-gems-could-not-get-much-easier"&gt;last time&lt;/a&gt;, calling it &lt;a href="http://github.com/jnunemaker/columbus/tree/master"&gt;Columbus&lt;/a&gt;. Get it? Auto-&lt;strong&gt;discovery&lt;/strong&gt; and Columbus was a &lt;strong&gt;discoverer&lt;/strong&gt;. Yeah, you get it. I’m sure I don’t need to explain it. Right? Yeah.&lt;/p&gt;


	&lt;h2&gt;Usage&lt;/h2&gt;


	&lt;p&gt;There isn’t much code in the gem and using it is even easier.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;# get the primary feed
primary = Columbus.new('http://railstips.org').primary
puts primary.url, primary.title, primary.body

# get all the feeds
Columbus.new('http://railstips.org').all&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The first returns a single feed if one is found else nil. The second returns all the feeds found in an array. That probably doesn’t feel like much, but there is a lot more going on behind the scenes.&lt;/p&gt;


	&lt;h2&gt;Behind the Scenes&lt;/h2&gt;


	&lt;ol&gt;
	&lt;li&gt;Gets the response for the passed in url.&lt;/li&gt;
		&lt;li&gt;If the &lt;span class="caps"&gt;URL&lt;/span&gt; is a redirect, it follows the redirect up to 5 times to find the endpoint.&lt;/li&gt;
		&lt;li&gt;Once it has the endpoint, it uses Hpricot to get all the link tags in the response body that appear to be &lt;span class="caps"&gt;RSS&lt;/span&gt; or Atom feeds.&lt;/li&gt;
		&lt;li&gt;For each link tag found, it gets the response for the &lt;span class="caps"&gt;URL&lt;/span&gt; and once again follows redirects up to 5 times until it finds an endpoint.&lt;/li&gt;
		&lt;li&gt;Once the endpoint for each feed is found, it returns the &lt;span class="caps"&gt;URL&lt;/span&gt;, the title and the response body for you to fart around with.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;h2&gt;Some Details&lt;/h2&gt;


	&lt;p&gt;Once again, I used &lt;a href="http://railstips.org/2009/2/21/shoulda-looked-at-it-sooner"&gt;shoulda&lt;/a&gt;, matchy and fakeweb to do the testing. I didn’t need &lt;a href="http://railstips.org/2008/7/29/it-s-an-httparty-and-everyone-is-invited"&gt;HTTParty&lt;/a&gt;, but I did break out an old friend Hpricot, which I haven’t used since &lt;a href="http://railstips.org/2006/12/9/parsing-xml-with-hpricot"&gt;&lt;span class="caps"&gt;XML&lt;/span&gt; parsing&lt;/a&gt; in the Twitter gem. Kind of funny that this is the first time I used Hpricot for its original intent, parsing &lt;span class="caps"&gt;HTML&lt;/span&gt;.&lt;/p&gt;


	&lt;h2&gt;Installation&lt;/h2&gt;


	&lt;p&gt;For now the gem is just up on Github so the usual routine will get your going.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;sudo gem install jnunemaker-columbus --source http://gems.github.com&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Hopefully someone finds it useful someday. :) I’ve already got my mileage out of it.&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=y7Ybj2GqMZ4:KvtdwSMuJL0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=y7Ybj2GqMZ4:KvtdwSMuJL0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=y7Ybj2GqMZ4:KvtdwSMuJL0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/y7Ybj2GqMZ4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/3/26/in-1492-columbus-discovered-a-feed</feedburner:origLink></entry>
  <entry xml:base="http://railstips.org/">
    <author>
      <name>john</name>
    </author>
    <id>tag:railstips.org,2009-03-25:8938</id>
    <published>2009-03-25T11:00:00Z</published>
    <updated>2009-04-11T06:02:36Z</updated>
    <category term="api" />
    <category term="gems" />
    <category term="google" />
    <category term="testing" />
    <link href="http://feedproxy.google.com/~r/railstips/~3/ajimswwDgJ0/building-api-wrapping-gems-could-not-get-much-easier" rel="alternate" type="text/html" />
    <title>Building API Wrapping Gems Could Not Get Much Easier</title>
<summary type="html">&lt;p&gt;In which I show how easy it is now to create ruby gems that wrap APIs, using Google Weather as an example.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In which I show how easy it is now to create ruby gems that wrap APIs, using Google Weather as an example.&lt;/p&gt;
&lt;p&gt;Google has a weather api that is dead simple to use. Just discovered that tonight so I whipped together a wrapper using HTTParty. I decided to try out &lt;a href="http://github.com/technicalpickles/jeweler/tree/master"&gt;Jeweler&lt;/a&gt;, a project by &lt;a href="http://technicalpickles.com/"&gt;Josh Nichols&lt;/a&gt;, that makes creating gems a snap and it delivered. I used shoulda and fakeweb for the tests. Holy crap has making a gem that wraps a web service become really easy.&lt;/p&gt;


	&lt;h2&gt;The New Way&lt;/h2&gt;


	&lt;ol&gt;
	&lt;li&gt;jeweler google-weather —shoulda —create-repo&lt;/li&gt;
		&lt;li&gt;%w(matchy fakeweb).each { |x| require x } (in your test_helper)&lt;/li&gt;
		&lt;li&gt;require ‘httparty’&lt;/li&gt;
		&lt;li&gt;Add some code and tests&lt;/li&gt;
		&lt;li&gt;rake version:bump:minor&lt;/li&gt;
		&lt;li&gt;rake gemspec&lt;/li&gt;
		&lt;li&gt;git push origin master&lt;/li&gt;
		&lt;li&gt;blog&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;I did all of these in &lt;strong&gt;about an hour or two&lt;/strong&gt; tonight.&lt;/p&gt;


	&lt;h2&gt;The Old Way&lt;/h2&gt;


	&lt;ol&gt;
	&lt;li&gt;Create a bunch of files and directories and make a bunch of decisions&lt;/li&gt;
		&lt;li&gt;mock and stub all net/http stuff&lt;/li&gt;
		&lt;li&gt;net/http and rexml (or hpricot once that came along)&lt;/li&gt;
		&lt;li&gt;Add some code and maybe some tests&lt;/li&gt;
		&lt;li&gt;Add a version&lt;/li&gt;
		&lt;li&gt;Figure out how to build a gemspec&lt;/li&gt;
		&lt;li&gt;svn commit your files&lt;/li&gt;
		&lt;li&gt;Request project to be created on rubyforge&lt;/li&gt;
		&lt;li&gt;Wait a few days&lt;/li&gt;
		&lt;li&gt;Project approved, release files, blog&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;And it would &lt;strong&gt;take a few days&lt;/strong&gt; from first code scratched to gem released. My how times are a changing.&lt;/p&gt;


	&lt;h2&gt;Stuff You Can Learn From This Gem&lt;/h2&gt;


	&lt;p&gt;At any rate, the &lt;a href="http://github.com/jnunemaker/google-weather/tree/master"&gt;GoogleWeather gem&lt;/a&gt; I just created is a really simple example of how to use:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/technicalpickles/jeweler/tree/master"&gt;jeweler&lt;/a&gt; to create and manage a gem&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/jnunemaker/httparty/tree/master"&gt;httparty&lt;/a&gt; to pwn an &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/thoughtbot/shoulda/tree/master"&gt;shoulda&lt;/a&gt; to test the gem&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://fakeweb.rubyforge.org/"&gt;fakeweb&lt;/a&gt; to make sure your tests aren’t making real web requests&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://github.com/jeremymcanally/matchy/tree/master"&gt;matchy&lt;/a&gt; for some syntactical sugar&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;If you want to learn any of those things, &lt;a href="http://github.com/jnunemaker/google-weather/tree/master"&gt;poke around in the code&lt;/a&gt; a bit and you should be good to go. Also, if you want a really easy way to get weather information, this gem &lt;a href="http://github.com/jnunemaker/google-weather/blob/1affe3d4da62b9cf22b996a6418ead63faeda4da/examples/forecast.rb"&gt;makes that possible&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Sorry I didn’t give it some fancy name like &lt;a href="http://railstips.org/2008/7/29/it-s-an-httparty-and-everyone-is-invited"&gt;HTTParty&lt;/a&gt; or &lt;a href="http://railstips.org/2008/11/17/happymapper-making-xml-fun-again"&gt;HappyMapper&lt;/a&gt;. Maybe I need to make another gem that spits out fancy names. After all, naming the project is the only thing left that is hard. ;)&lt;/p&gt;
          &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/railstips?a=ajimswwDgJ0:RaH3HhT_8W0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=ajimswwDgJ0:RaH3HhT_8W0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/railstips?a=ajimswwDgJ0:RaH3HhT_8W0:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/railstips?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/railstips/~4/ajimswwDgJ0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railstips.org/2009/3/25/building-api-wrapping-gems-could-not-get-much-easier</feedburner:origLink></entry>
</feed>
