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’re logged in or not.
Let’s go ahead and generate the controller:
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$
Let’s add an index action. Since we’re using TDD let’s add a functional test in test/functional/welcome_controller_test.rb that fails because we don’t have one:
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 < 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
Run the test:
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$
Alright we’re in the red now so let’s implement the code:
app/controllers/welcome_controller.rb:
class WelcomeController < ApplicationController def index end end
app/views/welcome/index.rhtml:
Welcome!
Run the test agan and we’re in the green:
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$
Before we forget let’s get rid of the public/index.html file so when we use WEBrick we get the correct page. The file doesn’t hurt the tests, but this is a good time to remove it anyway, and while we’re at it we’ll map our welcome controller to ” so it shows up by default:
jake@jake-laptop:~/src/pente$ rm public/index.html jake@jake-laptop:~/src/pente$
config/routes.rb:
ActionController::Routing::Routes.draw do |map| map.resource :players, :sessions map.connect '', :controller => "welcome" map.connect ':controller/:action/:id.:format' map.connect ':controller/:action/:id' end
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’s add some tests to check for this functionality. I’m adding more than one test at a time here to speed things up since this is pretty basic:
test/functional/welcome_controller_test.rb:
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 => {'href' => x}
end
end
def test_should_have_links_when_logged_in
login_as 'aaron'
get :index
['/sessions/destroy'].each do |x|
assert_tag :tag => 'a', :attributes => {'href' => x}
end
end
end
I’ve been doing a lot of thinking about REST and I think I’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’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’m not disabling the REST interface, and the HTML doesn’t have the ugly hacks.
Now let’s make them pass by modifying app/views/welcome/index.rhtml:
<ul> <% if logged_in? -%> <li><a href='/sessions/destroy'>Logout</a></li> <% else -%> <li><a href='/sessions/new'>Login</a></li> <li><a href='/players/new'>Signup</a></li> <% end -%> </ul>
We’re now back in the green with a working welcome controller! From here on out I’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’t actually seen it in the browser. That’s one of the great things about TDD. You don’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 see for yourself!
I’m going to be saving all the HTML/CSS prettification for the end of the project and keep the interfaces plain for now.
In the next post I’ll add a games resource and tie it to the players resource.
Pull out…
Comment by Follow this — June 10, 2008 @ 7:32 am