RailsConf wrap-up

Posted by Brian Eng Wed, 28 Jun 2006 02:06:56 GMT

We've posted a wrap-up of RailsConf as a whole over on our regular blog, Softies On Rails.



Posted by Brian Eng Sun, 25 Jun 2006 17:28:14 GMT

Stuart Halloway and Justin Gehtland talk about programming deep into Rails.


  • Hacking the type system
    • Add/remove/alias methods
    • Dynamically load/unload/mixin code
  • Hijacking the syntax
    • DSLs
    • Combining casts, blocks, etc.

Three easy pieces

to_proc Trick


Indifferent Access

h = { "hello" => "world" } h[:hello] => nil h = h.withindifferentaccess h[:hello] => "world"

  • Not the default
  • How do I know hash got patched? puts Hash.ancestors.join("\n")

Whiny Nil

x = nil x.id => Error x[0] => Error - wanted Array x.save => Error - you wanted ActiveRecord

  • Method missing
  • Reverse lookup

In Java, everything has got be exactly right, or you get nothing.

  • Verb-oriented programming - interpret symbols as procs
  • Nothing to remember - indifferent hash
  • Discoverable mods - indifferent access namespace
  • Learn from mistakes, then automate - whiny nil
  • Guesses may be better than certainty - whiny nil

How's they do that?

Where do ActiveRecord accessors come from?

  • Method generation
  • method_missing
  • Dynamic finders
  • Declaring an association - creates runtime reflection model
  • Borrowing other object models - accessors inferred from schema
  • Object model on demand - method_missing
  • Roll your own object model - ActiveRecord::Reflections
  • Object models exist to serve programmers

How do variables get from controllers to views?

  • Traditional OO way
    • Controllers stick values into context
    • View pull from context
  • Rails
    • Variables are magically available to views
    • Loop through assigns and give it to the views
  • Dynamic typing - controller->@assigns->view
  • Domain-specific encapsulation - protectedvariablecache
  • CoC loC - controller->@assigns->view

How do classes get reloaded during development?

  • Removing classes - Class.remove_class
  • Marking reloadable - Reloadable module
  • Make your own classes reloadable - requiredependencies / dependon
  • Finding all includers of a module - examine ObjectSpace
  • Load once with require
  • It's all about dynamic typing vs. static typing
  • Conditional inheritance - reloadable?
  • Looking down the object model - included_in_classes
  • Object model callbacks - included
  • App specific object model - removeclasses, Reloadable, requireor_load

How do transactions work?

  • ActiveRecord can use database transactions
  • Objects can themselves be transactional
  • Transaction support == Around Advice
  • Hopefully it will go away
  • Object transactions == fun
  • Start a transaction
    • Increment transaction level
    • Push transaction name
    • Marshal transaction checkpoint
  • Commit
    • Decrement transaction level
    • Pop name
    • Unmarshal transaction checkpoint
    • Set transaction checkpoint to previous value
  • Abort
    • Decrement
    • Pop
    • Unmarshal
    • Set all ivars to previous value

Following Rails' example

  • Generating tests
  • Creating an internal DSL

(sweet demos... this was an awesome presentation, was really hard to transcribe it all)


Using Rails to Sell Music in the 21st Century

Posted by Jeff Cohen Sun, 25 Jun 2006 17:25:19 GMT

Benjamin Curtis


(talking about his online music store)

Why build a store? Because you'd be out of a job if yuo told your client to

just use Shopify :-)

Do not build a store just to sell one product. Do something simpler.

There are a couple of open source solutions, boxcart and substruct.

But you probably have very specific requirements that would indicate that it

will be easier for you to develop your own.

Setting up a store can be more difficult than you might think. Downloads,

payments, gift certificates, affiliate programs, shipping and taxes... soon

the app on the back end can get really big really quickly.

Code stats: 4500 lines of code, and 5800 lines of tests.

Getting Started

  • Product info and product shots
  • Merchant acct and gateway
  • Shipping vendors
  • SSL certificates
  • Site design

Products and Variants

Product has many ProductVariants (cd, tape, vinyl, mp3) Variant has many ProductVariants ProductVariant has many LineItems Sale has many LineItems

Payment Processing

Credit Cards, Bank Accounts, and PayPal

PayPal is difficult if you need to use their SOAP API (certain functions are

only available in the API).

TrustCommerce has a Ruby API.

