<?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/"
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Quest for the Holy Rails</title>
	<atom:link href="http://railsquest.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://railsquest.wordpress.com</link>
	<description>One Web Knight&#039;s Quest to Master a Toolkit</description>
	<lastBuildDate>Mon, 15 Oct 2007 03:42:39 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='railsquest.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/f3ed1ba8ca5b91e4b9d5c6f88589a7ce?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Quest for the Holy Rails</title>
		<link>http://railsquest.wordpress.com</link>
	</image>
			<item>
		<title>The Games People Play (Part 2)</title>
		<link>http://railsquest.wordpress.com/2007/10/15/the-games-people-play-part-2/</link>
		<comments>http://railsquest.wordpress.com/2007/10/15/the-games-people-play-part-2/#comments</comments>
		<pubDate>Mon, 15 Oct 2007 03:42:39 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/10/15/the-games-people-play-part-2/</guid>
		<description><![CDATA[This was a partial post I was working on before I stopped the project, I might as well post it.
In the last post we wrote our Game model. In this post we will modify the games controller and views so players can create games.
Players need to be able to create games, delete games (forfeit), and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=13&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>This was a partial post I was working on before I stopped the project, I might as well post it.</p>
<p>In the <a href="/2007/05/10/the-games-people-play/">last post</a> we wrote our Game model. In this post we will modify the games controller and views so players can create games.<span id="more-13"></span></p>
<p>Players need to be able to create games, delete games (forfeit), and display games but there they won&#8217;t ever update them. Let&#8217;s drop the functional tests for updating since that feature isn&#8217;t needed. When a user makes a move we could call that editing a game, but I prefer to think of it as creating a move (we&#8217;ll do the Move model later).</p>
<p>Let&#8217;s remove the following tests from test/functional/games_controller_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">   def test_should_get_edit
    get :edit, :id =&gt; 1
    assert_response :success
  end

  def test_should_update_game
    put :update, :id =&gt; 1, :game =&gt; { }
    assert_redirected_to game_path(assigns(:game))
  end</pre>
<p>Now we can trim the edit, update actions from the app/controllers/games_controller.rb, and delete app/views/games/edit.rhtml.</p>
<p>Let&#8217;s require login to access the games controller, first add a test in test/functional/games_controller.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">  def setup
    @controller = GamesController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    login_as 'quentin'
  end
... snip ...
  def test_index_should_require_authenticated
    assert_requires_login {|c| c.get :index}
  end

  def test_new_should_require_authenticated
    assert_requires_login {|c| c.get :new}
  end</pre>
<p>Now we add the code to make it pass in app/controllers/games_controller.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">  before_filter :login_required</pre>
<p>We need to add some attributes to the Game model </p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;"></pre>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/13/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/13/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/13/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/13/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/13/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=13&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/10/15/the-games-people-play-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>In case you didn&#8217;t guess&#8230;</title>
		<link>http://railsquest.wordpress.com/2007/10/15/in-case-you-didnt-guess/</link>
		<comments>http://railsquest.wordpress.com/2007/10/15/in-case-you-didnt-guess/#comments</comments>
		<pubDate>Mon, 15 Oct 2007 03:41:47 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/10/15/in-case-you-didnt-guess/</guid>
		<description><![CDATA[So I&#8217;m working at Intentional Software now. I guess the previous post I made got their attention. I&#8217;m not planning any more work on this project, but I used Pente to learn C# for the new job. My work on that is more complete and is at http://mono-pente.sf.net &#8212; oh and it&#8217;s actually in C++ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=16&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>So I&#8217;m working at Intentional Software now. I guess the previous post I made got their attention. I&#8217;m not planning any more work on this project, but I used Pente to learn C# for the new job. My work on that is more complete and is at http://mono-pente.sf.net &#8212; oh and it&#8217;s actually in C++ now.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/16/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/16/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/16/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/16/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/16/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=16&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/10/15/in-case-you-didnt-guess/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>Intentional Programming</title>
		<link>http://railsquest.wordpress.com/2007/05/18/intentional-programming/</link>
		<comments>http://railsquest.wordpress.com/2007/05/18/intentional-programming/#comments</comments>
		<pubDate>Fri, 18 May 2007 06:28:37 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[Off Topic]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/05/18/intentional-programming/</guid>
		<description><![CDATA[I apologize for the long delay in posts, my parents were in town last week, and this week I&#8217;m catching up on homework. In the meantime I discovered an interesting programming paradigm that I&#8217;d been thinking about for awhile now, but didn&#8217;t know it had a name. It&#8217;s called intentional programming.
I really like the idea [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=14&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I apologize for the long delay in posts, my parents were in town last week, and this week I&#8217;m catching up on homework. In the meantime I discovered an interesting programming paradigm that I&#8217;d been thinking about for awhile now, but didn&#8217;t know it had a name. It&#8217;s called <a href="http://en.wikipedia.org/wiki/Intentional_programming">intentional programming</a>.<span id="more-14"></span></p>
<p>I really like the idea of allowing flexible levels of code abstraction. Wouldn&#8217;t it be great if software engineers could work the abstraction levels up from raw assembly to C-Style to Ruby style to <a href="http://en.wikipedia.org/wiki/Domain_Specific_Language">DSL</a> style using the same &#8220;language&#8221;? Then domain experts could work at the DSL level. Imagine being able to read the code at DSL level, and to &#8220;zoom in&#8221; on trouble parts to see what&#8217;s going on. Comments and external documentation shouldn&#8217;t even be necessary anymore. Instead you can just zoom out until it&#8217;s clear what the block you&#8217;re looking at does. This is already almost going on, but the abstraction levels are almost completely separated. We have assemblers, compilers, interpreters, and libraries. Putting all this into an integrated stack could be really powerful.</p>
<p>I also really like the idea of separating code source storage and presentation. Why are we all still working with ASCII fixed width text files? Source code should be stored as XML (or something like it) and the editor should present and allow us to edit it any way the programmer chooses. To one programmer the file looks like a standard text file w/ tabs and fixed width font, to another maybe it looks like a bunch of balloons connected with arrows. Maybe the first programmer is a software engineer and needs to be able to dig deeper down the abstraction layers, and the latter is the domain expert.</p>
<p>I&#8217;d like to see a &#8220;language&#8221; that has as close to <strong>zero</strong> primitives as possible. It should simply be able to translate one layer of abstraction to another. The terminal layer being assembly/machine code (or maybe even bytecode?). The programmer would be able to build as many abstraction layers on top as were needed. It wouldn&#8217;t have an if statement primitive, but in a library would have some &#8220;code&#8221; describing how to translate &#8220;if (true) then i = 1 + 0&#8243; to the appropriate machine code. Instead of including &#8220;if&#8221;, &#8220;for&#8221;, &#8220;while&#8221;, etc as primitives in the language they should be in libraries. Then it would be possible to extend the syntax of the language. You could include a library that would let you write ANSI compliant C with for_each support on arrays perhaps. This last bit reminds me a bit of the .NET stuff where you can write code using different languages. I think it&#8217;s a bit different though as I believe .NET is just a collection of separate compilers that generate CLR code that can be interlinked. I&#8217;d like to see the &#8220;primitives&#8221; or even syntax of a language defined as much as possible in libraries that can be extended.</p>
<p>If the compiler were able to understand the mathematical properties of the machine code (like adding or subtracting 0 doesn&#8217;t change the number) then it could know that &#8220;i = 1 + 0&#8243; is the same as &#8220;i = 1&#8243;. It could figure out on the fly what could be done statically at compile time and what needs to be done dynamically at runtime. It&#8217;s all still pretty rough in my mind, but I think there is a ton of potential for optimization. I think a lot of the ideas of <a href="http://en.wikipedia.org/wiki/Generic_programming">generic programming</a> fit in very well here.</p>
<p>I can&#8217;t really put it into concrete examples yet, but it&#8217;s really interesting as a dual-major hardware/software engineering student to see the differences between &#8220;programming&#8221; hardware and software. I think the software engineering community could really take some lessons from the hardware community. I love how I can describe how I want a block of logic to work using if&#8217;s/cases/boolean logic and the compiler will break down all the barriers I&#8217;ve set up to keep the code modular and optimize it down to a minimal set of logic equations. That seems pretty close to intentional programming. I&#8217;m writing what my intention is, and the compiler figures out how best to do it. When I write C I feel like I&#8217;m just using shorthand for assembly. I need to study how optimization works in today&#8217;s compilers, maybe it&#8217;s more like hardware than I think, but today&#8217;s programming languages are still based heavily on the principles of C which was initially intended to map quite directly to machine code.</p>
<p>Well this turned out to be a longer, and less organized post than I intended it to be. I really think there&#8217;s some great potential in a combination of this Intentional Programming idea and Generic Programming. I really need to read up on some of these ideas when I get a chance to see what work is already being done.</p>
<p><strong>Update:</strong> There&#8217;s a <a href="http://www.intentsoft.com/technology/IS_OOPSLA_2006_paper.pdf">great paper</a> from the company <a href="http://www.intentsoft.com/">Intentional Software</a> that goes into really good detail on some of these ideas. If you find these ideas interesting, or don&#8217;t quite understand what the ideas mean I would highly recommend reading it.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/14/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/14/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/14/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/14/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/14/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=14&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/05/18/intentional-programming/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>The Games People Play (Part 1)</title>
		<link>http://railsquest.wordpress.com/2007/05/10/the-games-people-play/</link>
		<comments>http://railsquest.wordpress.com/2007/05/10/the-games-people-play/#comments</comments>
		<pubDate>Thu, 10 May 2007 18:31:01 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[pente]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/05/10/the-games-people-play/</guid>
		<description><![CDATA[In the last post we implemented a welcome controller that lets us sign up, in and out. Now we&#8217;re going to add a RESTful games resource to the project so users can manage games.
First let&#8217;s use the generator to give us a resource scaffold:
jake@jake-laptop:~/src/pente$ script/generate scaffold_resource game
      exists  app/models/
 [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=11&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>In the <a href="/2007/05/07/the-welcome-controller/">last post</a> we implemented a welcome controller that lets us sign up, in and out. Now we&#8217;re going to add a RESTful games resource to the project so users can manage games.<span id="more-11"></span></p>
<p>First let&#8217;s use the generator to give us a resource scaffold:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ script/generate scaffold_resource game
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/games
      exists  test/functional/
      exists  test/unit/
      create  app/views/games/index.rhtml
      create  app/views/games/show.rhtml
      create  app/views/games/new.rhtml
      create  app/views/games/edit.rhtml
      create  app/views/layouts/games.rhtml
      create  public/stylesheets/scaffold.css
      create  app/models/game.rb
      create  app/controllers/games_controller.rb
      create  test/functional/games_controller_test.rb
      create  app/helpers/games_helper.rb
      create  test/unit/game_test.rb
      create  test/fixtures/games.yml
      exists  db/migrate
      create  db/migrate/002_create_games.rb
       route  map.resources :games
jake@jake-laptop:~/src/pente$</pre>
<p>Now let&#8217;s define the columns for the games table in edit db/migrate/002_create_games.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">class CreateGames &lt; ActiveRecord::Migration

  def self.up
    create_table :games do |t|
      t.column :black_player_id, :integer
      t.column :white_player_id, :integer
      t.column :current_player_id, :integer
      t.column :winning_player_id, :integer
      t.column :created_at, :datetime
      t.column :updated_at, :datetime
      t.column :ended_at, :datetime
    end
  end

  def self.down
    drop_table :games
  end

end</pre>
<p>And migrate:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ rake db:migrate
(in /home/jake/src/pente)
== CreateGames: migrating =====================================================
-- create_table(:games)
   -&gt; 0.0163s
== CreateGames: migrated (0.0165s) ============================================

jake@jake-laptop:~/src/pente$</pre>
<p>Let&#8217;s add in a couple fixtures to work with in our tests:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">one:
  id: 1
  black_player_id: 1
  white_player_id: 2
  current_player_id: 1
  created_at: &lt;%= 1.days.ago.to_s :db %&gt;
  updated_at: &lt;%= 12.hours.ago.to_s :db %&gt;

two:
  id: 2
  black_player_id: 2
  white_player_id: 1
  winning_player_id: 2
  created_at: &lt;%= 5.days.ago.to_s :db %&gt;
  updated_at: &lt;%= 2.days.ago.to_s :db %&gt;
  ended_at: &lt;%= 2.days.ago.to_s :db %&gt;</pre>
<p>Let&#8217;s associate it with players first defining some tests in test/unit/game_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">require File.dirname(__FILE__) + '/../test_helper'

class GameTest &lt; Test::Unit::TestCase
  fixtures :games, :players

  def test_should_associate_with_players
    assert_equal 1, games(:one).black_player.id
    assert_equal 2, games(:one).white_player.id
    assert_equal 1, games(:one).current_player.id
    assert_equal 2, games(:two).winning_player.id
  end

end</pre>
<p>Your tests will now fail so let&#8217;s add some code to app/models/game.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">class Game &lt; ActiveRecord::Base
  belongs_to :black_player, :class_name =&gt; 'Player', :foreign_key =&gt; :black_player_id
  belongs_to :white_player, :class_name =&gt; 'Player', :foreign_key =&gt; :white_player_id
  belongs_to :current_player, :class_name =&gt; 'Player', :foreign_key =&gt; :current_player_id
  belongs_to :winning_player, :class_name =&gt; 'Player', :foreign_key =&gt; :winning_player_id
end</pre>
<p>Let&#8217;s add associations to the player side starting with the tests in test/unit/player_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  fixtures :players, :games
... snip ...
  def test_should_associate_with_games
    assert players(:aaron).black_games
    assert players(:aaron).white_games
    assert players(:quentin).current_games
    assert players(:aaron).won_games
  end
... snip ...</pre>
<p>And to make it pass by adding to app/models/player.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  has_many :black_games, :class_name =&gt; 'Game', :foreign_key =&gt; :black_player_id
  has_many :white_games, :class_name =&gt; 'Game', :foreign_key =&gt; :white_player_id
  has_many :current_games, :class_name =&gt; 'Game', :foreign_key =&gt; :current_player_id
  has_many :won_games, :class_name =&gt; 'Game', :foreign_key =&gt; :winning_player_id
... snip ...</pre>
<p>Now I&#8217;m going to go through and add several tests and show the code required to make it pass.</p>
<p>test/unit/game_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  def test_should_validate_presence_of_players
    g = games(:one)
    g.black_player_id = nil
    assert !g.valid?
    assert g.errors.on(:black_player_id)
    g = games(:one)
    g.white_player_id = nil
    assert !g.valid?
  end
... snip ...</pre>
<p>app/model/game.rb</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  validates_presence_of :black_player_id, :white_player_id
... snip ...</pre>
<p>When you run your tests now the test we just wrote is passing, but we&#8217;ve broken another one! The generated functional test case contains a test that checks create. When we add validations to the model that won&#8217;t allow a model to be created with all of its attributes set to nil that test will break. We&#8217;ve got to modify the test to create a valid player.</p>
<p>test/functional/games_controller_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  def test_should_create_game
    old_count = Game.count
    post :create, :game =&gt; { :black_player_id =&gt; 1, :white_player_id =&gt; 2 }
    assert_equal old_count+1, Game.count

    assert_redirected_to game_path(assigns(:game))
  end
... snip ...</pre>
<p>Back to creating more tests:</p>
<p>test/unit/game_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  def test_should_validate_players_different
    g = games(:one)
    g.black_player_id = g.white_player_id
    assert !g.valid?
    assert g.errors.on_base
  end
... snip ...</pre>
<p>app/model/game.rb</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  validate :players_different
... snip ...
  protected

  def players_different
    errors.add_to_base('Players must be different') if self.black_player_id == self.white_player_id
  end
... snip ...</pre>
<p>test/unit/game_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  def test_should_make_white_current_on_create
    g = Game.create(:white_player_id =&gt; 1, :black_player_id =&gt; 2)
    assert_equal g.white_player_id, g.current_player_id
  end
... snip ...</pre>
<p>app/model/game.rb</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  before_create :make_white_player_current
... snip ...
  protected

  def make_white_player_current
    self.current_player_id = self.white_player_id
  end
... snip ...</pre>
<p>test/unit/game_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  def test_should_declare_winner
    g = games(:one)
    before = Time.now
    g.declare_winner!(g.black_player_id)
    assert_equal g.black_player_id, g.winning_player_id
    assert_nil g.current_player_id
    assert g.ended_at.between?(before, Time.now)
    assert g.save
  end

  def test_should_raise_on_invalid_winner
    g = games(:one)
    assert_raise(Game::InvalidWinner) { g.declare_winner!(999) }
  end
... snip ...</pre>
<p>app/model/game.rb</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  def declare_winner!(winner_id)
    raise InvalidWinner unless
      [self.black_player_id, self.white_player_id].include?(winner_id)
    self.winning_player_id = winner_id
    self.current_player_id = nil
    self.ended_at = Time.now
  end
... snip ...</pre>
<p>These tests will already pass because this is done automatically, but let&#8217;s put them in anyway:<br />
test/unit/game_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">... snip ...
  def test_should_set_created_at
    before = Time.now
    g = Game.create(:black_player_id =&gt; 1, :white_player_id =&gt; 2)
    assert g.created_at.between?(before, Time.now)
  end

  def test_should_set_updated_at
    before = Time.now
    g = games(:one)
    g.save
    assert g.updated_at.between?(before, Time.now)
  end
... snip ...</pre>
<p>So we&#8217;ve written a pretty complete Game model now and have a full test suite for it! Isn&#8217;t TDD nice? I made it look easy by copy/pasting the working tests and code, but there was some finageling on my part to get things to work. It&#8217;s better to iron out all the problems now though rather than attempting to use the class and discovering problems while I&#8217;m trying to write other code.</p>
<p>In the next part we&#8217;ll write the controller and views to handle the new Game model.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/11/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/11/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/11/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=11&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/05/10/the-games-people-play/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>The Welcome Controller</title>
		<link>http://railsquest.wordpress.com/2007/05/07/the-welcome-controller/</link>
		<comments>http://railsquest.wordpress.com/2007/05/07/the-welcome-controller/#comments</comments>
		<pubDate>Mon, 07 May 2007 01:27:08 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[pente]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/05/07/the-welcome-controller/</guid>
		<description><![CDATA[In the last post we created the Rails project and added authentication. In this post we will add a welcome controller.
Our welcome controller will be very simple for now. It will just have links for the options available to the user depending on if they&#8217;re logged in or not.
Let&#8217;s go ahead and generate the controller:
jake@jake-laptop:~/src/pente$ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=10&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>In the <a href="/2007/05/04/our-journey-begins-players/">last post</a> we created the Rails project and added authentication. In this post we will add a welcome controller.<span id="more-10"></span></p>
<p>Our welcome controller will be very simple for now. It will just have links for the options available to the user depending on if they&#8217;re logged in or not.</p>
<p>Let&#8217;s go ahead and generate the controller:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ script/generate controller welcome

      exists  app/controllers/

      exists  app/helpers/

      create  app/views/welcome

      exists  test/functional/

      create  app/controllers/welcome_controller.rb

      create  test/functional/welcome_controller_test.rb

      create  app/helpers/welcome_helper.rb

jake@jake-laptop:~/src/pente$</pre>
<p>Let&#8217;s add an index action. Since we&#8217;re using TDD let&#8217;s add a functional test in test/functional/welcome_controller_test.rb that fails because we don&#8217;t have one:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">require File.dirname(__FILE__) + '/../test_helper'

require 'welcome_controller'# Re-raise errors caught by the controller.

class WelcomeController; def rescue_action(e) raise e end; end

class WelcomeControllerTest &lt; Test::Unit::TestCase

def setup

    @controller = WelcomeController.new

    @request    = ActionController::TestRequest.new

    @response   = ActionController::TestResponse.new

  end

def test_should_have_index

    get :index

    assert_response :success

  end

end</pre>
<p>Run the test:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ rake

(in /home/jake/src/pente)

/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb" "test/unit/player_test.rb"

Loaded suite /var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader

Started

.............

Finished in 0.086673 seconds.13 tests, 26 assertions, 0 failures, 0 errors

/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/functional/welcome_controller_test.rb" "test/functional/players_controller_test.rb"

Loaded suite /var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader

Started

..............E

Finished in 0.137953 seconds.

1) Error:

test_should_have_index(WelcomeControllerTest):

ActionController::UnknownAction: No action responded to index

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:632:in `call_filter'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:638:in `call_filter'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:438:in `call'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:637:in `call_filter'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:619:in `perform_action_without_benchmark'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue'

    /usr/lib/ruby/1.8/benchmark.rb:293:in `measure'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/rescue.rb:83:in `perform_action'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/base.rb:430:in `send'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/base.rb:430:in `process_without_filters'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:624:in `process_without_session_management_support'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/session_management.rb:114:in `process_without_test'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/test_process.rb:15:in `process'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/test_process.rb:382:in `process'

    /var/lib/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/test_process.rb:353:in `get'

    ./test/functional/welcome_controller_test.rb:16:in `test_should_have_index'

15 tests, 26 assertions, 0 failures, 1 errors

/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb"

Command failed with status (1): [/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems...]

/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake.rb:719:in `sh'

/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake.rb:726:in `call'

... snip ...

/var/lib/gems/1.8/bin/rake:18:in `load'

/var/lib/gems/1.8/bin/rake:18

rake aborted!

Test failures

(See full trace by running task with --trace)

jake@jake-laptop:~/src/pente$</pre>
<p>Alright we&#8217;re in the red now so let&#8217;s implement the code:</p>
<p>app/controllers/welcome_controller.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">class WelcomeController &lt; ApplicationController  def index

  end

end</pre>
<p>app/views/welcome/index.rhtml:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">Welcome!</pre>
<p>Run the test agan and we&#8217;re in the green:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ rake

(in /home/jake/src/pente)

/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb" "test/unit/player_test.rb"

Loaded suite /var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader

Started

.............

Finished in 0.100943 seconds.13 tests, 26 assertions, 0 failures, 0 errors

/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/functional/welcome_controller_test.rb" "test/functional/players_controller_test.rb"

Loaded suite /var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader

Started

...............

Finished in 0.145732 seconds.

15 tests, 27 assertions, 0 failures, 0 errors

/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb"

jake@jake-laptop:~/src/pente$</pre>
<p>Before we forget let&#8217;s get rid of the public/index.html file so when we use WEBrick we get the correct page. The file doesn&#8217;t hurt the tests, but this is a good time to remove it anyway, and while we&#8217;re at it we&#8217;ll map our welcome controller to &#8221; so it shows up by default:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ rm public/index.html

jake@jake-laptop:~/src/pente$</pre>
<p>config/routes.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">ActionController::Routing::Routes.draw do |map|

  map.resource :players, :sessions

  map.connect '', :controller =&gt; "welcome"

  map.connect ':controller/:action/:id.:format'

  map.connect ':controller/:action/:id'

end</pre>
<p>Now we want to add some useful links to the welcome page. So far the only think a user can do is signup, login and logout. Let&#8217;s add some tests to check for this functionality. I&#8217;m adding more than one test at a time here to speed things up since this is pretty basic:<br />
test/functional/welcome_controller_test.rb:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">require File.dirname(__FILE__) + '/../test_helper'

require 'welcome_controller'# Re-raise errors caught by the controller.

class WelcomeController; def rescue_action(e) raise e end; end

class WelcomeControllerTest  'a', :attributes =&gt; {'href' =&gt; x}

    end

  end

def test_should_have_links_when_logged_in

    login_as 'aaron'

    get :index

    ['/sessions/destroy'].each do |x|

      assert_tag :tag =&gt; 'a', :attributes =&gt; {'href' =&gt; x}

    end

  end

end</pre>
<p>I&#8217;ve been doing a lot of thinking about REST and I think I&#8217;ve found a compromize that will keep all the main benefits of REST without any of the ugly javascript hacks. I will use RESTful URLs in links when it&#8217;s possible, but resort to classic Rails controller/action/id style links when it avoids an ugly Javascript hack. I still get the REST web API as I&#8217;m not disabling the REST interface, and the HTML doesn&#8217;t have the ugly hacks.</p>
<p>Now let&#8217;s make them pass by modifying app/views/welcome/index.rhtml:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">&lt;ul&gt;

&lt;% if logged_in? -%&gt;

  &lt;li&gt;&lt;a href='/sessions/destroy'&gt;Logout&lt;/a&gt;&lt;/li&gt;

&lt;% else -%&gt;

  &lt;li&gt;&lt;a href='/sessions/new'&gt;Login&lt;/a&gt;&lt;/li&gt;

  &lt;li&gt;&lt;a href='/players/new'&gt;Signup&lt;/a&gt;&lt;/li&gt;

&lt;% end -%&gt;

&lt;/ul&gt;</pre>
<p>We&#8217;re now back in the green with a working welcome controller! From here on out I&#8217;m going to skip copy/pasting the test results when they all pass to save space and time. You might not be convinced the login controller is actually working because we haven&#8217;t actually seen it in the browser. That&#8217;s one of the great things about TDD. You don&#8217;t have to rely on randomly clicking links in a browser to make sure things are working. Go ahead and fire up WEBrick (scripts/server) and <a href="http://localhost:3000">see for yourself</a>!</p>
<p>I&#8217;m going to be saving all the HTML/CSS prettification for the end of the project and keep the interfaces plain for now.</p>
<p>In the next post I&#8217;ll add a games resource and tie it to the players resource.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/10/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/10/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/10/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=10&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/05/07/the-welcome-controller/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>Our Journey Begins: Players</title>
		<link>http://railsquest.wordpress.com/2007/05/04/our-journey-begins-players/</link>
		<comments>http://railsquest.wordpress.com/2007/05/04/our-journey-begins-players/#comments</comments>
		<pubDate>Wed, 30 Nov -0001 00:00:00 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[pente]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/05/04/our-journey-begins-players/</guid>
		<description><![CDATA[I&#8217;ve introduced the concept of test driven development and REST and I&#8217;m finally ready to start writing some code on my Pente project. In this post I will setup the project, and generate and customize the player resource.
I&#8217;m going to assume that you&#8217;ve covered the basics already so I&#8217;ll go quickly over some of the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=7&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;ve introduced the concept of <a href="/2007/05/02/would-you-jump-before-you-checked-your-parachute/">test driven development</a> and <a href="/2007/05/02/resting-on-rails-isnt-as-dangerous-as-it-sounds/">REST</a> and I&#8217;m finally ready to start writing some code on my Pente project. In this post I will setup the project, and generate and customize the player resource.<span id="more-7"></span></p>
<p>I&#8217;m going to assume that you&#8217;ve <a href="/2007/05/02/all-aboard-getting-started-with-rails/">covered the basics</a> already so I&#8217;ll go quickly over some of the basics.</p>
<p><strong>Note:</strong> Since we&#8217;re using REST Rails must be at version 1.2 or better</p>
<p>The first step is to create your rails project:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src$ rails pente -d sqlite3
      create
      create  app/controllers
      create  app/helpers
      ... snip ...
      create  log/production.log
      create  log/development.log
      create  log/test.log
jake@jake-laptop:~/src$</pre>
<p>I used &#8220;-d sqlite3&#8243; so it would use sqlite3 for the databases. I find it much easier to develop using sqlite3 since you don&#8217;t need to setup mysql. When I deploy the app I&#8217;ll evaluate the different database options and might change the database then, but for now it&#8217;s sqlite3.</p>
<p>Next let&#8217;s install a plugin from <a href="http://techno-weenie.net/">Rick Olson</a> called <a href="http://svn.techno-weenie.net/projects/plugins/restful_authentication/">restful_authentication</a>:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
+ ./restful_authentication/README
+ ./restful_authentication/Rakefile
... snip ...
+ ./restful_authentication/generators/authenticated/templates/unit_test.rb
+ ./restful_authentication/install.rb
Restful Authentication Generator
====

This is a basic restful authentication generator for rails, taken from acts as authenticated.  Currently it requires Rails 1.2 (or edge).

To use:

  ./script/generate authenticated user sessions --include-activation

The first parameter specifies the model that gets created in signup (typically a user or account model).  A model with migration is created, as well as a basic controller with the create method.

The second parameter specifies the sessions controller name.  This is the controller that handles the actual login/logout function on the site.

The third parameter (--include-activation) generates the code for a ActionMailer and its respective Activation Code through email.

You can pass --skip-migration to skip the user migration.

From here, you will need to add the resource routes in config/routes.rb.

  map.resources :users, :sessions

Also, add an observer to config/environment.rb if you chose the --include-activation option
  config.active_record.observers = :user_observer # or whatever you named your model

jake@jake-laptop:~/src/pente$</pre>
<p>This plugin adds a generator for making RESTful authentication systems. Let&#8217;s use it to add a players resource using this generator:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ script/generate authenticated player sessions -p

----------------------------------------------------------------------
Don't forget to:

  - add restful routes in config/routes.rb
    map.resources :players, :sessions
    map.activate '/activate/:activation_code', :controller =&gt; 'players', :action =&gt; 'activate'

Try these for some familiar login URLs if you like:

  map.signup '/signup', :controller =&gt; 'players', :action =&gt; 'new'
  map.login  '/login', :controller =&gt; 'sessions', :action =&gt; 'new'
  map.logout '/logout', :controller =&gt; 'sessions', :action =&gt; 'destroy'

----------------------------------------------------------------------

      exists  app/models/
      exists  app/controllers/
      ... snip ...
      create  db/migrate
      create  db/migrate/001_create_players.rb
jake@jake-laptop:~/src/pente$</pre>
<p>It&#8217;s not hard to think of how to make players RESTful. Players map to resources quite easily. The authentication itself it a little trickier to think of RESTfully. Think about what you&#8217;re really doing when you login. You&#8217;re creating a login session. When you logout you&#8217;re destroying a login session. The login session itself is the REST resource.</p>
<p>Let&#8217;s add the REST resource to config/routes.rb, and while I&#8217;m at it I&#8217;ll clean it up a bit:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">ActionController::Routing::Routes.draw do |map|
  map.resource :players, :sessions
  # map.connect '', :controller =&gt; "welcome"
  map.connect ':controller/:action/:id.:format'
  map.connect ':controller/:action/:id'
end</pre>
<p>Now let&#8217;s run the players migration generated for us:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ rake db:migrate
(in /home/jake/src/pente)
== CreatePlayers: migrating ===================================================
-- create_table("players", {:force=&gt;true})
   -&gt; 0.0072s
== CreatePlayers: migrated (0.0073s) ==========================================

jake@jake-laptop:~/src/pente$</pre>
<p>And now let&#8217;s run the generated tests to make sure everything is working:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ rake
(in /home/jake/src/pente)
/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb" "test/unit/player_test.rb"
Loaded suite /var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader
Started
.............
Finished in 0.088721 seconds.

13 tests, 26 assertions, 0 failures, 0 errors
/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/functional/players_controller_test.rb"
Loaded suite /var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader
Started
..............
Finished in 0.127973 seconds.

14 tests, 26 assertions, 0 failures, 0 errors
/usr/bin/ruby1.8 -Ilib:test "/var/lib/gems/1.8/gems/rake-0.7.3/lib/rake/rake_test_loader.rb"
jake@jake-laptop:~/src/pente$</pre>
<p>And there it is. We&#8217;ve got a fully working authentication and signup mechanism! Let&#8217;s take a look at what was generated to understand what is really going on.</p>
<p>First Let&#8217;s look at the migration:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">class CreatePlayers  true do |t|
      t.column :login,                     :string
      t.column :email,                     :string
      t.column :crypted_password,          :string, :limit =&gt; 40
      t.column :salt,                      :string, :limit =&gt; 40
      t.column :created_at,                :datetime
      t.column :updated_at,                :datetime
      t.column :remember_token,            :string
      t.column :remember_token_expires_at, :datetime

    end
  end

  def self.down
    drop_table "players"
  end
end</pre>
<p>Some of the columns&#8217; functions are pretty obvious (login, email, created_at, updated_at), but if you haven&#8217;t designed an authentication system before (I hadn&#8217;t really either) the other columns might be a bit of a puzzle.</p>
<ul>
<li><strong>crypted_password</strong> &#8211; Well it&#8217;s not really encrypted, it&#8217;s a hash of the password. A hash cannot be directly decrypted back to the original password, but you can apply the same hash algorithm to the password given at login and determine if the hashes match. This way we don&#8217;t store the users&#8217; actual passwords which makes for better security. Even if the hash database were stolen it would take a lot of processing power to determine even one user&#8217;s true password.</li>
<li><strong>salt</strong> &#8211; If the hashed password list is somehow stolen it is possible to use precomputed hash dictionaries to get weak passwords that are dictionary words or other obvious things. when the user picks or changes a password a random string is generated and stored in the salt column. Before the password hash is generated the salt is concatenated with the plaintext password. This means that even though two users might have the same password the randomly generated salt would mean they have different hashes. Therefore you can&#8217;t just calculate the hash for &#8220;password&#8221; and scan for matching hashes.</li>
<li><strong>remember_token</strong> &#8211; Instead of logging in every time the user visits the site a randomly generated token can be stored in a cookie in the user&#8217;s browser. This cookie is checked when the user visits the site and the user is automatically authenticated if the match.</li>
<li><strong>remember_token_expires_at</strong> &#8211; Whenever the token is checked this column is also checked to make sure that the token hasn&#8217;t expired. If it has then the user must be authenticated through standard means.</li>
</ul>
<p>The generator adds a couple of files in lib for us. libs/authenticated_system.rb contains methods useful for inclusion in methods, controllers and views. lib/authenticated_test_helper.rb contains methods useful for testing controllers that require authentication.</p>
<p>Here are some of the highlights:</p>
<p>lib/authenticated_system.rb</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">    def logged_in?
      current_player != :false
    end
...
    def current_player
      @current_player ||= (session[:player] &amp;&amp; Player.find_by_id(session[:player])) || :false
    end</pre>
<p>The above methods are commonly referenced in the view and controller to determine if the user is logged in and if so who&#8217;s logged in.</p>
<p>lib/authenticated_system.rb</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">    def login_required
      username, passwd = get_auth_data
      self.current_player ||= Player.authenticate(username, passwd) || :false if username &amp;&amp; passwd
      logged_in? &amp;&amp; authorized? ? true : access_denied
    end
...
    def login_from_cookie
      return unless cookies[:auth_token] &amp;&amp; !logged_in?
      user = Player.find_by_remember_token(cookies[:auth_token])
      if user &amp;&amp; user.remember_token?
        user.remember_me
        self.current_player = user
        cookies[:auth_token] = { :value =&gt; self.current_player.remember_token , :expires =&gt; self.current_player.remember_token_expires_at }
        flash[:notice] = "Logged in successfully"
      end
    end</pre>
<p>The above methods are intended to be used as <a href="http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000180">before_filter</a>s for classes that need authentication.</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">module AuthenticatedTestHelper
  # Sets the current player in the session from the player fixtures.
  def login_as(player)
    @request.session[:player] = player ? players(player).id : nil
  end
...
  # Assert the block redirects to the login
  #
  #   assert_requires_login(:bob) { |c| c.get :edit, :id =&gt; 1 }
  #
  def assert_requires_login(login = nil)
    yield HttpLoginProxy.new(self, login)
  end</pre>
<p>The above methods can be very useful when testing controllers that use authentication.</p>
<p>The generator gave us two resources. The sessions resource is a sort of &#8220;virtual&#8221; resource that doesn&#8217;t actually have a table in the database or a model but does have a controller and views. The players resource is more standard and has a table, model controller, and views.</p>
<p>We should move the includes from the two generated controllers to the application controller as shown. This way all controllers will have access to the helper methods:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">class ApplicationController &lt; ActionController::Base
  include AuthenticatedSystem
  before_filter :login_from_cookie

  # Pick a unique cookie name to distinguish our session data from others'
  session :session_key =&gt; '_pente_session_id'
end</pre>
<p>We should also move the includes from the two generated controller functional tests to the test_helpers.rb so they will be available from all tests.</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'test_help'

class Test::Unit::TestCase
  ...snip...

  # Add more helper methods to be used by all tests here...
  include AuthenticatedTestHelper
end</pre>
<p>The last thing the generator gave us was a set of tests and test fixtures to exercise the generated code. These are the tests we ran earlier.</p>
<p>We can experiment with signing up for accounts and logging in by starting WEBrick:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">jake@jake-laptop:~/src/pente$ script/server
=&gt; Booting WEBrick...
=&gt; Rails application started on http://0.0.0.0:3000
=&gt; Ctrl-C to shutdown server; call with --help for options
[2007-05-05 18:03:17] INFO  WEBrick 1.3.1
[2007-05-05 18:03:17] INFO  ruby 1.8.5 (2006-08-25) [i486-linux]
[2007-05-05 18:03:17] INFO  WEBrick::HTTPServer#start: pid=8278 port=3000</pre>
<p>Open your browser and load <a href="http://localhost:3000/players/new">http://localhost:3000/players/new</a> and create an account. You can now log in at <a href="http://localhost:3000/sessions/new">http://localhost:3000/sessions/new</a>. There isn&#8217;t much to see yet when you log on. You will simply be redirected to the default Rails page. If you use an invalid account to login you will not be redirected.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/7/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/7/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/7/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=7&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/05/04/our-journey-begins-players/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>RESTing on Rails isn&#8217;t as Dangerous as it Sounds</title>
		<link>http://railsquest.wordpress.com/2007/05/02/resting-on-rails-isnt-as-dangerous-as-it-sounds/</link>
		<comments>http://railsquest.wordpress.com/2007/05/02/resting-on-rails-isnt-as-dangerous-as-it-sounds/#comments</comments>
		<pubDate>Wed, 02 May 2007 19:38:00 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[design decisions]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/05/02/resting-on-rails-isnt-as-dangerous-as-it-sounds/</guid>
		<description><![CDATA[I have decided to try and use REST design for my Pente project, and the purpose of this post is to ground readers on how I came to that decision.
There I was beginning to get comfortable with Rails. I was just starting to think I was hot stuff because I was learning the latest and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=8&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I have decided to try and use REST design for my Pente project, and the purpose of this post is to ground readers on how I came to that decision.<span id="more-8"></span></p>
<p>There I was beginning to get comfortable with Rails. I was just starting to think I was hot stuff because I was learning the latest and greatest web framework on the tubes. Then I saw all this stuff about RESTful this and RESTful that. Well it turns out REST is yet another whole new can of worms.</p>
<h3>ZZZZZZZZZZZZzzzz</h3>
<p>No, RESTful Rails doesn&#8217;t involve closing your eyes while you program. REST stands for REpresentational State Transfer and was coined by <a href="http://www.ics.uci.edu/%7Efielding/">Dr. Roy Fielding</a> in his <a href="http://www.ics.uci.edu/%7Efielding/pubs/dissertation/top.htm">doctoral dissertation</a>. Dr. Fielding is no slouch. Have you heard of the Apache webserver? He&#8217;s a co-founder. In his dissertation he essentially suggests we stick to the fundamental ideas in the <a href="http://en.wikipedia.org/wiki/Http">HTTP</a> <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">standard</a> when designing interactive web applications.</p>
<p>Most webpages today use two of the verbs HTTP defines: GET and POST. However, HTTP defines several others: HEAD, PUT, TRACE, DELETE, OPTIONS and CONNECT that aren&#8217;t supported by <a href="http://www.w3.org/TR/html401/">HTML</a> forms and therefore not actively used in today&#8217;s web apps. REST design makes use of GET, POST, PUT and DELETE. REST also emphasizes the idea that the <a href="http://en.wikipedia.org/wiki/Uniform_Resource_Identifier">URI</a> should not contain any verbs, only nouns and maybe some adjectives. <strong>The URI tells us what we&#8217;re doing something with</strong> and <strong>the HTTP verb tells us what to do with it</strong>.</p>
<p>Examples of non-RESTful URIs:</p>
<ul>
<li>/employees.php?id=5&amp;action=delete</li>
<li>/records/admin/create?documentid=45</li>
<li>/users/1;edit</li>
<li>/edit/users/1</li>
</ul>
<p>Examples of RESTful URIs:</p>
<ul>
<li>/users</li>
<li>/users/admins</li>
<li>/users/1</li>
<li>/users.php?id=1</li>
<li>/posts/1/12/2007/my_day</li>
<li>/posts/1/12/2007/my_day/comments</li>
<li>/posts/1/12/2007/my_day/comments/5</li>
<li>/posts/random</li>
</ul>
<p>These RESTful URIs don&#8217;t really mean anything by themselves. For a webapp to service a request it needs to know <strong>what it should do something with</strong> and <strong>what to do with it</strong>. The URI tells you the former. With just the URI you <em>cannot</em> know what the client wants!</p>
<p>To get the complete story you also need to know the verb:</p>
<table border="1">
<tr>
<th>HTTP Verb</th>
<th>Meaning</th>
</tr>
<tr>
<td>GET</td>
<td>Receive a representation of the resource in the URI without changing <strong>anything</strong></td>
</tr>
<tr>
<td>POST</td>
<td>Create a new representation of the resource in the URI</td>
</tr>
<tr>
<td>PUT</td>
<td>Update an existing representation of the resource in the URI with new data</td>
</tr>
<tr>
<td>DELETE</td>
<td>Remove the resource identified in the URI</td>
</tr>
</table>
<p>These should sound familiar to you. You&#8217;ve probably learned that Rails is designed around the idea of CRUD (Create, Read, Update, Destroy). Well these actions map quite well to the REST HTTP verbs.</p>
<table border="1">
<tr>
<th>HTTP Verb</th>
<th>CRUD mapping</th>
</tr>
<tr>
<td>POST</td>
<td>Create</td>
</tr>
<tr>
<td>GET</td>
<td>Read</td>
</tr>
<tr>
<td>PUT</td>
<td>Update</td>
</tr>
<tr>
<td>DELETE</td>
<td>Destroy</td>
</tr>
</table>
<h3>Why?</h3>
<p>Now you know what REST is, but so what? Why does it make a better app? There are many reasons. My favorite reason is that (at least in Rails) you get a nearly free web API by following RESTful techniques. Here&#8217;s a little bit of code generated for a games controller by Rails&#8217; REST resource generator:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;"># GET /games/1
# GET /games/1.xmldef show @game = Game.find(params[:id])
respond_to do |format|
  format.html # show.rhtml
  format.xml  { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&gt; @game.to_xml }
end</pre>
<p>The respond_to method make it easy to render the data in different ways. The RESTful generators automatically give you two formats: the standard HTML and a new XML format. Thanks to the .to_xml method we get built in on our models we just got a one line web API for this resource! REST is also just a good way to think about designing your app. If you use the REST design principles correctly it&#8217;s hard to end up with an ugly design. Finally by using the HTTP verbs as they are intended the browser and any proxies and routers that are relaying your HTTP between the client and server can do more intelligent caching with the data.</p>
<h3>Just a minute here&#8230;</h3>
<p>Remember how I said REST uses four HTTP verbs, but HTML only uses two? How can we write forms that delete or update resources if we can&#8217;t use the PUT and DELETE verbs? Well we really can&#8217;t be truly RESTful. Currently RAILS sort of sneaks the PUT and DELETE verbs in by assigning a &#8220;_method&#8221; parameter to fake it when setting up a form. My initial reaction to this was &#8220;yuck!&#8221;, and it still is, but I think it might be worth it. There is lots of <a href="http://pragdave.pragprog.com/pragdave/2007/03/the_radar_archi.html">ongoing</a> <a href="http://blog.roberthahn.ca/articles/2007/04/06/url-design">discussion</a> <a href="http://dev.rubyonrails.org/changeset/6485">about</a> the issue, but I&#8217;m not sure there will be a great solution until the HTML spec supports PUT and DELETE. In fact one of the URI&#8217;s I gave in the list of non-RESTful (/users/1;edit) is one that Rails uses when you generate a REST resource because nobody has come up with a perfect solution yet.</p>
<p>Don&#8217;t forget about one of REST&#8217;s big benefits. When used as a Web API you aren&#8217;t limited to GET and POST verbs. Any HTTP library worth its salt can make PUT and DELETE requests as well so there is no Javascript hackery involved. To experiment with a REST API you can use <a href="http://curl.haxx.se/">cURL</a> (<a href="http://curl.haxx.se/docs/manpage.html">manpage</a>) to generate pretty much any HTTP request you want.</p>
<p>Since it sounds like such a neat idea, and I&#8217;d like to have a web API for my Pente project I&#8217;m going to go ahead with REST design. I might get sick of all the javascript hacks and decide REST isn&#8217;t worth it, but I&#8217;m going to give it a shot.</p>
<h3>Questions</h3>
<ul>
<li>What do you think about REST?</li>
<li>Do you think Dave&#8217;s <a href="http://pragdave.pragprog.com/pragdave/2007/03/the_radar_archi.html">RADAR</a> is the correct answer to HTML&#8217;s failings?</li>
<li>How would you get around HTML&#8217;s limitations to implement a REST design?</li>
</ul>
<h3>Want to Learn More about REST?</h3>
<p>This post doesn&#8217;t cover the technical details of how to use REST in your rails application because there are already other resources that do a great job of that.</p>
<ul>
<li><a href="http://peepcode.com/">Peepcode</a> has a great <a href="http://peepcode.com/products/restful-rails">screencast</a> on REST I would highly recommend, the $9 is a steal.</li>
<li><a href="http://www.xml.com">XML.com</a> has a good <a href="http://www.xml.com/pub/a/2005/11/02/rest-on-rails.html">article</a> on RESTful Rails</li>
<li><a href="http://topfunky.com">Topfunky</a> has a good <a href="http://topfunky.com/clients/peepcode/REST-cheatsheet.pdf">Cheetsheet</a> for RESTful Rails development</li>
</ul>
<h3>Where to Next?</h3>
<p>Look at my decision to use <a href="/2007/05/02/would-you-jump-before-you-checked-your-parachute/">test driven development</a> for Pente or <a href="/tag/pente/">follow along</a> as I implement the project.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/8/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/8/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/8/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/8/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/8/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=8&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/05/02/resting-on-rails-isnt-as-dangerous-as-it-sounds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>Would you Jump Before you Checked your Parachute?</title>
		<link>http://railsquest.wordpress.com/2007/05/02/would-you-jump-before-you-checked-your-parachute/</link>
		<comments>http://railsquest.wordpress.com/2007/05/02/would-you-jump-before-you-checked-your-parachute/#comments</comments>
		<pubDate>Wed, 02 May 2007 07:59:00 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[design decisions]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/05/02/would-you-jump-before-you-checked-your-parachute/</guid>
		<description><![CDATA[Software engineering has one big difference from all other engineering disciplines. If a civil engineer built a bridge without going through computer simulations, scale models, and rigorous review he would be jailed. If an aerospace engineer thought he found a new wing design and threw it on a passenger jet to see if it would [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=5&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Software engineering has one big difference from all other engineering disciplines. If a civil engineer built a bridge without going through computer simulations, scale models, and rigorous review he would be <a href="http://www.icivilengineer.com/News/news.php?id=7786">jailed</a>. If an aerospace engineer thought he found a new wing design and threw it on a passenger jet to see if it would work he and his grandchildren would be barred from engineering forever. Nobody thinks twice when a software engineer whips up a new function and runs it to see if it works. In this post I&#8217;ll introduce the concept of test driven development and explain why I will be using it for my Pente project.<span id="more-5"></span></p>
<p>Part of the agile/extreme programming movement is the notion of <a href="http://en.wikipedia.org/wiki/Test-driven_development">test driven development</a> (TDD). The crux of the idea is that before you write any application code you should first write a test that fails because the code doesn&#8217;t exist. The big idea is <strong><span style="color:red;">Red</span>, <span style="color:green;">Green</span>, <em>Refactor</em></strong>. The official dogmatic TDD method is a bit more strict than I will demonstrate here, but this is how I have personally found the ideas of TDD to be useful.</p>
<p>This article assumes you are familiar with the basic Unit Testing features of Rails. There is a <a href="http://manuals.rubyonrails.com/read/book/5">great resource</a> on the Rails wiki that will help you learn what you need.</p>
<p>I highly recommend the book <a href="http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530/">Test Driven Development by Example</a>. It does a great job of introducing the need for test driven development and introducing the technique step by step.</p>
<h3>1: <span style="color:red;">Red</span></h3>
<p>So you want your program to do something. Let&#8217;s say you want your Player model to validate the format of the email address. The first step is to write a test that fails because the Player model doesn&#8217;t validate the format of the email address.</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">def test_validate_email_invalid
  p = Player.new
  p.email = '@bedrock.com'
  assert !p.valid?
end</pre>
<p>Run the test and watch it fail miserably. You&#8217;re now in the <span style="color:red;"><strong>red</strong></span>! Don&#8217;t worry though, this is a good thing. You&#8217;re making progress. You&#8217;ve now defined how you want your code to work. You also know that your test fails properly. This is really important. If you write a test and never actually see it fail how do you know the test is working? The next step is to make it pass!</p>
<h3>2: <span style="color:green;">Green</span></h3>
<p>The official dogmatic TDD approach is to write the dirtiest, ugliest, quickest code you can that will make your test pass. Personally I think that&#8217;s a bit much. One of the nice things about TDD is that if you are having trouble with a certain section of code, or want to be <em>really</em> sure that a piece of code is working perfectly you can always slow down and start doing really detailed tests, but if you&#8217;ve done a thing a thousand times and know it will probably work right away you can test in big chunks.</p>
<p>Let&#8217;s make our email validation test pass by adding this code to our model:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">validates_format_of :email, :with =&gt; /.+@.+..+/</pre>
<p>Run your test again and you&#8217;ll see that we&#8217;re passing! We&#8217;re back in the <span style="color:green;"><strong>green</strong></span>!</p>
<h3>3: <em>Refactor</em></h3>
<p>In the refactor phase you get the chance to make your code nicer. You can break out functions/classes and make your code look nicer. Since you&#8217;ve got all the things your code is supposed to do under test you&#8217;ll know you aren&#8217;t breaking any established functionality. Don&#8217;t forget to refactor the tests themselves too. Our example isn&#8217;t really complicated enough yet to require any refactoring, so let&#8217;s move on and dig ourselves back in the red.</p>
<h3>4: <span style="color:red;"><strong>Red</strong></span></h3>
<p>Our simple test got us some basic email validation, but there are still lots of bad addresses that will get through. Let&#8217;s improve it a bit:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">def test_validate_email_invalid
  p = Player.new
  p.email = 'fl1nst0n3@bedr0ck.c0m'
  assert !p.valid?
  p.email = 'fflinstone@bedrock.theoffice'
  assert !p.valid?
  p.email = 'fflinstone'
  assert !p.valid?
  p.email = 'fflinstone@bedrock'
  assert !p.valid?
  p.email = '@bedrock.com'
  assert !p.valid?
  p.email = 'fflinstone@bedrock.c'
  assert !p.valid?
  p.email = 'fflin@stone@bedrock.com'
  assert !p.valid?
  p.email = 'fflinstone@bed_rock.com'
  assert !p.valid?
  p.email = 'fflinstone@bedrock..com'
  assert !p.valid?
  p.email = ''
  assert !p.valid?
  p.email = nil
  assert !p.valid?
end

def test_validate_email_valid
  p = Player.new
  p.email = 'fflinstone@bedrock.com'
  assert p.valid?
  p.email = 'fflinstone@bedrock.co.uk'
  assert p.valid?
  p.email = 'fflin_ston-e@bed-rock.com'
  assert p.valid?
  p.email = 'fflinstone@bedrock.museum'
  assert p.valid?
  p.email = 'fl1nst0n3@bedr0ck.com'
  assert p.valid?
  p.email = 'FLiN570nE@B3dR0ck.com'
  assert p.valid?
end</pre>
<p>The modified test takes a big chunk out of our email validation problem by throwing in a whole bunch of possible problems with an email address. I took a bigger chunk because I have a <a href="http://www.regular-expressions.info/email.html">regular expression</a> that I&#8217;ve used before that I&#8217;m confident will solve this on the first try. If I didn&#8217;t I might just throw one problem in at a time and build a regular expression that would solve each new problem while not breaking old ones.</p>
<h3>5: <span style="color:green;"><strong>Green</strong></span></h3>
<p>Here&#8217;s the new code for the model:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">validates_format_of :email, :with =&gt; /A[A-Z0-9._%-]+@(?:[A-Z0-9-]+.)+[A-Z]{2,6}Z/i</pre>
<p>We should be passing all of our tests again, but the tests are a bit ugly, let&#8217;s move on.</p>
<h3>6: <em>Refactor</em></h3>
<p>Now we can make our test code look a little nicer:</p>
<pre style="border:thin solid black;background-color:#eeeeee;padding:1em;">def test_validate_email_invalid
  p = Player.new
  ['fl1nst0n3@bedr0ck.c0m',
   'fflinstone@bedrock.theoffice',
   'fflinstone',
   'fflinstone@bedrock',
   '@bedrock.com',
   'fflinstone@bedrock.c',
   'fflin@stone@bedrock.com',
   'fflinstone@bed_rock.com',
   'fflinstone@bedrock..com',
   '',
   nil].each do |bad_email|
    p.email = bad_email
    assert !p.valid?
  end
end

def test_validate_email_valid
  p = Player.new
  ['fflinstone@bedrock.com',
   'fflinstone@bedrock.co.uk',
   'fflin_ston-e@bed-rock.com',
   'fflinstone@bedrock.museum',
   'fl1nst0n3@bedr0ck.com',
   'FLiN570nE@B3dR0ck.com'].each do |good_email|
    p.email = good_email
    assert p.valid?
  end
end</pre>
<h3>Now What?</h3>
<p>Keep adding tests to express the desired behavior of your code, then make those tests pass. You&#8217;ll wind up with a fully tested codebase that makes adding new features and refactoring the code a dream because you can run the tests to know what functionality you&#8217;ve changed.</p>
<p>TDD is very hard at first, but if you stay committed and keep writing your tests before the code that makes them work it will become a natural process and writing untested code will start to give you the shivers.</p>
<h3>Questions</h3>
<ul>
<li>What do you think about TDD?</li>
<li>If you&#8217;ve used TDD in a project how did it go?</li>
<li>Have you ever had to refactor testless code?</li>
</ul>
<h3>Where to Next?</h3>
<p>Read about my decision to use <a href="/2007/05/02/resting-on-rails-isnt-as-dangerous-as-it-sounds/">RESTful design</a> or follow along as I <a href="/tag/pente/">implement</a> the project.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/5/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/5/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/5/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=5&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/05/02/would-you-jump-before-you-checked-your-parachute/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
		<item>
		<title>All Aboard! Getting Started with Rails</title>
		<link>http://railsquest.wordpress.com/2007/05/02/all-aboard-getting-started-with-rails/</link>
		<comments>http://railsquest.wordpress.com/2007/05/02/all-aboard-getting-started-with-rails/#comments</comments>
		<pubDate>Wed, 02 May 2007 06:07:00 +0000</pubDate>
		<dc:creator>Jake Brownson</dc:creator>
				<category><![CDATA[getting started]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://railsquest.wordpress.com/2007/05/02/all-aboard-getting-started-with-rails/</guid>
		<description><![CDATA[I&#8217;m not going to try and recreate the wonderful getting started with Rails documents that exist all over the web. Instead I&#8217;m going to point you to the resources I found the most helpful when I started looking at Rails.
First: &#8220;Get Excited&#8221;!
Before we dig into the bowels of Ruby and Rails let&#8217;s get a taste [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=6&subd=railsquest&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;m not going to try and recreate the wonderful getting started with Rails documents that exist all over the web. Instead I&#8217;m going to point you to the resources I found the most helpful when I started looking at Rails.<span id="more-6"></span></p>
<h3>First: &#8220;Get Excited&#8221;!</h3>
<p>Before we dig into the bowels of Ruby and Rails let&#8217;s get a taste of what it is we&#8217;re doing here. What&#8217;s so great about Rails? Does anybody actually use Rails?</p>
<ol>
<li>Watch the official <a href="http://rubyonrails.org/screencasts">screencasts</a>. They will give you a taste of what Rails is about quickly and visually.</li>
<li>One of the big questions I had when looking at Rails was: &#8220;Does this actually work in production?&#8221; The best way to answer this question is to show <a href="http://wiki.rubyonrails.com/rails/pages/RealWorldUsage">production websites</a> that use Rails.</li>
</ol>
<h3>Next: Build a Solid Foundation</h3>
<p>When I came to Rails I was mainly a C++ programmer. I had dabbled in PHP and other scripting languages, but Ruby was a completely new language to me. It was difficult to read some of the code in the Rails tutorials without knowing some of the unique Ruby syntax.</p>
<ol>
<li>At this point it&#8217;s not necessary to completely learn Ruby before starting on Rails, but it is valuable to pick up on some of the basics. Luckily there is a fantastic <a href="http://tryruby.hobix.com/">interactive tutorial</a> that has you covered.</li>
<li>Finally let&#8217;s get started with some basic Rails. There is a good list of tutorials at <a href="http://www.digitalmediaminute.com/article/1816/top-ruby-on-rails-tutorials">Top 12 Ruby on Rails Tutorials</a>. My favorite is #3 <a href="http://rails.homelinux.org/">Four Days on Rails</a>, but your tastes may vary. Try a few and see what sticks.</li>
</ol>
<h3>Then: Getting Help</h3>
<p>Once you&#8217;ve gone through the basic tutorials and understand the fundamentals of Ruby on Rails you&#8217;ll want to start writing code. At first it can be difficult to understand how to find the method you&#8217;re looking for, or what the error message you&#8217;re getting means, but there is help.</p>
<ol>
<li>Though daunting at first, the <a href="http://api.rubyonrails.org">API reference</a> is extremely helpful once you learn to use it. Spend some time browsing through the classes and functions to get an idea of what is available.</li>
<li>The #rubyonrails IRC channel on irc.freenode.net is generally filled with friendly, helpful folks that are willing to answer stupid questions (don&#8217;t ask how I know). Even if you just spend some time lurking in the channel you&#8217;ll pick up all sorts of good tips.</li>
<li>If you&#8217;ve got a real stumper try the <a href="http://groups.google.com/group/rubyonrails-talk">official group</a>.</li>
</ol>
<h3>And Beyond: The Path to Enlightenment</h3>
<p>Thirsty for more? Here&#8217;s some resources that will help you with your Rails fix.</p>
<ol>
<li><a href="http://www.railscasts.com">Railscasts</a> is a fantastic weekly screencast that gives a great tip every week with a high quality video.</li>
<li>Another very high quality Rails screencast site is <a href="http://www.peepcode.com">Peepcode</a>. They cost $9 each but go into good depth on the topics they cover and are well worth the price.</li>
<li>The <a href="http://podcast.rubyonrails.org/">Rails Podcast</a> is a great way to get a sense of the Rails community. You get to hear prominent Rails developers talking about how they use Rails.</li>
<li>There are <a href="http://pragdave.pragprog.com/pragdave">several</a> <a href="http://nubyonrails.com/">great</a> <a href="http://weblog.rubyonrails.org/">blogs</a> <a href="http://www.loudthinking.com/">about</a> Rails that are quite worth reading.</li>
</ol>
<h3>Questions</h3>
<ul>
<li>What&#8217;s your favorite Rails related resource?</li>
</ul>
<h3>Where to next?</h3>
<p>You might want to look at some of the <a href="/tag/design-decisions/">design decisions</a> I made about my project or <a href="/tag/pente/">follow along</a> as I implement the project.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/railsquest.wordpress.com/6/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/railsquest.wordpress.com/6/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/railsquest.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/railsquest.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/railsquest.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/railsquest.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/railsquest.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/railsquest.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/railsquest.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/railsquest.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/railsquest.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/railsquest.wordpress.com/6/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=railsquest.wordpress.com&blog=1061775&post=6&subd=railsquest&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://railsquest.wordpress.com/2007/05/02/all-aboard-getting-started-with-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/41c75e51e98c012d34a3f0d63f6e9f5a?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jbrownson</media:title>
		</media:content>
	</item>
	</channel>
</rss>