Tuesday, December 14, 2010

sqlite3-ruby 1.3.2 on Windows 'Error'

When I created a new rails app ran bundle install I noticed a new version of sqlite3-ruby was installed.

...
Installing sqlite3-ruby (1.3.2)
...

When I tried to start the server I got this message.

C:\web\testapp>rails s
C:/Ruby192/lib/ruby/gems/1.9.1/gems/sqlite3-ruby-1.3.2-x86-mingw32/lib/sqlite3.rb:6:in `require': no such file to load -- sqlite3/sqlite3_native (Load Error)
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/sqlite3-ruby-1.3.2-x86-mingw32/lib/sqlite3.rb:6:in `rescue in <top (required)>'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/sqlite3-ruby-1.3.2-x86-mingw32/lib/sqlite3.rb:2:in `<top (required)>'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/bundler-1.0.7/lib/bundler/runtime.rb:64:in `require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/bundler-1.0.7/lib/bundler/runtime.rb:64:in `block (2 levels) in require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/bundler-1.0.7/lib/bundler/runtime.rb:62:in `each'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/bundler-1.0.7/lib/bundler/runtime.rb:62:in `block in require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/bundler-1.0.7/lib/bundler/runtime.rb:51:in `each'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/bundler-1.0.7/lib/bundler/runtime.rb:51:in `require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/bundler-1.0.7/lib/bundler.rb:112:in `require'
from C:/web/testapp/config/application.rb:7:in `<top (required)>'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.3/lib/rails/commands.rb:28:in `require'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.3/lib/rails/commands.rb:28:in `block in <top (required)>'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.3/lib/rails/commands.rb:27:in `tap'
from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.3/lib/rails/commands.rb:27:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'

I thought I'd reinstall it, since that's what one does on windows, and I got some more information.

C:\web\testapp>gem install sqlite3-ruby

=============================================================================

You've installed the binary version of sqlite3-ruby.
It was built using SQLite3 version 3.7.3.
It's recommended to use the exact same version to avoid potential issues.

At the time of building this gem, the necessary DLL files where available
in the following download:

http://www.sqlite.org/sqlitedll-3_7_3.zip

You can put the sqlite3.dll available in this package in your Ruby bin
directory, for example C:\Ruby\bin

=============================================================================

Successfully installed sqlite3-ruby-1.3.2-x86-mingw32
1 gem installed
Installing ri documentation for sqlite3-ruby-1.3.2-x86-mingw32...
Installing RDoc documentation for sqlite3-ruby-1.3.2-x86-mingw32...


Let's look at what was installed.

C:\web\testapp>gem list --local -d sql

*** LOCAL GEMS ***

sqlite3-ruby (1.3.2)
Platform: x86-mingw32
Authors: Jamis Buck, Luis Lavena, Aaron Patterson
Rubyforge: http://rubyforge.org/projects/sqlite3-ruby
Homepage: http://github.com/luislavena/sqlite3-ruby
Installed at: C:/Ruby192/lib/ruby/gems/1.9.1

This module allows Ruby programs to interface with the SQLite3
database engine (http://www.sqlite.org)

I downloaded the file at http://www.sqlite.org/sqlitedll-3_7_3.zip and copied the DLL into my C:\Ruby192\bin folder since that's where I have it installed.

Let's give it a try

C:\web\testapp>rails s
=> Booting WEBrick
=> Rails 3.0.3 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-12-14 11:37:09] INFO WEBrick 1.3.1
[2010-12-14 11:37:09] INFO ruby 1.9.2 (2010-08-18) [i386-mingw32]
[2010-12-14 11:37:09] INFO WEBrick::HTTPServer#start: pid=2080 port=3000
[2010-12-14 11:37:56] INFO going to shutdown ...
[2010-12-14 11:37:57] INFO WEBrick::HTTPServer#start done.

It works.

Tuesday, November 30, 2010

Make An HTML Version of the iPhone's Contact Screen.



Make An HTML Version of the iPhone's Contact Screen.