(slides on how to be decoupled from actual payment gateway)

Sensitive Data

Objective: Speey checkout for customers Problem: credit card data == liability Solution: pass the buck, try not to store credit card numbers Alternate solution: encryption

Gift certificates

They just suck. Seems easy at first, but it has to be treated differently. It is not just a shipped good, it has to be treated like money. There are a lot of state laws regarding gift certificates. They can be long-term liabilities.

Working with Sales

Carts, sales, and shipments.

They all seem similar (they all have many line items, etc.) and you could use STI, but usually separate tables are a better idea.



Returns and Refunds: need to credit the credit card, or issue some kind of store credit, etc. A big hassle.


ShipZone has many ShipMethod ShipZone has many PostalCode PostalCode has many ShipZone ShipZone has many ShipRate ShipZone has many Country Country has many ShipZone



OpenID, Rails, and Identity 2.0

Posted by Brian Eng Sun, 25 Jun 2006 15:45:09 GMT

Matt Pelletier talks about cultivating the identity ecosystem.

What is digital identity?

  • Who you say you are
  • What people know about you
  • What you represent

How it works

  • You create account
  • You login

Digital identity sucks!

  • Repetitive
  • Complex and inconsistent
  • Poor UI
  • Lack of control
  • Unnecessary

What can we do?

What people want - not Passport

  • Unique global identifier
  • Decentralized
  • Lightweight
  • Open standards
  • Community driven
  • Diffusion of risk
  • Features
    • Single sign-on
    • Secure
    • I control the flow of information

Yadis + OpenID

  • Yadis
    • Service Discovery Layer for Web 2.0
  • OpenID
    • URL-based
    • Authentication and Authorization
    • LiveJournal

Project Bantay

  • Blend Yadis + OpenID and offer them as a service
  • Building an identity 2.0 stack
    • Protocol support
    • Yadis
    • OpenID 1.1
    • http://openidenabled.com
    • Mongrel
    • A natural fit for HTTP-heavy protocols
    • Tight, fast, secure
    • Support for Handlers, Filters
    • Zed Shaw is the man
    • Identity server
    • Single sign on
    • Profile management
    • Trust requests
    • Consumer plugin
    • Rails plugin
    • Push-button simplicity
    • Leverage Rails conventions
    • Play nice with "old" idiom of user silo
    • Bookmarks demo application
    • Testing
    • Interesting test environment
    • Test libraries
    • Test handlers
    • Test Rails app
    • Test cross-site functionality (Selenium)
    • Mongrel Rules!

An identity ecosystem

  • Cultivating Services
    • Claims verification
    • Dating sites: verify your gender
    • pr0n: verfiy your age
    • Job application: verify your green card
    • No posting to kids' blogs unless you're <= 14
    • Reputation
    • Seller reputation
    • Weenie reputation
    • You can't post blog comments
    • No committing to Rails trunk unless you're a verified pouty artsy wanker
    • Trusting identity providers
      • Needs to be discussed
      • Trust chain
    • Wide open marketplace
    • Develop creative new services

Next steps

  • Download the plugin - identity.eastmedia.com
  • Download the bookmarks demo app
  • Identity Server to be released this summer
  • Play around. Use your noodle.


Agile Databases with Migrations

Posted by Jeff Cohen Sun, 25 Jun 2006 15:01:37 GMT

Damon Clinkscales

Why Should You Care?

Migrations are cool.

We're going to cover a lot of ground: Schema, chimps, agile, failures, transactions, foreign keys, data, sql.

Being Agile

By agile do we mean yoga? No. We mean keeping our software flexible and willing to change. "Agile development uses feedback

to make constant adjustments in a highly collaborative environment." - Pragmatic Programmers

Migrations are agile.

Migrations support lots of databases: MySQL, PostgreSQL, SQLite, MS SQL Server, Oracle, Sybase. Not OpenBase, FireBird, or


Migrations are a database agnostic (mostly!) way to create and alter database schemas and manipulate data with Ruby code; and

also a way to execute that code.

Every migration gets a unique number, stored in the schema_info table. The number is called the version number. You can go

forward or back by specifying the version number.

Cheat Sheet for using Rake

rake migrate [VERSION=xx] - migrate your db rake db:schema:dump - dump to schema.rb rake db:schema:load - load from schema.b rake db:structure:dump rake db:sessions:create - create session migration rake -T - show available tasks

