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

<channel>
	<title>Brit Gardner &#187; ruby</title>
	<atom:link href="http://britg.com/topics/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://britg.com</link>
	<description>The big yellow one&#039;s the sun.</description>
	<lastBuildDate>Fri, 03 Feb 2012 05:08:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Forging Forgecraft: A Hybrid SQL MongoDB Data Solution</title>
		<link>http://britg.com/2012/01/07/forging-forgecraft-a-hybrid-sql-mongodb-data-solution/</link>
		<comments>http://britg.com/2012/01/07/forging-forgecraft-a-hybrid-sql-mongodb-data-solution/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 14:27:39 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[gaming]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[forgecraft]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[postgres]]></category>

		<guid isPermaLink="false">http://britg.com/?p=26402</guid>
		<description><![CDATA[Forgecraft is a game currently in development using Ruby on Rails, Backbone.js, and all sorts of HTML5 buzzwords. Read an introduction here, and play the demo here. One of my primary goals while building Forgecraft is to learn as many new technologies as possible. I&#8217;ve learned the hard way that it&#8217;s better to leave this [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://playforgecraft.com"><img src="http://britg.com.s3.amazonaws.com/forgecraft/logo-shadow.jpg" style="float: right; margin-left: 10px; margin-bottom: 10px; height: 45px;" /></a><em><a href="http://playforgecraft.com">Forgecraft</a> is a game currently in development using Ruby on Rails, Backbone.js, and all sorts of HTML5 buzzwords. Read an introduction <a href="http://britg.com/2011/12/29/forging-forgecraft-part-1-introduction/">here</a>, and play the demo <a href="http://playforgecraft.com">here</a>.</em></p>
<p>One of my primary goals while building Forgecraft is to learn as many new technologies as possible. I&#8217;ve learned the hard way that it&#8217;s better to leave this kind of exploration in your hobby projects and out of your production &#8220;for real&#8221; stuff. And, seeing as how there are so many emergent technologies right now in web development there&#8217;s a lot to explore!</p>
<h4>Whole Hog is Too Much Hog</h4>
<p><a href="http://mongodb.org">MongoDB</a> has quite a bit of steam behind it in the Rails/Ruby community (and plenty of other places too), and with projects like <a href="http://mongoid.org">Mongoid</a> and <a href="http://mongomapper.com/">MongoMapper</a> (I went with Mongoid) it&#8217;s an easy drop-in replacement for Active Record that maintains all those ORM conventions you know and love. I decided against the <em>replacement</em> approach for one primary reason: <strong>I wanted to use existing, robust, and actively developed libraries that rely on Active Record</strong>.</p>
<p>Example: There&#8217;s no reason to roll your own authentication/user system when there are insanely popular and feature-full libraries already in place for them like <a href="https://github.com/plataformatec/Devise">Devise</a> and <a href="https://github.com/binarylogic/authlogic">authlogic</a> (I went with Devise).</p>
<p>Fortunately combining Active Record with Mongoid and getting the best of both worlds proved to be easy and painless.</p>
<h4>The Set Up</h4>
<p>The <a href="http://mongoid.org/docs/installation/configuration.html">instructions</a> for Mongoid include a step to remove the Active Record libraries from being loaded and delete your database.yml. Simply skip that step and both systems will run in conjunction.</p>
<p>One small operational change you&#8217;ll have to make during development is explicitly defining when your rails generators should use Active Record. If you want to make an AR-driven model, your generators will look like:</p>
<p><code>rails g active_record:model Player …</code> produces a model the extends from ActiveRecord::Base.</p>
<p>And by default, the data generators will use Mongoid:</p>
<p><code>rails g model Skill …</code> produces a model that includes Mongoid::Document.</p>
<h4>The Implementation</h4>
<p>Here&#8217;s how this combo system really shines in my opinion: get all the great features of gems built on AR with all the schema less features of Mongo. I&#8217;ll walk through an example:</p>
<p>In Forgecraft, the authenticating object is the <code>Player</code> and players have many <code>Skills</code> which, right now, are Accuracy, Craftsmanship, and Perception. But, the skill list will likely grow and change over time as the game evolves. A typical AR/SQL based approach would be to create a skills table and a join table between players and skills resulting in a complex multi-table query to get a player&#8217;s complete skills.</p>
<p>It&#8217;s clear here that the Player and Skills would fit well together as a single document in Mongo, queried all at once in one tidy object. But, since the Player is also our authentication model, using Mongo would prevent us from using Devise to handle all of that boring and complex auth stuff for us.</p>
<p>Enter Hybridization. Forgecraft&#8217;s implementation uses the typical Devise set up around the Player object (again all on top of AR). All of a player&#8217;s skills go into a single document with a reference to the player, like so:</p>
<p><script src="https://gist.github.com/1575059.js?file=skill.rb"></script><br />
<noscript>
<pre>class Skill
  include Mongoid::Document
  field :player_id, :type => Integer

  field :accuracy, :type => Integer, :default => 0
  field :craftsmanship, :type => Integer, :default => 0
  field :perception, :type => Integer, :default => 0

  index :player_id, :unique => true

  def player
    Player.find_by_id(player_id)
  end
end</pre>
<p></noscript></p>
<p>To set up the relationships like one would expect with Active Record is a simple method on your Player object:</p>
<p><script src="https://gist.github.com/1575059.js?file=player.rb"></script><br />
<noscript>
<pre>class Player < ActiveRecord::Base

  # ...

  def skills
    @skills ||= (Skill.where(:player_id => self.id).first || \
                 Skill.create(:player_id => self.id))
  end

end</pre>
<p></noscript></p>
<p>Bam! Now we can retrieve our skills as a single document (fast), and add new skills with ease (easy). Since Mongo is schema less, you could even have a different set of skills per player. Again, all of this is achievable through SQL &#8212; it&#8217;s been done for decades &#8212; but it just makes more conceptual sense to treat these as a single document.</p>
<p>Querying and working with these objects and their relationships looks and feels just like active record:</p>
<pre>player.skills
player.skills.accuracy
player.skills.update_attributes(:accuracy => 5)
player.skills.inc(:accuracy, 1)</pre>
<h4>Benefits Outweight the Consequences</h4>
<p>I know, I know &#8212; any time you introduce an additional system, especially a datastore, you introduce a lot of complexity, failure modes, testing, etc. But, I honestly think the benefits are worth this extra complexity. Speed, ease of development, and the potential for less schema-driven growth make this an ideal environment for me. I highly recommend it, and will be using it in the future!</p>
<hr />
<p><em>More Forging Forgecraft:</em></p>
<ul>
<li> <a href="http://britg.com/2011/12/29/forging-forgecraft-part-1-introduction/">Introducing Forgecraft</a></li>
<li> <a href="http://britg.com/2012/01/15/forging-forgecraft-integrating-css3-transitions-with-javascript/">Integrating CSS3 Transitions with Javascript</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2012/01/07/forging-forgecraft-a-hybrid-sql-mongodb-data-solution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A SublimeText2 Project File for Rails Projects</title>
		<link>http://britg.com/2011/10/27/a-sublimetext2-project-file-for-rails-projects/</link>
		<comments>http://britg.com/2011/10/27/a-sublimetext2-project-file-for-rails-projects/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 16:03:10 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://britg.com/?p=24730</guid>
		<description><![CDATA[The fuzzy finder in SublimeText2 is great, but if you&#8217;ve added a rails folder to your project you may see a bunch of cruft in the result list most likely due to cache files. Here&#8217;s a generic rails project file I use that keeps the fuzzy finder pretty clean. Note: this is a Rails 3.0 [...]]]></description>
			<content:encoded><![CDATA[<p>The fuzzy finder in <a href="http://www.sublimetext.com/">SublimeText2</a> is great, but if you&#8217;ve added a rails folder to your project you may see a bunch of cruft in the result list most likely due to cache files. Here&#8217;s a generic rails project file I use that keeps the fuzzy finder pretty clean.</p>
<p><strong>Note:</strong> this is a Rails 3.0 project with <a href="http://documentcloud.github.com/jammit/">jammit</a> and <a href="http://compass-style.org/">compass</a> installed. The exclusion of the <code>assets</code> folder is probably not ideal in a Rails 3.1 project.</p>
<p><script src="https://gist.github.com/1319965.js?file=project.sublime-project"></script></p>
<p><noscript>
<pre>
{
	"folders":
	[
		{
			"path": "/Users/britg/Projects/ponycorn-fanclub.com",
            "folder_exclude_patterns": ["*.sass-cache", "tmp", "log", "assets", "cache"]
		}
	]
}
</pre>
<p></noscript></p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/10/27/a-sublimetext2-project-file-for-rails-projects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Foreman for Logging and Watchr</title>
		<link>http://britg.com/2011/06/02/using-foreman-for-logging-and-watchr/</link>
		<comments>http://britg.com/2011/06/02/using-foreman-for-logging-and-watchr/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 03:03:10 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[dev]]></category>

		<guid isPermaLink="false">http://britg.com/?p=6044</guid>
		<description><![CDATA[Foreman has quickly turned into a must-have gem for local development for me. From @ddollar&#8217;s description of Foreman: Using foreman you can declare the various processes that are needed to run your application using a Procfile. Besides the normal processes (rails, workers, etc.) I&#8217;ve found great success running log tailing and watchr through Foreman. Here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.daviddollar.org/2011/05/06/introducing-foreman.html">Foreman</a> has quickly turned into a must-have gem for local development for me.</p>
<p>From <a href="https://twitter.com/#!/ddollar">@ddollar&#8217;s</a> description of Foreman:</p>
<blockquote><p>Using foreman you can declare the various processes that are needed to run your application using a Procfile.</p></blockquote>
<p>Besides the normal processes (rails, workers, etc.) I&#8217;ve found great success running log tailing and <a href="https://github.com/mynyml/watchr">watchr</a> through Foreman. Here&#8217;s what my current Procfile looks like:</p>
<p><script src="https://gist.github.com/1005789.js?file=Procfile"></script><br />
<noscript>
<p><em>(View original to see this Gist.)</em></noscript></p>
<p>If your development pattern is anything like mine, it looks like:</p>
<ul>
<li>Edit a test, model or controller: check watchr output</p>
<li>Edit a view, js or scss file: refresh the browser</p>
</ul>
<p>Here&#8217;s what that looks like through Foreman:</p>
<p><a href="http://britg.com.s3.amazonaws.com/foreman_output.png" rel="facebox"><img src="http://britg.com.s3.amazonaws.com/foreman_output.png" style="width:600px;" /></a></p>
<p>This works well with watchr and log tailing output, as they rarely overlap. Even if they do, finding the appropriate output is easy with Foreman&#8217;s prepending of the process name and timestamp.</p>
<p>Have any other tips/tricks with Foreman? Let me know!</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2011/06/02/using-foreman-for-logging-and-watchr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sinatra Authentication with MongoMapper Support</title>
		<link>http://britg.com/2010/01/01/sinatra-authentication-with-mongomapper-support/</link>
		<comments>http://britg.com/2010/01/01/sinatra-authentication-with-mongomapper-support/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 20:56:45 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://britg.com/?p=1297</guid>
		<description><![CDATA[Added support for MongoMapper in the sinatra-authentication gem. Grab it from http://github.com/britg/sinatra-authentication. Be sure to require mongo_mapper before sinatra-authentication and everything should work peachy keen. require 'sinatra/base' require 'mongo_mapper' require 'sinatra-authentication']]></description>
			<content:encoded><![CDATA[<p>Added support for MongoMapper in the sinatra-authentication gem.  Grab it from <a href="http://github.com/britg/sinatra-authentication">http://github.com/britg/sinatra-authentication</a>.</p>
<p>Be sure to require mongo_mapper before sinatra-authentication and everything should work peachy keen.</p>
<pre class="brush: ruby; title: ;">
require 'sinatra/base'
require 'mongo_mapper'
require 'sinatra-authentication'
</pre>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2010/01/01/sinatra-authentication-with-mongomapper-support/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cross Origin Resource Sharing with Sinatra</title>
		<link>http://britg.com/2009/12/29/cross-origin-resource-sharing-with-sinatra/</link>
		<comments>http://britg.com/2009/12/29/cross-origin-resource-sharing-with-sinatra/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 15:46:45 +0000</pubDate>
		<dc:creator>britg</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[cors]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://britg.com/?p=1282</guid>
		<description><![CDATA[It&#8217;s no lie that I think highly of the potential of Cross Origin Resource Sharing. One of the great things about it is that it doesn&#8217;t take much re-wiring of existing server (or client-side) apps to start working cross domain. Enabling your server app is as simple as including a few extra headers when you [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s no lie that <a href="http://britg.com/2009/12/02/cross-origin-resource-sharing/">I think highly</a> of the potential of Cross Origin Resource Sharing.  One of the great things about it is that it doesn&#8217;t take much re-wiring of existing server (or client-side) apps to start working cross domain.</p>
<p>Enabling your server app is as simple as including a few extra headers when you detect a cross origin request.  How do you know it&#8217;s a cross origin request?  You&#8217;ll see the <code>Origin:</code> header &#8212; all CORS requests will have it.  From there, response headers depend on the specifics of the request, but I won&#8217;t go over those here &#8212; check out the <a href="https://developer.mozilla.org/En/HTTP_access_control">Mozilla Developer Center treatment</a> for in-depth information.</p>
<p>I&#8217;ve been working with Sinatra a lot lately, so I put together <a href="http://github.com/britg/sinatra-cross_origin">an extension for Sinatra</a> that makes enabling Cross Origin requests even easier.</p>
<p><code>sudo gem install sinatra-cross_origin</code></p>
<p>There are two ways to use the extension: globally or per-route.</p>
<h3>Global</h3>
<p>For when you want to share all your endpoints cross-domain.</p>
<pre class="brush: ruby; title: ;">

require 'sinatra/base'
require 'sinatra/cross_origin'

class MyApp &amp;lt; Sinatra::Base
  register Sinatra::CrossOrigin

  enable cross_origin

  get '/' do
    &amp;quot;This is available to cross domain javascript requests automatically&amp;quot;
  end
end
</pre>
<h3>Per Route</h3>
<p>For when you want to share only some of your routes cross-domain.</p>
<pre class="brush: ruby; title: ;">

require 'sinatra/base'
require 'sinatra/cross_origin'

class MyApp &amp;lt; Sinatra::Base
  register Sinatra::CrossOrigin

  get '/' do
    cross_origin
    &amp;quot;This is available to cross domain javascript requests&amp;quot;
  end
end
</pre>
<h3>Configuration</h3>
<p>You can mix and match app-wide config and request specific config.</p>
<pre class="brush: ruby; title: ;">

require 'sinatra/base'
require 'sinatra/cross_origin'

class MyApp &amp;lt; Sinatra::Base
  register Sinatra::CrossOrigin

  configure do
    # Comma separate list of remote hosts that are allowed.
    # :any will allow any host
    set :allow_origin, :any

    # HTTP methods allowed
    set :allow_methods, [:get, :post]

    # Allow cookies to be sent with the requests
    set :allow_credentials, true
  end

  get '/' do
    # Only available to GET requests originating from
    # <a href="http://example.com" rel="nofollow">http://example.com</a>.  No cookies allowed.
    cross_origin :allow_origin =&amp;gt; '<a href="http://example.com&#039;" rel="nofollow">http://example.com&#039;</a>,
      :allow_methods =&amp;gt; [:get],
      :allow_credentials =&amp;gt; false
    &amp;quot;This is available to cross domain javascripts&amp;quot;
  end
end
</pre>
<p>Grab the source at Github: <a href="http://github.com/britg/sinatra-cross_origin">britg/sinatra-cross_origin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://britg.com/2009/12/29/cross-origin-resource-sharing-with-sinatra/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