We want this, but not so blurry.
Image of iPhone contact page
I'm going to break it down with a heading, text and a list. I'll go with a definition list. We define the phone numbers, email and address.
Let's mark up the base.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Person</title>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
article, aside, details, figcaption, figure, footer, header,
hgroup, menu, nav, section { display: block; }
</style>
</head>
<body>
<h2>John Ivanoff</h2>
<p>Some Company</p>
<dl>
<dt>work</dt>
<dd>972-555-1212</dd>
<dt>home</dt>
<dd>972-555-1212</dd>
</dl>
<dl>
<dt>work</dt>
<dd><a href="mailto:unknown@unknown.org">unknown@unknown.org</a></dd>
</dl>
<dl>
<dt>work</dt>
<dd><a href="http://goo.gl/1nTU8">123 Chicago Ave<br/>Lebanon, KS 76051-7693 </a></dd>
</dl>
</body>
</html>
View it in a browser and we get.
screen shote of the base code
We have the foundation. Now let's add some style.
We'll start with the background of the page.
body {
background-color: #ddd; /* Background color */
color: #222; /* Foreground color used for text */
font-family: Helvetica;
font-size: 14px;
margin: 0; /* Amount of negative space around the outside of the body */
padding: 0; /* Amount of negative space around the inside of the body */
}
View it in a browser and we get.
screen shot with background CSS applied
Let's get the lists styled.
We'll add the white background and border.
dl {
list-style: none;
padding: 0;
}
dt, dd {
background-color: #fff; /* Background color */
color: #222222; /* Foreground color used for text */
border: 1px solid #999;
font-weight: bold;
margin: 0;
padding: 12px 10px;
}
dt:first-child {
-webkit-border-top-left-radius: 8px;
}
dt:first-child + dd { /* This rounds the first definition item */
-webkit-border-top-left-radius: 8px;
-webkit-border-top-right-radius: 8px;
}
dd:last-child {
-webkit-border-bottom-right-radius: 8px;
-webkit-border-bottom-left-radius: 8px;
}
View it in a browser.
screen shot with list formatted
We'll style the 'terms.' We'll make them 60 pixels wide, have the text align to the right and make it a little lighter in color.
dt {
color: #516691;
text-align: right;
width: 60px;
}
View it in a browser.
screen shot
Now we'll move up the 'definitions' so it looks like one line. We'll float the dt
dt {
float: left; /* this will 'bring up' the dd */
color: #516691;
text-align: right;
width: 60px;
}
View it in a browser.
screen shot
That doesn't look good. We'll remove the border on the dt and I'm picky here but I want to move the dt a little bit.
dt {
float: left; /* this will 'bring up' the dd */
border: 0; /* remove border */
padding-top: 13px; /* alignment tweaking */

color: #516691;
text-align: right;
width: 60px;
}
View it in a browser.
screen shot
That's a little better but the top left looks like crud. The remedy? Make the color of the dt transparent.
dt {
float: left; /* this will 'bring up' the dd */
border: 0; /* remove border */
padding-top: 13px; /* alignment tweaking */
color: #516691;
text-align: right;
width: 60px;
background-color: transparent; /* clears up the top left corner */
}
View it in a browser. Bam!
screen shot
Looking good.
Let's work on the name and company. We'll wrap a div around the contact name and company
.......
<div id="namecompany">
<h2>John Ivanoff</h2>
<p>Some Company</p>
</div>
.....
We'll add this image like the on for a contact without a photo
contact icon
div#namecompany{
padding-left: 90px; /* Makes room for the photo */
background: transparent url(../i/person-icon.png) 10px 0 no-repeat; /* This sets up the position of the image */
height: 70px; /* Set the height of the div */
}
div#namecompany h2, div#namecompany p {
margin: 0; /* Just smash it all together */
}
View it in a browser.
screen shote
We're starting to cook with gas. A few minor areas to touch up. We need padding around the page.
We can hack it and add a margin to the entire page. The problem with that is when we add a header or footer that will ruin the look. The header or footer will not span the width of the screen.
What about wrapping everything in a div content? That add unnecessary HTML.
For this simple layout I'll add the padding to the namecompany div and the lists
div#namecompany, dl {
margin: 10px;
}
View it in a browser.
screen shot
Smashing. Be'll make the phone numbers into links so we can call
...
<dl>
<dt>work</dt>
<dd><a href="tel:972-555-1212">972-555-1212</a></dd>
<dt>home</dt>
<dd><a href="tel:972-555-1213">972-555-1213</a></dd>
</dl>
...
View it in a browser.
screen shot
Let's hide those ugly links.
a {
text-decoration: none;
color: #000;
}
View it in a browser.
screen shot
With this current design if you have a really long email the email will wrap just like the address. In the contacts app on the iPhone long emails are truncated with a trailing ellipsis.
We'll add a home email and make it a really long email address and we'll add a class of email to the dd
...
<dl>
<dt>work</dt>
<dd class="email"><a href="mailto:unknown@unknown.org">unknown@unknown.org</a></dd>
<dt>home</dt>
<dd class="email"><a href="mailto:unknown.unknown@areallyreallyreallylongurl.org"> unknown.unknown@areallyreallyreallylongurl.org</a></dd>
</dl>
...
View it in a browser.
screen shot
That's not good.
Let's add an ellipsis to text that is too long for its container.
.email {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
View it in a browser.
screen shot
Still not good.
.email {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
width: inherit;

}

Update…

That code will render like the previous image.
Move the .email class into the a element. The a element should look like the following
a {
text-decoration: none;
color: #000;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
width: inherit;

}

Then remove the .email class from the <dd> for the emails,
Moving that code to the a element will also insure that any long text will be shortened to stay within the page.
View it in a browser.
screen shot
Hurray!
Let's add some finishing touches.
A title bar and the pinstriped background. Add this to the html code.
...
<h1>Info</h1>
...
Add to CSS code.
body {
background: #ddd url(../i/pinstripes.png) repeat scroll 0%;
color: #222; /* Foreground color used for text */
font-family: Helvetica;
font-size: 14px;
margin: 0; /* Amount of negative space around the outside of the body */
padding: 0; /* Amount of negative space around the inside of the body */
}
...
h1 {
color: #222;
font-size: 20px;
font-weight: bold;
margin: 0 auto;
padding: 10px 0;
text-align: center;
text-shadow: 0px 1px 0px #fff;
background-image: -webkit-gradient(linear, left top, left bottom,
from(#ccc), to(#999));
}
View it in a browser.
screen shot
There we go, a web page that looks like a native iPhone app.

Thursday, November 18, 2010

rails 3.0.3 and activerecord-sqlserver-adapter (3.0.5) error on windows

rails 3.0.1
Using activerecord-sqlserver-adapter (3.0.5)
SELECT TOP (1) [users].* FROM [users] WHERE ([users].[id] = 1)

rails 3.0.3
Using activerecord-sqlserver-adapter (3.0.5)
ActiveRecord::StatementInvalid (ODBC::Error: 37000 (102) [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'LIMIT'.:
SELECT [users].* FROM [users] WHERE ([users].[id] = N'1') LIMIT 1)
:

I just found this and I don't have a fix other than rolling back to 3.0.1

Wednesday, September 01, 2010

Ruby 1.9.2 Rails 3, A Clean Install on Windows XP

Down loaded rubyinstaller-1.9.2-p0.exe from http://rubyinstaller.org/ and installed it. (this will remove any previously installed gems)

C:>gem list --local

*** LOCAL GEMS ***

minitest (1.6.0)
rake (0.8.7)
rdoc (2.5.8)

Install RubyGems (http://rubygems.org/pages/download)

C:\>gem update --system
Updating RubyGems
Nothing to update

C:\>gem install rubygems-update
Successfully installed rubygems-update-1.3.7
1 gem installed
Installing ri documentation for rubygems-update-1.3.7...
Installing RDoc documentation for rubygems-update-1.3.7...

C:\>gem list --local

*** LOCAL GEMS ***

minitest (1.6.0)
rake (0.8.7)
rdoc (2.5.8)
rubygems-update (1.3.7)

Next install rails.

C:\>gem install rails
Successfully installed activesupport-3.0.0
Successfully installed builder-2.1.2
Successfully installed i18n-0.4.1
Successfully installed activemodel-3.0.0
Successfully installed rack-1.2.1
Successfully installed rack-test-0.5.4
Successfully installed rack-mount-0.6.13
Successfully installed tzinfo-0.3.23
Successfully installed abstract-1.0.0
Successfully installed erubis-2.6.6
Successfully installed actionpack-3.0.0
Successfully installed arel-1.0.1
Successfully installed activerecord-3.0.0
Successfully installed activeresource-3.0.0
Successfully installed mime-types-1.16
Successfully installed polyglot-0.3.1
Successfully installed treetop-1.4.8
Successfully installed mail-2.2.5
Successfully installed actionmailer-3.0.0
Successfully installed thor-0.14.0
Successfully installed railties-3.0.0
Successfully installed bundler-1.0.0
Successfully installed rails-3.0.0
23 gems installed
Installing ri documentation for activesupport-3.0.0...
Installing ri documentation for builder-2.1.2...
Installing ri documentation for i18n-0.4.1...
Installing ri documentation for activemodel-3.0.0...
Installing ri documentation for rack-1.2.1...
Installing ri documentation for rack-test-0.5.4...
Installing ri documentation for rack-mount-0.6.13...
Installing ri documentation for tzinfo-0.3.23...
Installing ri documentation for abstract-1.0.0...
Installing ri documentation for erubis-2.6.6...
Installing ri documentation for actionpack-3.0.0...
Installing ri documentation for arel-1.0.1...
Installing ri documentation for activerecord-3.0.0...
Installing ri documentation for activeresource-3.0.0...
Installing ri documentation for mime-types-1.16...
Installing ri documentation for polyglot-0.3.1...
Installing ri documentation for treetop-1.4.8...
Installing ri documentation for mail-2.2.5...
Installing ri documentation for actionmailer-3.0.0...
Installing ri documentation for thor-0.14.0...
Installing ri documentation for railties-3.0.0...
Installing ri documentation for bundler-1.0.0...
Installing ri documentation for rails-3.0.0...
Installing RDoc documentation for activesupport-3.0.0...
Installing RDoc documentation for builder-2.1.2...
Installing RDoc documentation for i18n-0.4.1...
Installing RDoc documentation for activemodel-3.0.0...
Installing RDoc documentation for rack-1.2.1...
Installing RDoc documentation for rack-test-0.5.4...
Installing RDoc documentation for rack-mount-0.6.13...
Installing RDoc documentation for tzinfo-0.3.23...
Installing RDoc documentation for abstract-1.0.0...
Installing RDoc documentation for erubis-2.6.6...
Installing RDoc documentation for actionpack-3.0.0...
Installing RDoc documentation for arel-1.0.1...
Installing RDoc documentation for activerecord-3.0.0...
Installing RDoc documentation for activeresource-3.0.0...
Installing RDoc documentation for mime-types-1.16...
Installing RDoc documentation for polyglot-0.3.1...
Installing RDoc documentation for treetop-1.4.8...
Installing RDoc documentation for mail-2.2.5...
Installing RDoc documentation for actionmailer-3.0.0...
Installing RDoc documentation for thor-0.14.0...
Installing RDoc documentation for railties-3.0.0...
Installing RDoc documentation for bundler-1.0.0...
Installing RDoc documentation for rails-3.0.0...

Let's see what's installed.

C:\>gem list --local

*** LOCAL GEMS ***

abstract (1.0.0)
actionmailer (3.0.0)
actionpack (3.0.0)
activemodel (3.0.0)
activerecord (3.0.0)
activeresource (3.0.0)
activesupport (3.0.0)
arel (1.0.1)
builder (2.1.2)
bundler (1.0.0)
erubis (2.6.6)
i18n (0.4.1)
mail (2.2.5)
mime-types (1.16)
minitest (1.6.0)
polyglot (0.3.1)
rack (1.2.1)
rack-mount (0.6.13)
rack-test (0.5.4)
rails (3.0.0)
railties (3.0.0)
rake (0.8.7)
rdoc (2.5.8)
rubygems-update (1.3.7)
thor (0.14.0)
treetop (1.4.8)
tzinfo (0.3.23)

Let's create a new app to see if it works.

C:\>rails new testapp
create
create README
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/views/layouts/application.html.erb
create app/mailers
create app/models
create config
create config/routes.rb
create config/application.rb
create config/environment.rb
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
create config/initializers
create config/initializers/backtrace_silencers.rb
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/initializers/secret_token.rb
create config/initializers/session_store.rb
create config/locales
create config/locales/en.yml
create config/boot.rb
create config/database.yml
create db
create db/seeds.rb
create doc
create doc/README_FOR_APP
create lib
create lib/tasks
create lib/tasks/.gitkeep
create log
create log/server.log
create log/production.log
create log/development.log
create log/test.log
create public
create public/404.html
create public/422.html
create public/500.html
create public/favicon.ico
create public/index.html
create public/robots.txt
create public/images
create public/images/rails.png
create public/stylesheets
create public/stylesheets/.gitkeep
create public/javascripts
create public/javascripts/application.js
create public/javascripts/controls.js
create public/javascripts/dragdrop.js
create public/javascripts/effects.js
create public/javascripts/prototype.js
create public/javascripts/rails.js
create script
create script/rails
create test
create test/performance/browsing_test.rb
create test/test_helper.rb
create test/fixtures
create test/functional
create test/integration
create test/unit
create tmp
create tmp/sessions
create tmp/sockets
create tmp/cache
create tmp/pids
create vendor/plugins
create vendor/plugins/.gitkeep

Smashing! Let's change directories and start the server.

C:\>cd testapp

C:\testapp>rails s
Could not find gem 'sqlite3-ruby (>= 0, runtime)' in any of the gem sources.
Try running `bundle install`.

Forgot to run the bundler.

C:\testapp>bundle install
Fetching source index for http://rubygems.org/
Using rake (0.8.7)
Using abstract (1.0.0)
Using activesupport (3.0.0)
Using builder (2.1.2)
Using i18n (0.4.1)
Using activemodel (3.0.0)
Using erubis (2.6.6)
Using rack (1.2.1)
Using rack-mount (0.6.13)
Using rack-test (0.5.4)
Using tzinfo (0.3.23)
Using actionpack (3.0.0)
Using mime-types (1.16)
Using polyglot (0.3.1)
Using treetop (1.4.8)
Using mail (2.2.5)
Using actionmailer (3.0.0)
Using arel (1.0.1)
Using activerecord (3.0.0)
Using activeresource (3.0.0)
Using bundler (1.0.0)
Using thor (0.14.0)
Using railties (3.0.0)
Using rails (3.0.0)
Installing sqlite3-ruby (1.3.1)
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.

Notice bundler installed sqlite3-ruby(1.3.1).

Let's look at the gems again.

C:\testapp>gem list --local

*** LOCAL GEMS ***

abstract (1.0.0)
actionmailer (3.0.0)
actionpack (3.0.0)
activemodel (3.0.0)
activerecord (3.0.0)
activeresource (3.0.0)
activesupport (3.0.0)
arel (1.0.1)
builder (2.1.2)
bundler (1.0.0)
erubis (2.6.6)
i18n (0.4.1)
mail (2.2.5)
mime-types (1.16)
minitest (1.6.0)
polyglot (0.3.1)
rack (1.2.1)
rack-mount (0.6.13)
rack-test (0.5.4)
rails (3.0.0)
railties (3.0.0)
rake (0.8.7)
rdoc (2.5.8)
rubygems-update (1.3.7)
sqlite3-ruby (1.3.1 x86-mingw32)
thor (0.14.0)
treetop (1.4.8)
tzinfo (0.3.23)

let's start the server!

If you get and error message about the SQLIte3 gem, here's how I solved it.

C:\testapp>rails s
=> Booting WEBrick
=> Rails 3.0.0 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-09-01 09:26:43] INFO WEBrick 1.3.1
[2010-09-01 09:26:43] INFO ruby 1.9.2 (2010-08-18) [i386-mingw32]
[2010-09-01 09:26:43] INFO WEBrick::HTTPServer#start: pid=4044 port=3000

Now go to http://127.0.0.1:3000/


What are we running?

Have fun.

Next we'll get it to hook up to MySQL

Monday, June 14, 2010

Create A Rails 3 beta With Authlogic, Declarative Authorization a

Create A Rails 3 beta With Authlogic, Declarative Authorization and Cucumber

I have updated my auth_with_roles app to use rails 3.0.7. You can find the code at https://github.com/johnivanoff/auth_with_roles/tree/rails_3_0_7

This was done on a windows wachine so forgive the C:\
And it's a crappy first draft.

My test aren't the best and need refactoring but this should get you started.
I plan to update this when rails 3 is released. I would also like to intergate Factory Girl.



This project uses:

Let's get going.
C:\web> rails auth_with_roles
C:\web> cd auth_with_roles
C:\web\auth_with_roles> git init
C:\web\auth_with_roles> git add .
C:\web\auth_with_roles> git commit -m "auth_with_roles Scaffold"

Let's add the gems for cucumber.
open /Gemfile add . . .
# Use Authlogic for security
gem "authlogic", :git => "git://github.com/odorcicd/authlogic.git", :branch => "rails3"
# using for role assignments
gem "declarative_authorization", :git => "git://github.com/stffn/declarative_authorization.git"

group :test do
gem 'capybara'
gem 'database_cleaner'
gem 'cucumber-rails'
gem 'cucumber', '0.7.2'
gem 'rspec-rails', '2.0.0.beta.8'
gem 'spork'
gem 'launchy' # So you can do Then show me the page
end


run
C:\web\auth_with_roles> bundle install

bootstrap your Rails app, for rspec:
C:\web\auth_with_roles> rails g rspec:install

Finally, bootstrap your Rails app, for cucumber:
C:\web\auth_with_roles> rails generate cucumber:skeleton --rspec --capybara

create the authlogic base.
C:\web\auth_with_roles> rails g cucumber:feature user username:string email:string password:string
C:\web\auth_with_roles> rails g scaffold user username:string email:string password:string

create_user migration
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :username
t.string :email
t.string :crypted_password
t.string :password_salt
t.string :persistence_token
t.timestamps
end
add_index :users, :username
add_index :users, :persistence_token
end
def self.down
drop_table :users
end
end

run
C:\web\auth_with_roles>rake db:migrate

Create a UserSessionsController
C:\web\auth_with_roles> rails g authlogic:session user_session
C:\web\auth_with_roles> rails g controller user_sessions new create destroy

fix up the sign up form /app/views/users/_form.html.erb
<%= form_for(@user) do |f| %>
<% if @user.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>


fix the user index fix /app/views/users/index.html.erb
<h1>Listing users</h1>
<table>
<tr>
<th>Username</th>
<th>Email</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New User', new_user_path %>


the user show /app/views/users/show.html.erb
<p class="notice"><%= notice %></p>
<p>
<b>Username:</b>
<%= @user.username %>
</p>
<p>
<b>Email:</b>
<%= @user.email %>
</p>
<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>



fix up the login form /app/views/user_sessions/new.html.erb
<%= form_for @user_session, :url => login_path do |f| %>
<% if @user_session.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@user_session.errors.count, "error") %> prohibited this asset_type from being saved:</h2>
<ul>
<% @user_session.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :username %><br />
<%= f.text_field :username %>
</p>
<p>
<%= f.label :password %><br />
<%= f.password_field :password %>
</p>
<p><%= f.submit "Log in" %></p>
<% end %>


add the routes /config/routes.rb
AuthWithRoles::Application.routes.draw do |map|
resources :users
controller :user_sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end

match 'register', :to => 'users#new', :as => "register"
end



Modify the application controller /apps/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
layout 'application'
helper :all
helper_method :current_user_session, :current_user
#filter_parameter_logging :password, :password_confirmation
before_filter :set_current_user
protected
def set_current_user
Authorization.current_user = current_user
end
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.record
end
def require_user
unless current_user
store_location
flash[:notice] = "You must be logged in to access this page"
redirect_to login_url
return false
end
end
def require_no_user
if current_user
store_location
flash[:notice] = "You must be logged out to access this page"
redirect_to account_url
return false
end
end
def store_location
session[:return_to] = request.fullpath
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
end



user_sessions_controller.rb /apps/controllers/user_sessions_controller.rb
class UserSessionsController < ApplicationController
def new
@user_session = UserSession.new
end
def create
@user_session = UserSession.new(params[:user_session])
if @user_session.save
flash[:notice] = "Successfully logged in."
redirect_to users_path
else
render :action => 'new'
end
end
def destroy
current_user_session.destroy
flash[:notice] = "Successfully logged out."
redirect_back_or_default login_url
end
end


Modify the user controller /apps/controllers/users_controller.rb
class UsersController < ApplicationController
#before_filter :require_no_user, :only => [:new, :create]
#before_filter :require_user, :only => [:show, :edit, :update]
# GET /users
# GET /users.xml
def index
@users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
end
end
# GET /users/1
# GET /users/1.xml
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
end
end
# GET /users/new
# GET /users/new.xml
def new
@user = User.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @user }
end
end
# GET /users/1/edit
def edit
@user = User.find(params[:id])
end
# POST /users
# POST /users.xml
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
format.html { redirect_to(@user, :notice => 'Registration successful.') }
format.xml { render :xml => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
# PUT /users/1
# PUT /users/1.xml
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
format.html { redirect_to(@user, :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.xml
def destroy
@user = User.find(params[:id])
@user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
end



modify the user model /app/model/user.rb
class User < ActiveRecord::Base
acts_as_authentic
end


we'll need to modify the cucumber test /features/manage_users.feature
Feature: Manage users
In order to [goal]
[stakeholder]
wants [behaviour]
Scenario: Register new user
Given the following roles:
|name|
|admin|
And I am on the new user page
When I fill in "Username" with "username 1"
And I fill in "Email" with "example@example.com"
And I fill in "Password" with "secret"
And I fill in "Password confirmation" with "secret"
And I check "admin"
And I press "Create"
Then I should see "username 1"
And I should see "example@example.com"
And I should see "admin"
Scenario: Delete user
Given the following users:
|username |email|password|password_confirmation|role_ids|
|username 1|email1@example.com|secret|secret|1|
|username 2|email2@example.com|secret|secret|2|
|username 3|email3@example.com|secret|secret|2|
|username 4|email4@example.com|secret|secret|2|
When I delete the 3rd user
Then I should see the following users:
|Username |Email|
|username 1|email1@example.com|
|username 2|email2@example.com|
|username 4|email4@example.com|



run
C:\web\auth_with_roles> rake cucumber
...........

2 scenarios (2 passed)
11 steps (11 passed)

run
C:\web\auth_with_roles> rake spec

Well we have some test to correct.

let modify the user session spec in /spec/controllers/user_sessions_controller_spec.rb
require 'spec_helper'
describe UserSessionsController do
def mock_usersession(stubs={})
@mock_usersession ||= mock_model(UserSession, stubs).as_null_object
end
describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
end
describe "GET 'create'" do
it "should be successful" do
get 'create'
response.should be_success
end
end
describe "DELETE destroy" do
it "destroys the current session" do
UserSession.should_receive(:find).with("37") { mock_usersession }
mock_usersession.should_receive(:destroy)
delete :destroy, :id => "37"
end
it "redirects to the login page" do
UserSession.stub(:find) { mock_usersession(:destroy => true) }
delete :destroy
response.should redirect_to(login_url)
end
end
end

Now modify the user's index spec /spec/views/users/index.html.erb_spec.rb
require 'spec_helper'
describe "users/index.html.erb" do
before(:each) do
assign(:users, [
stub_model(User,
:username => "MyUsername",
:email => "MyEmail",
:password => "MyPassword"
),
stub_model(User,
:username => "MyUsername",
:email => "MyEmail",
:password => "MyPassword"
)
])
end
it "renders a list of users" do
render
response.should have_selector("tr>td", :content => "MyUsername".to_s, :count => 2)
response.should have_selector("tr>td", :content => "MyEmail".to_s, :count => 2)
end
end


run
C:\web\auth_with_roles> rake spec

...................*.....*


Finished in 2.34 seconds
26 examples, 0 failures, 2 pending

Pending:
User add some examples to (or delete) ./spec/models/user_spec.rb (Not Yet Implemented)
# ./spec/models/user_spec.rb:4
user_sessions/create.html.erb add some examples to (or delete) ./spec/views/user_sessions/create.html.erb_spec.rb (Not Yet Implemented)
# ./spec/views/user_sessions/create.html.erb_spec.rb:4

All tests are passing, although they are not complete.

Let's get the login spec working /spec/views/new.html.erb_spec
require 'spec_helper'
describe "user_sessions/new.html.erb" do
before(:each) do
assign(:user_session, stub_model(User,
:new_record? => true,
:username => "MyString",
:password => "MyString"
))
end
it "renders login form" do
render
response.should have_selector("form", :action => login_path, :method => "post") do |form|
form.should have_selector("input#user_username", :name => "user[username]")
form.should have_selector("input#user_password", :name => "user[password]")
end
end
end

Let's get the User model working /spec/models/user_spec.rb
require 'spec_helper'
describe User do
before(:each) do
@user = User.new(:username => "Jimmy",
:email => "jimmy@example.com",
:password => "secret",
:password_confirmation => "secret")
end
it "is valid with valid attributes" do
@user.should be_valid
end
it "is not valid without a username" do
@user.username = nil
@user.should_not be_valid
end
it "is not valid without a unique username" do
@user2 = User.create( :username => "Jimmy",
:email => "johnny@example.com",
:password => "secret",
:password_confirmation => "secret")
@user.should_not be_valid
end
it "is not valid without an email" do
@user.email = nil
@user.should_not be_valid
end
it "is not valid without a unique email" do
@user2 = User.create( :username => "Johnny",
:email => "jimmy@example.com",
:password => "secret",
:password_confirmation => "secret")
@user.should_not be_valid
end
it "is not valid without a password"
it "is not valid without matching password and password confirmation" do
@user.password = "wrong"
@user.should_not be_valid
end
it "is not valid without a password confirmation" do
@user.password_confirmation = nil
@user.should_not be_valid
end
end



Now create the Roles scaffold

C:\web\auth_with_roles> rails g cucumber:feature role name:string
C:\web\auth_with_roles> rails g scaffold role name:string

create the join table
C:\web\auth_with_roles> rails g model assignment user_id:integer role_id:integer
C:\web\auth_with_roles> rake db:migrate

update the models to

in /app/models/assignment.rb
class Assignment < ActiveRecord::Base
belongs_to :user
belongs_to :role
end

in /app/models/role.rb
class Role < ActiveRecord::Base
has_many :assignments
has_many :users, :through => :assignments
end

in /app/models/user.rb
class User < ActiveRecord::Base
acts_as_authentic
has_many :assignments
has_many :roles, :through => :assignments
def role_symbols
roles.map do |role|
role.name.underscore.to_sym
end
end
end


run some tests
run
C:\web\auth_with_roles> rake cucumber
..................

4 scenarios (4 passed)
18 steps (18 passed)
0m6.688s

run
C:\web\auth_with_roles> rake spec
..................................**.....*.............


Finished in 6.66 seconds
55 examples, 0 failures, 3 pending

Pending:
Assignment add some examples to (or delete) ./spec/models/assignment_spec.rb (Not Yet Implemented)
# ./spec/models/assignment_spec.rb:4
Role add some examples to (or delete) ./spec/models/role_spec.rb (Not Yet Implemented)
# ./spec/models/role_spec.rb:4
User is not valid without a password (Not Yet Implemented)
# ./spec/models/user_spec.rb:37

Let's add some tests for the Role model. /spec/models/role_spec.rb
require 'spec_helper'
describe User do
before(:each) do
@role = Role.new(:name => "Jimmy")
end
it "is valid with valid attributes" do
@role.should be_valid
end
it "is not valid without a name" do
@role.name = nil
@role.should_not be_valid
end
it "is not valid without a unique name"
end

run
C:\web\auth_with_roles> rake spec
..................................*.F*.....*.............

1) Role is not valid without a name
Failure/Error: @role.should_not be_valid
expected valid? to return false, got true
# ./spec/models/role_spec.rb:14
# ./spec/controllers/roles_controller_spec.rb:3


Finished in 4.59 seconds
57 examples, 1 failures, 3 pending

Pending:
Assignment add some examples to (or delete) ./spec/models/assignment_spec.rb (Not Yet Implemented)
# ./spec/models/assignment_spec.rb:4
Role is not valid without a unique name (Not Yet Implemented)
# ./spec/models/role_spec.rb:17
User is not valid without a password (Not Yet Implemented)
# ./spec/models/user_spec.rb:37


We need to add vilidation to the Role model /app/models/role.rb
class Role < ActiveRecord::Base
has_many :assignments
has_many :users, :through => :assignments
validates :name, :presence => true
end


run
C:\web\auth_with_roles> rake spec
..................................*..*.....*.............


Finished in 4.75 seconds
57 examples, 0 failures, 3 pending

Pending:
Assignment add some examples to (or delete) ./spec/models/assignment_spec.rb (Not Yet Implemented)
# ./spec/models/assignment_spec.rb:4
Role is not valid without a unique name (Not Yet Implemented)
# ./spec/models/role_spec.rb:17
User is not valid without a password (Not Yet Implemented)
# ./spec/models/user_spec.rb:37

Passed.
Let's add finish the tests for the Role model. /spec/models/role_spec.rb
require 'spec_helper'
describe User do
before(:each) do
@role = Role.new(:name => "Jimmy")
end
it "is valid with valid attributes" do
@role.should be_valid
end
it "is not valid without a name" do
@role.name = nil
@role.should_not be_valid
end
it "is not valid without a unique name" do
@role2 = ROle.create( :username => "Jimmy") @role.should_not be_valid
end
end

run
C:\web\auth_with_roles> rake spec
..................................*..F.....*.............

1) Role is not valid without a unique name
Failure/Error: @role.should_not be_valid
expected valid? to return false, got true
# ./spec/models/role_spec.rb:19
# ./spec/controllers/roles_controller_spec.rb:3


Finished in 4.63 seconds
57 examples, 1 failures, 2 pending

Pending:
Assignment add some examples to (or delete) ./spec/models/assignment_spec.rb (Not Yet Implemented)
# ./spec/models/assignment_spec.rb:4
User is not valid without a password (Not Yet Implemented)
# ./spec/models/user_spec.rb:37


We need to add vilidation to the Role model /app/models/role.rb
class Role < ActiveRecord::Base
has_many :assignments
has_many :users, :through => :assignments
validates :name, :presence => true
validates :name, :uniqueness => true
end


run
C:\web\auth_with_roles> rake spec
..................................*........*.............


Finished in 6.27 seconds
57 examples, 0 failures, 2 pending

Pending:
Assignment add some examples to (or delete) ./spec/models/assignment_spec.rb (Not Yet Implemented)
# ./spec/models/assignment_spec.rb:4
User is not valid without a password (Not Yet Implemented)
# ./spec/models/user_spec.rb:37

We need to lock down the roles controller to admin only

In the application controller /app/controllers/application_controller.rb add
class ApplicationController < ActionController::Base
protect_from_forgery
layout 'application'
helper :all
helper_method :current_user_session, :current_user
#filter_parameter_logging :password, :password_confirmation
before_filter :set_current_user
protected
def set_current_user
Authorization.current_user = current_user
end
def permission_denied
flash[:error] = "Sorry, you are not allowed to access that page."
redirect_to '/'
end
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.record
end
def require_user
unless current_user
store_location
flash[:notice] = "You must be logged in to access this page"
redirect_to login_url
return false
end
end
def require_no_user
if current_user
store_location
flash[:notice] = "You must be logged out to access this page"
redirect_to account_url
return false
end
end
def store_location
session[:return_to] = request.fullpath
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
end

In the role controller /app/controllers/roles_controller.rb add
class RolesController < ApplicationController
filter_resource_access
.....................................
end

In the user controller /app/controllers/users_controller.rb add
class RolesController < ApplicationController
filter_resource_access
.....................................
end


run
C:\web\auth_with_roles> rake cucumber
.F--.F-...........

(::) failed steps (::)

cannot fill in, no text field, text area or password field with id, name, or label 'Name' found (Capybara::ElementNotFound)
./features/step_definitions/web_steps.rb:41
./features/step_definitions/web_steps.rb:14:in `with_scope'
./features/step_definitions/web_steps.rb:40:in `/^(?:|I )fill in "([^\"]*)" with "([^\"]*)"(?: within "([^\"]*)")?$/'
features\manage_roles.feature:8:in `When I fill in "Name" with "name 1"'

scope '//table//*[position() = 4 and self::tr]' not found on page (Capybara::ElementNotFound)
./features/step_definitions/role_steps.rb:7:in `/^I delete the (\d+)(?:st|nd|rd|th) role$/'
features\manage_roles.feature:42:in `When I delete the 3rd role'

Failing Scenarios:
cucumber features\manage_roles.feature:6 # Scenario: Register new role
cucumber features\manage_roles.feature:35 # Scenario: Delete role

4 scenarios (2 failed, 2 passed)
18 steps (2 failed, 3 skipped, 13 passed)
0m7.813s
rake aborted!
Command failed with status (1): [C:/Ruby/bin/ruby.exe -I "C:/Documents and ...]

Well we got redirected to the home page. We'll have to log in.
in /featues/manage_roles.feature add
Feature: Manage roles
In order to manage roles
as an Admin
I want to create and edit roles.
Scenario: Register new role
Given the following roles:
|name|
|admin|
And the following users:
|username |email|password|password_confirmation|role_ids|
|don |email1@example.com|secret|secret|1|
And I am logged in as "don" with password "secret"
Given I am on the new role page
When I fill in "Name" with "name 1"
And I press "Create"
Then I should see "name 1"
Scenario: Delete role
Given the following roles:
|name |
|admin |
|name 2|
|name 3|
|name 4|
And the following users:
|username |email |password|password_confirmation|role_ids|
|don |email1@example.com|secret |secret |1 |
And I am logged in as "don" with password "secret"
When I delete the 3rd role
Then I should see the following roles:
|Name |
|admin |
|name 2|
|name 4|

run
C:\web\auth_with_roles> rake cucumber
..U----..U--...........

4 scenarios (2 undefined, 2 passed)
23 steps (6 skipped, 2 undefined, 15 passed)
0m5.781s

You can implement step definitions for undefined steps with these snippets:

Given /^I am logged in as "([^\"]*)" with password "([^\"]*)"$/ do |arg1, arg2|
pending # express the regexp above with the code you wish you had
end

in /featues/step_definitions/user_steps.rb add
Given /^I am logged in as "([^\"]*)" with password "([^\"]*)"$/ do |username, password|
unless username.blank?
visit login_url
fill_in "Username", :with => username
fill_in "Password", :with => password
click_button "Log in"
end
end
run
C:\web\auth_with_roles> rake cucumber
.......................

4 scenarios (4 passed)
23 steps (23 passed)
0m10.063s

Let's update the users feature so we can select a role for a new users and admin can show edit or destroy. everyone can see a list of the users
In /features/manage_users.feature
Feature: Manage users
In order to manage Users
As an Admin
I want to manage users
@focus
Scenario: Register new user
Given the following roles:
|name|
|admin|
And I am on the new user page
When I fill in "Username" with "username 1"
And I fill in "Email" with "example@example.com"
And I fill in "Password" with "secret"
And I fill in "Password confirmation" with "secret"
And I check "admin"
And I press "Create"
Then I should see "username 1"
And I should see "example@example.com"
And I should see "admin"
Scenario: Delete user
Given the following users:
|username |email|password|password_confirmation|
|username 1|email1@example.com|secret|secret|
|username 2|email2@example.com|secret|secret|
|username 3|email3@example.com|secret|secret|
|username 4|email4@example.com|secret|secret|
When I delete the 3rd user
Then I should see the following users:
|Username |Email|
|username 1|email1@example.com|
|username 2|email2@example.com|
|username 4|email4@example.com|
Scenario: Admin sees all user's edit links
Given the following roles:
|name|
|admin|
|guest|
And the following users:
|username |email|password|password_confirmation|role_ids|
|don |email1@example.com|secret|secret|1|
|username 2|email2@example.com|secret|secret|2|
|username 3|email3@example.com|secret|secret|2|
|username 4|email4@example.com|secret|secret|2|
And I am logged in as "don" with password "secret"
Then I should see the following users:
|Username |Email|Show|Edit|Destroy|
|don |email1@example.com|Show|Edit|Destroy|
|username 2|email2@example.com|Show|Edit|Destroy|
|username 3|email3@example.com|Show|Edit|Destroy|
|username 4|email4@example.com|Show|Edit|Destroy|

you might have noticed I added an @focus tag. We'll be running one scenario at a time now. we'll be able to focus on it.
run
C:\web\auth_with_roles> cucumber --tags @focus
......F----

(::) failed steps (::)

cannot check field, no checkbox with id, name, or label 'admin' found (Capybara::ElementNotFound)
./features/step_definitions/web_steps.rb:78
./features/step_definitions/web_steps.rb:14:in `with_scope'
./features/step_definitions/web_steps.rb:77:in `/^(?:|I )check "([^\"]*)"(?: within "([^\"]*)")?$/'
features\manage_users.feature:16:in `And I check "admin"'

Failing Scenarios:
cucumber features\manage_users.feature:6 # Scenario: Register new user

1 scenario (1 failed)
11 steps (1 failed, 4 skipped, 6 passed)
0m7.453s


We Update the _form view so we can add roles to users /app/views/users/_form.html.erb
<%= form_for(@user) do |f| %>
<% if @user.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<p>
<%= f.label :roles %><br />
<% for role in Role.all %>
<%= check_box_tag "user[role_ids][]", role.id, @user.roles.include?(role) %>
<label for="user_role_ids_"><%= role.name %></label>
<% end %>
</p>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
run
C:\web\auth_with_roles> cucumber --tags @focus
..........F

(::) failed steps (::)

<false> is not true. (Test::Unit::AssertionFailedError)
C:/Ruby/lib/ruby/1.8/test/unit/assertions.rb:48:in `assert_block'
C:/Ruby/lib/ruby/1.8/test/unit/assertions.rb:500:in `_wrap_assertion'
C:/Ruby/lib/ruby/1.8/test/unit/assertions.rb:46:in `assert_block'
C:/Ruby/lib/ruby/1.8/test/unit/assertions.rb:63:in `assert'
C:/Ruby/lib/ruby/1.8/test/unit/assertions.rb:495:in `_wrap_assertion'
C:/Ruby/lib/ruby/1.8/test/unit/assertions.rb:61:in `assert'
./features/step_definitions/web_steps.rb:112
./features/step_definitions/web_steps.rb:14:in `with_scope'
./features/step_definitions/web_steps.rb:108:in `/^(?:|I )should see "([^\"]*)"(?: within "([^\"]*)")?$/'
features\manage_users.feature:20:in `And I should see "admin"'

Failing Scenarios:
cucumber features\manage_users.feature:6 # Scenario: Register new user

1 scenario (1 failed)
11 steps (1 failed, 10 passed)
0m7.531s


We'll also update the show page so we can see the user's roles /app/views/users/show.html.erb
<p class="notice"><%= notice %></p>
<p>
<b>Username:</b>
<%= @user.username %>
</p>
<p>
<b>Email:</b>
<%= @user.email %>
</p>
<p><%= pluralize(@user.roles.size, 'Role') %></p>
<ul>
<% @user.roles.each do |role| %>
<li><%= role.name %></li>
<% end %>
</ul>
<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

run
C:\web\auth_with_roles> cucumber --tags @focus
...........

1 scenario (1 passed)
11 steps (11 passed)
0m7.828s

It passes.
Now we want only the admin to 'Show", "Edit', and 'Destroy' users.
in /features/manage_users.feature add
@focus
Scenario: Admin sees all user's edit links
Given the following roles:
|name|
|admin|
|guest|
And the following users:
|username |email|password|password_confirmation|role_ids|
|don |email1@example.com|secret|secret|1|
|username 2|email2@example.com|secret|secret|2|
|username 3|email3@example.com|secret|secret|2|
|username 4|email4@example.com|secret|secret|2|
And I am logged in as "don" with password "secret"
Then I should see the following users:
|Username |Email|Show|Edit|Destroy|
|don |email1@example.com|Show|Edit|Destroy|
|username 2|email2@example.com|Show|Edit|Destroy|
|username 3|email3@example.com|Show|Edit|Destroy|
|username 4|email4@example.com|Show|Edit|Destroy|
And I should see "New user"

Remove the previous @focus from feature
run
C:\web\auth_with_roles> cucumber --tags @focus
......F

(::) failed steps (::)

Tables were not identical (Cucumber::Ast::Table::Different)
./features/step_definitions/user_steps.rb:13:in `/^I should see the following users:$/'
features\manage_users.feature:73:in `Then I should see the following users:'

Failing Scenarios:
cucumber features\manage_users.feature:61 # Scenario: Admin sees all user's edit links

2 scenarios (1 failed, 1 passed)
7 steps (1 failed, 6 passed)

we need to modify the index view /app/views/users/index.html.erb
<h1>Listing users</h1>
<table>
<tr>
<th>Username</th>
<th>Email</th>
<th>Show</th>
<th>Edit</th>
<th>Destroy</th>
</tr>
<% @users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />

<%= link_to 'New User', new_user_path %>

run
C:\web\auth_with_roles> cucumber --tags @focus
.....

1 scenario (1 passed)
5 steps (5 passed)
0m7.828s

We will need to fix the delete user scenario. remember to move the @focus tag to it.
Scenario: Delete user
Given the following roles:
|name|
|admin|
|guest|
And the following users:
|username |email|password|password_confirmation|role_ids|
|don |email1@example.com|secret|secret|1|
|username 2|email2@example.com|secret|secret|2|
|username 3|email3@example.com|secret|secret|2|
|username 4|email4@example.com|secret|secret|2|
And I am logged in as "don" with password "secret"
When I delete the 3rd user
Then I should see the following users:
|Username |Email|
|don |email1@example.com|
|username 2|email2@example.com|
|username 4|email4@example.com|


run
C:\web\auth_with_roles> cucumber --tags @focus
.....

1 scenario (1 passed)
5 steps (5 passed)
0m7.828s

Let's add a scenario so that users can see everyone but do not see the show edit or destroy and the New user link.
@focus
Scenario: guest sees all user's and Show links, but no edit or destroy links
Given the following roles:
|name|
|admin|
|guest|
And the following users:
|username |email|password|password_confirmation|role_ids|
|don |email1@example.com|secret|secret|1|
|jimmy |email2@example.com|secret|secret|2|
|username 3|email3@example.com|secret|secret|2|
|username 4|email4@example.com|secret|secret|2|
And I am logged in as "jimmy" with password "secret"
Then I should see the following users:
|Username |Email |Show|Edit|Destroy|
|don |email1@example.com|Show| | |
|jimmy |email2@example.com|Show| | |
|username 3|email3@example.com|Show| | |
|username 4|email4@example.com|Show| | |
And I should not see "New User"



run
C:\web\auth_with_roles> cucumber --tags @focus
...F-

(::) failed steps (::)

Tables were not identical (Cucumber::Ast::Table::Different)
./features/step_definitions/user_steps.rb:13:in `/^I should see the following users:$/'
features\manage_users.feature:97:in `Then I should see the following users:'

Failing Scenarios:
cucumber features\manage_users.feature:85 # Scenario: guest sees all user's and Show links, but no edit or destroy links

1 scenario (1 failed)
5 steps (1 failed, 1 skipped, 3 passed)
0m14.359s

Let's updae the index page /app/views/users/index.html.erb
<h1>Listing users</h1>
<table>
<tr>
<th>Username</th>
<th>Email</th>
<th>Show</th>
<th>Edit</th>
<th>Destroy</th>
</tr>
<% @users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= user.email %></td>
<td>
<% if permitted_to? :show, @user %>
<%= link_to 'Show', user %>
<% end %>
</td>
<td>
<% if permitted_to? :edit, @user %>
<%= link_to 'Edit', edit_user_path(user) %>
<% end %>
</td>
<td>
<% if permitted_to? :destroy, @user %>
<%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %>
<% end %>
</td>
</tr>
<% end %>
</table>
<br />
<% if permitted_to? :create, @user %>
<%= link_to 'New User', new_user_path %>
<% end %>

run
C:\web\auth_with_roles> cucumber --tags @focus
.....

1 scenario (1 passed)
5 steps (5 passed)
0m7.828s

Let's test all the cucumber tests
C:\web\auth_with_roles> rake cucumber
......................................

6 scenarios (6 passed)
38 steps (38 passed)
0m18.016s

Now only an admin can create, edit or delete roles.
You'll need to lock down the Users so only an admin can create, edit or destroy users, or what ever you decide.

Cheers,
John

Source code on git hub.

Thanks to
railscasts Authlogic
and the documentation for the gems I used.