Development environment is assumed, or you can add RAILSENV=production or RAILSNV=test.

i.e. rake RAILS_ENV=production migrate

With Capistrano: rake remote:deploywithmigrations

Schema Statements

Remember, table names in Rails are plural.

Tables: addtable, droptable, rename_table Options are:

  • :id (true or false for primary key)
  • :primary_key (name of primary key)
  • :temporary (make it a temp table)
  • :force (true to drop table, default false)
  • :options (i.e. "DEFAULT CHARSET", "ENGINE" in MySQL)

Columns: addcolumn, removecolumn, rename_column, etc.

Indexes: addindex, removeindex. Options are :name (specify a custom index name), :index_type (i.e. UNIQUE), :column (perfect

for default names)

Getting Started

To create a new migration, use the generator:

script/generate migration MyFirstMigration

which produces a class derived from ActiveRecord::Migration

Or, creating a model creates a migration:

script/generate model MyModel

Adding A Join Table

Join tables might not need an ID column, so you can turn it off:

createtable :myjoin_table, :id => false do |t| ....

You can also execute any SQL you want:

def self.up begin execute "ALTER TABLE 'companies' ENGINE=MyISAM" rescue end end

Note that this example only works on MySQL, hence the rescue.

Existing Schemas

Stuff your schema into an initial migration:

  • backup the database
  • create an empty migration
  • Dump the schema and paste it into your migration (the create_table statements in schema.rb)
  • Dump the structure, i.e. rake db:structure:dump. Paste the SQL into your migration.
  • Save off your data with mysqldump, for example

To test, drop all your tables, rake migrate, then load your data back in with mysql script.

Then rake to run your full test suite.

Manipulating Data

You can include Ruby code inside your migrations. i.e.

def self.up products = Product.findallby_processed(0) products.each do |p| say p.name ... end end

def self.down execute "DELETE * FROM PRODUCTS" end

Check out the AR Fixtures Plugin from Geoffrey Grosenbach to make it easier to dump/load ActiveRecord objects to yml.

For more info, look at Recipe #42 in Rails Recipes by Chad Fowler.

Migration Messes

You might get an error while you're running a migration. Usually an error in your logic.

There are three ways to fix:

  • User yuor database tool
  • Define a schema on the fly in script\console. Just use ActiveRecord::Schema.

ActiveRecord::Schema.define do drop_table :follies end

Best way is with a migration console. Start script/console and then run irb:

irb ActiveRecord::Base.connection tables drop_table :follies


Whenever possible, make your migrations reversible.

When a migration can't be reversed, raise an IrreversibleMigration exception. This is typically associated with a loss of



You can use transactions to wrap data changes as well as schema changes.

But some databases like MySQL internally commit after some statements outside of Rails transactions.

Foreign Keys

There is no native support for foreign keys in migrations. You can run raw SQL inside your migration to support them or look

for plugins from Red Hill and Bubbleshare.


  • Make sure you use self.up and not just up
  • Don't write independent migrations in an SVN branch. Make sure the code and database stay the same.
  • Numbering conflicts in version control.
  • If you do use foreign keys, make sure you drop them in the right order.
  • Make sure your migration names don't conflict with other class names.
  • Schema dumper may not dump to your liking because of least-common-denominator across databases.
  • See Rails Recipes #30.

Best Practices

  • Keep each migration simple and small
  • Make them reversible
  • Use Ruby schema when possible, otherwise standard SQL
  • Be careful when relying on models

Other Tips

  • Purge db: rake migration VERSION=0
  • Don't modify schema.rb
  • Use saywthtime blocks for benchmarking
  • TextMate migration shortcuts
  • script/about for schema version check

Changes with Rails 1.1+

  • Ruby schema format is enabled by default
  • Verbose migrations are on by default
  • MySQL's InnoDB is now the default table type
  • A migration fr every generated model (use --skip-migration)
  • rails myapp --database=postgreSQL


Beyond DHTML - Laszlo on Rails

Posted by Brian Eng Sun, 25 Jun 2006 14:43:36 GMT

Mike Pence talks about sex, drugs, and rock-and-roll. (Er, Laszlo on Rails.)

A professional web surfer, Mike thinks that Google has really pioneered the idea of blurring the lines of web and desktop apps. Google Maps, Spreadsheets. Yahoo! Mail.

Web 2.0 movement - a design movement.

  • Minimalist
  • Attractive
  • User customization - pimp my site (MySpace, blogs)
  • Audio/video

The Holy Grail!

  • Rich apps that is self-updating and doesn't require downloading
  • Desktop apps need to be downloaded, installed, updated
  • Pandora/Music Genome Project
    • Written in Laszlo


  • Outstanding documentation
  • LZX language - XML-based
  • Form widgets
  • XML Datasets - Communications with databases
  • XPath empowers views
  • Visuals - animations
  • Powerful language
    • Declarative syntax
    • Object-oriented
    • Prototype-based - mixins
    • Delegates
    • States
  • Components - skinnable
  • Components - write your own

(group hug for those of us who hate flash)

Don't hate the player; hate the game.

False dichotomies:

  • Flash vs. DHTML
  • Ajax vs. Laszlo
  • fullscreen vs. nothing
  • bald vs. sexy

The DHTML runtime is part of "Project Legals" - target September for developers, December for general use. Goal: support OpenLaszlo for multiple clients/platforms.

(screenshot of Gliffy - sp? - Laszlo-based "Visio")

Laszlo on Rails

  • Installation
    • gem install ropenlaszlo
    • rails app
    • cd app
    • ruby script/plugin install svn://rubyforge.org/var/svn/laszlo-plugin/tags/
  • Full REST API
  • Possibilities
    • Rich web "widgets"
    • Pass data back and forth between clients - (e.g. chat)
    • In-browser development suite
  • But...
    • Cost to consuming resources
    • Accessibility, searching, printing - all advantages of HTML
    • Performance is not stellar
    • The best solution is a combination of HTML and Laszlo
  • Still...
    • A very powerful environment with many possibilities
    • Web development/HTML a step backwards for UI
    • Laszlo opens options for UI up again



David Heinemeier Hansson Keynote

Posted by Brian Eng Sun, 25 Jun 2006 02:20:00 GMT

Update: slides available.

David talks about discovering a world of resources on Rails.

But before we get started, David is going to be a just little bit... arrogant. Time to gloat.

(Cover of Linux Journal)

Time to think about why we have gotten so much attention. Rails is what it is because we said "no", and turning people away. I don't think it's time to turn that around. Let's not live in the "real world". It's a miserable place to be. You're weighed down by decades of old practices. But that's not what Rails is all about.

There is a lot more going on than us in this little room.

  • Book sales
  • 7000 copies in Japanese
  • Individual team growth
    • 43 Things

But anyway, this talk is not about that. It's about CRUD. The fundamental thing that Rails is all about.

What they told you about CRUD...

  • It's simplistic
  • It's unfulfilling
  • It's unworthy
  • It's shameful

They were wrong. How I learned to stop worrying and love the CRUD.

find, create, update, destroy = SELECT, INSERT, UPDATE, DELETE

Recently, we've had a renaissance. A renaissance for HTTP. So now we add GET, POST, PUT, DELETE.

POST /people/create GET /people/show/1 POST /people/update/1 POST /people/destroy/1

That makes me queazy. Not DRY. Because we're not using the CRUD features of HTTP. So instead>

POST /people GET /people/1 PUT /people/1 DELETE /people/1

Why can't we tackle this problem too?

In our routes file, we can start talking about these resources. We can create our own world where these rules magically apply.


form_for :person, david, :method => :put do |f| f.text_field :name end


link_to "Destroy", person_url(/david.html), :method => :delete

Why bother?

  • Consistency
  • Simplicity
  • Discoverability

The grand prize... constraints are liberating (a straightjacket for your mind)

Your controllers should always contain:

  • index (GET /people)
  • new (GET /people;new)
  • create (POST /people)
  • show (GET /people/1)
  • edit (GET /people/1;edit)
  • update (PUT /people/1)
  • destroy (DELETE /people/1)

And that's it.

How about a many-to-many?

For a many-to-many add user for a group: POST /groups/1;adduser?userid=2

Nah. Think about the domain. Instead:

POST /memberships?groupid=1&userid=2

Model beyond "things"

  • Relations (membership, subscription)
  • Events (closure, change)
  • States (reviewed, accepted)

Frameworks are either the devil or the angel. Resist the temptation. Being insane should hurt! Doing the right thing should be easy. Because we want to elevate the practices that developers follow.


CRUD is not a goal; it's an aspiration, a design technique. You can invent the "closed pressure cooker", but you must be willing to understand and weigh the trade-offs.


And there is more!

Answering to mime types

  • One controller for many clients
  • One action returning different results
  • Flexible input model

GET /people => returns HTML

Accept: text/javascript GET /people => returns RJS

Accept: text/html GET /people.xml => returns XML

Use extensions as they were meant to be! For getting data back in different formats.

Not just for getting data. But also for creating/update data. And mobile.


That is why this is better than SOAP and WS-*, etc. Doing things by hand is good!

One more thing

If exposing APIs are so easy, then let's encapsulate it!

Active Resource

Person = ActiveResource::Struct.new do |p| p.uri "http://www.example.com/people" p.credentials :name => "dhh", :password => "secret" end

GET http://www.example.com/people/1

=> Matz

matz = Person.find(1)

=> matz


(more examples)

Have the exact same benefits of ActiveRecord across resources.

And life will be happier!


Homesteading: A Thriver's Guide

Posted by Jeff Cohen Sat, 24 Jun 2006 23:23:44 GMT

Nathaniel Talbott


It's 1870. Think of Bobby the shopkeeper. He's got a small family and is starting to hear about the frontier, now that the

railroad has been completed. Even before now the railroad had been going out further and further away. He's been in the

established places for a long time, and maybe he's ready to move out the more marginal areas.

And, the Homesteading Act had just come into reality. You could stake out empty land in certain areas and stay there for 4

years and have it free and clear.

Homesteading for us is working with small companies, perhaps so small that we almost own a part of them.

Opportunity cost is the value of the next thing you could be doing. Could be a monetary cost, or could be cost in time, or

maybe you could be learning something else.

Life is risk management. Risk is tied to time. "So teach us to number our days, that we may apply our hearts unto wisdom."


Bobby does some research, and decides to buy a ticket to move out to the frontier. He buys a ticket that will take him on the

train all the way to the west coast, and he will find someplace to settle down somewhere between Boston and the west coast.

"Prepare your outside work, make it fit for yourself in the field, and afterward build your house."

In the 1870's, land was limited at some point - you had to find land that wasn't already taken by someone else. Our land is

limitless. There's plenty of room for everybody.

Bobby ends up in a small town along the railroad where he can setup a small shop. He knows how to keep a shop and likes to be

near the mountains.


"A little sleep, a little slumber, a little folding of the hands to sleep - so shall your poverty come on you like a prowler,

and your need like an armed man."

Time is our most precious. It's the only one that is completely unrenewable. Once it's gone, it's gone.


When you're out in the frontier, if you're alone, you're in trouble. You need a community around you. There are three parts:

  • family: the partners that you're building with; and even your real family should be involved.
  • neighbors: you're not in competition with everyone, you need to find win-win situations. Godd fences make good neighbors:

keep boundaries and expectations clear.

  • the town: you need room for yourself but you also need to be near good infrastructure. Learn from all the resources you have

around you.


It's hard to plow the field without a cart and an ox. Build tools that make yourself more efficient. Not just computer tools,

but marketing. It's a great way to multiply your efforts. A website for yourself is a good example.


Bobby would work hard during the week, but would have taken a break on Sunday. We need rest in order to be at the top of our

game. After all, why work if you can enjoy the fruits of all that labor? Rest is not the same as vegging out :-) It means

doing something different that is recharging and re-energizing.

If you don't have time to rest, then you're doing something wrong. Not resting ends up costing you more in the long run.


Bobby is building wealth not just for himself, but for his children and grandchildren. "A good man leaves an inheritance to

his children's children."


After five years, Bobby reflects on what he's done. He works hard but is living in the fresh air, away from the old Boston

city dirtiness, living on land that his is own. Today, it's not realistic to work for one company that will take care of us

from cradle to grave. So figure out what you're passionate about. What do you love doing? Do that. In order to do that,

along the way you will need to do some tasks that you don't love; but they allow you to do the things you do love. Never lose

your love for people. Also, never love your love for learning and improving yourself.


A rainstorm starts, so Bobby needs to get the animals into the barn. He can't control the weather. There are many things we

can't control either. Watch out for assumptions about what can and can't happen. What if those assumptions don't come true?

Evil times will happen, markets crash, etc. But if you have homesteading skills, those are probably the most useful no matter

what the outside circumstances are. Sometimes difficult times provide opportunities that only homesteaders can take advantage

of. Debt is a big problem here. It makes it difficult to take risk because you have a smaller safety net.


One day Bobby dies. What do they write on his tombstone? How would it be different than if he stayed in Boston?

"To everything there is a season, a time for every purpose under heaven: A time to be born, and a time to die..."

It's ok for your business to come to an end. Maybe it doesn't work out, or maybe something even better comes along.

Buy The Ticket!


Testing Rails Apps

Posted by Jeff Cohen Sat, 24 Jun 2006 22:13:47 GMT

Mike Clark

What brought Mike to Rails was the testing support.

Why should developers care about testing? What's really in it for me? "Because I should" doesn't really last for more than a

few days. It seems to get in the way of writing code which is what I really enjoy.

Marcel said to Mike, "But testing won't be as fun as working on the app..." But test are, in part, the insurance for the app

staying fun. Tests let you change anything you want without worrying. Software wants to be changed and you want to change

it. So testing is, ironically, all about writing fun code.

Law of Unintended Consequences: almost all human actions have at least one unintended consequence. Bad coupling leads to a

game of whack-a-mole. :-) What you thought was a small change can have an unintended consequence somewhere else.

You may think, if my app is small, then it doesn't really matter. Well, most small programs turn into bigger apps whether you

intend it or not.

So testing is about confidence. It's an early detection system you can play around with anything you want and change

anything you want without worry.

Some database-backed web frameworks make testing painful. The barriers to testing your website are too high, so nobody really

does it.

I'd rather be on Rails.

What about Rails itself?

  • ActiveRecord has 898 tests.
  • ActionPack has 820 tests.
  • ActiveSupport has 370 tests.

Don't be too skeptical - the tests are high quality. And they all pass without errors! Patches are more likely to be accepted

if it comes with a test.

Rails makes it easy to do the right thing.

Just by typing "rails killer_app" you get a bunch of test directories ready for you to use, and the guilt immediately sets in.


Before we look at each of these, we need a quick overview of unit testing basics.

def test_add
  assert_equal 4, 2+2

(Mike explains assert_equal here, etc.)

Ruby comes with Test::Unit, and Rails takes it further by opening the class and adding some helpers.

You test suite is a class that derives from Test::Unit::TestCase.

Tests are a way of teaching the computer to lots of things.

Run the tests with ruby my_test.rb. You'll get output (no green bar unfortunately) showing the results of the tests.

Core Assertions

  • assert_equal
  • assert
  • assert_nil
  • assert_raise
  • flunk
  • plus all the inverses (assertnotequal, etc.)

You can also write custom assertions to build on top of these primitives.

All Rails testing is based on Test::Unit with some important goodies added.

Back to the directory structure...

test/unit is for testing one model. Start with small tests and grow your suite, you don't have to start by testing the

hardest stuff first.

Mike shows a simple example of a Product class with several validatespresenceof, etc. and makes sure that the models do

report validation errors.

How about testing uniqueness? To do that we need a a database with data in it. So that's what fixtures are for. Using

Yaml you can define rows of test data without ever going to your database. One nice thing is you can actually put Ruby inside

of your fixtures, because it's really interpreted by Erb!


fixtures :products

def test_unique_title
  product = Product.new(:title => products(:rails_book).title, :price => 1234)

  assert !product.save

  assert_equal ActiveRecord::Errors.default_error_messages[:taken],

Before each test, a SQL transaction is started your fixture data is loaded into the db, and at the end of the test the

transaction is simply rolled back.

Functional tests are for your controllers.

How Does Rails Help?

Sending test requests: http_method(action, parameters, session, flash).

get :index get :show, :id => 1 etc.

Custom assertions

assert_response(type, message) assertredirectedto(options, message) assert_template(expected, message) assert_tag(conditions)


session flash cookies assigns

Mock Object Support

When difficulties with dependencies become an excuse for not testing...

Don't go crazy with mocks. A good example of a mock is a payment gateway - you don't really want to make the call when running

the tests.

In your test/mocks directory, create a file with the same name as the file you want to mock.

require "lib/payment_gateway"

class PaymentGateway

  def online_capture(credit_card)
    # return a fake response

Integration Tests

Tell a story...

A user goes to a store. They add a product to the cart... etc.

A testing mini-language (DSL)

  • Singleton methods

For tests to be useful, you have to run them!

Lots of ways to run tests from the command line:

rake test:units rake rake stats rake test:functionals rake test:uncommitted

Are You Testing Enough? Try rcov for some code insurance. Getting bug reports? Use rake stats.


  • Work with unsaved records if you can.
  • Access records by fixture name, not by id.
  • Write your own custom assertions to provide higher-level DRYness.
  • Use named routes for ease of use with assertredirectedto

Testing helps you write better code... faster! It may be counterintuitive because of the addition time needed to write the

tests. So just write tests incrementally as you go.

When do I start writing tests?

  • Today!
  • When a bug is reported
  • Tomorrow
  • When adding new features
  • Yesterday!


Rails, Ajax, and Universal Design

Posted by Brian Eng Sat, 24 Jun 2006 20:30:48 GMT

Jason Kunesh talks about universal design, accessibility, and usability.

Universal design

  • A focus on designing products that are usable by the widest range of people
  • "Inclusive design"
  • Usability vs. Accessibility debate

Accessibility is for...

  • People with disabilities
  • People with cultural or technical disadvantages

Accessible technology

  • Perceivable
  • Operable
  • Understandable
  • Robust

Usable technology

  • Jakob Nielsen cites 5 factors:
    • Learnablity
    • Efficiency
    • Memorability
    • Errors
    • Satisfaction

Epicenter or IUI design

  • 37signals - "Start from the core and build outward"
  • Microsoft - break down the tasks that the users have to accomplish and create 1-to-1 to pages

Other Principles

  • Steve Krug's Trunk Test
  • Heuristic Evaluation
  • Tog's First Principles, Fitts' Law

Why is it important?

  • Reach more people
  • Legal protection
  • Increased public approval
  • It's the right thing to do

How do we accommodate users?

  • People with disabilities
    • Web standards XHTML + CSS
    • Multimedia transcribed
    • Assistive hardware
    • Cognitive impairments are often not addressable
  • People with cultural/technical disadvantages
    • Page optimization, alt text, etc.
    • Language declaration, standardized access keys, etc.

Visual Disability != blind

  • Age-related degeneration
  • Glaucoma
  • Cataract
  • Diabetic Retinopathy
  • Color Blindness


  • Screen Magnifiers
  • Screen readers

Blind users can comprehend speech at 370 words per minute; accomplished users 490 wpm or more. (Audio of 100 wpm incomprehensible to me!)

Assistive hardware

  • Sip and puff
  • Datahand
  • Predictive keyboards
  • Reading machines
  • Headwand
  • Eye-tracking
  • Mouse-by-mouth

Legal + W3C framework

  • WCAG 1.0
  • WCAG 2.0

Ewwwwwwww... lawyers

  • Ramada.com and Priceline.com
  • Access Now, Inc. vs. Southwest Airlines
  • AOL sued
  • Target.com sued

Why do I care?

  • The user is your responsibility
  • You have a form factor that is mutable
  • Good software lets customers have their cake and eat it too

Why personas?

  • You are not a user
  • Your customer may be a user, but not a typical user.
  • Cooper's 4 truisms

Agile personas

  • Cooper and Reimann say coders can't be designers.
  • It's okay, we're not doing it solo.
  • We are going to go Agile, and our customers will design our personas.
  • Same as agile development
  • Persona attributes
    • Demographics (name, age, sex, etc.)
    • User goals... the most important
    • Primary, secondary, or negative personas
    • One to two page narrative of persona's personal experience
    • Can have multiple personas in any role
    • Get a picture from Corbis, Getty, Flickr, etc.
    • A quote from the persona
  • Where do you find data?
    • Customer
    • Task analysis
    • Jupiter Research
    • Google for personas to extend
    • diveintoaccessibility.org
    • Logs
    • Groups - user, support

Um, this is RailsConf!

  • Intelligent URL design
  • Labels and terms that resonate with the personas
  • Consistent filenaming - use whole words, not abbreviations
  • Rails "newness" lends it to progressive enhancement
  • New methods (e.g. Streamlined)
  • Graceful degradation
  • Progressive enhancement - as you add AJAX, ensure the prior, less interactive version is not broken
  • Text alternative
  • AJAX and screen readers - support is uneven
  • http://sitepoint.com/article/ajax-screenreaders-work

(Examples of accessibility without usability and vice versa)

Big future endnote

  • Rails is fast becoming the API for web applications, UI to DB, much like the Windows API once was for desktop applications.


Older posts: 1 2 3