RailsConf 2006 Recap

RailsConf

June 23-25, 2006, Chicago, IL

Welcome

Rich Kilmer—Ruby Central Inc. 501c3

RubyConf 2006, October 20-22, Denver, CO
  • registration coming in July
  • Google summer of code
  • rubyforge
  • rubycentral.org/pledge
Sponsors:
  • Five Runs
  • IBM
  • The Pragmatic Studio
  • TextDrive
  • Thoughtworks

Keynote

Dave Thomas, the father of Ruby in the western world presents 3 Unsolved Problems

What’s Good? Googling “Ruby on Rails”—21,000,000 hits but more importantly, in the sidebar:
  • web hosting, training, consulting,
  • real, serious B2B
  • people making their livings
  • alternatives to ROR
What else is good?
  • RubyForge—gems and downloads 536K for rails
  • Google trends—ROR nice graph vs. websphere or jboss or tapestry or “spring framework” or zend
  • functional and fun to use
  • Thank you rails core team, working 24hrs per day.
  • 14 years of ruby

But…

David Hilbert, German Mathmatician—23 unsolved problems, Paris 1900. Dave’s list was cut down to 3 problems in rails

Please Do Investigate means “That’s a good idea. Go do it.”—we’re all programmers, it’s open, go do it.

To move to the next level:

Data Integration
  • use database schema-level constraints, reflect them in models
  • work with database foreign keys—make them easy to define in migrations, add belongs_to if fk is detected, primary keys not artifical ids, especially in migrations, support for composite pk’s
  • support for distributed transactions
  • standard attributes-based finders
  • non-database models including JMS/MessageQueue
Real-World CRUD
  • scaffolding brings people to rails but it is the worst of web 1.0
  • support for table relationships
  • ajax
  • cross-application skinning
  • bring the beauty of AR to views and controls
Deployment Capistrano—best deployment system there is, let’s make it better
  • push model, application contains the configuration information—doesn’t factor in server admins
  • better? cooperative deployment, library requirements, nominate server roles, where the files go, permissions and security (including database passwords)
  • setup server once then setup applications as needed

“All developers deserve to be happy.”

AC/DC, Stravinsky and Rails

Adam Keys, PureDiscovery—How can software be better constructed?

AC/DC

  • Adam’s Law of AC/DC—if you know the title, you know the chorus
  • Corollary: Read the url, you will know the name of the controller and probably the model, too.
  • Explore the Space—they don’t feel compelled to fill the song with notes vs. Eddie Van Halen-ism
  • Consistent—they’ll never slip a ballad in on you. Rails will always be MVC. Convention.
  • Intuitive—space gives you time to dance and flail and throw up horns of rock. MVC vs. spelunking to find a function
  • Bus factor—how many people have to get hit by a bus before your project dies? Rails, like ac/dc, has bus_factor_ > 1. Don’t be a cowboy.
  • Easy—reusing idioms, you can pick it up by ear, tablature has no rhythm information
  • Flatten the cost curve—write, rehearse and record

The Rite of Spring

  • Igor Stravinsky (1913—one of his 4 ballets)
  • Tribal communities and human sacrifice—1913
  • You and 109 of your closest friends to play it. A J2EE app on a supercomputer.
  • Conductor makes the artistic decisions. bus_factor == 1
  • ink is dry and won’t change for centuries
  • complexity—good for regulations and money, piano music for a 29-handed alien
  • 11/4 time vs. ac/dc’s 4/4, non-conformist expression
  • Fight!—be passionate
  • Aesthetic—be artistic
  • Rails lets us create

“Meanwhile, in the rest of the world.”

David Demaree who makes Simple tools, connecting people to their customers, before that, he did tech support

Web 2.0
  • communities
  • participatory
  • content as rss
  • less time waiting => Ajax

Are the users still in Web 1.0?

!customers know what their computers and browsers can do !users know what they’re talking about—wishes are often aspirational. overbuilt, the feature goes unused. !users are choosing their environment (XP, IE6, email, proprietary IM client, itunes or WMP, mediocre broadband, search engine)

why don’t they love the hotness?
  • not aware, don’t think they need, not properly explained
  • they already have lots of friends
  • feel they don’t understand computers
  • don’t see the value of the new hotness, new web is alienating
why should we care?
  • hotness would be a hit if they understood it
  • not just grandma
  • idealism—change the world for everybody
what’s the solution
  • do your homework
  • talk to people—learn better ways to explain technologies
  • solution is more that a feature set—it is a use case
  • think about the future
it starts with how you think about a product
  • who’s going to use it
  • how will they use it
  • how often will they use it?
problems with RSS (syndication, including iCal)
  • awareness is low—12% are aware it exists, 4% have knowingly used it, 27% use it unknowingly.
  • 28% know about podcasts, 2% subscribe to them
  • poorly-conceived browser features
  • portals—give them buttons for their portal?
  • RSS is invisible to the end user
  • describe how it pertains to your app—don’t assume user connects your RSS and someone else’s
  • explain the orange icon—in the context of that particular page
Tags
  • what is a tag? really, what is it? microcomments?
  • what are people looking for in the app?
  • grouping items?
  • open or closed-ended taxonomy
  • suggest tags
  • ExtraTasty is well-designed with tags—comes off as a great search.
  • Cork’d—tags aren’t forced on you, in the context of a review.

Rails Application Optimization techniques and Tools

Stefan Kaes—15 months on rails, recipe application which performed poorly, 4 or 5x better than it was a year ago

  • Trying to improve without measurement is foolish
  • bad design could be an inherent performance problem
  • plan ahead to meet a specific performance goal
  • not every page must be optimized
Four Metrics
  • Latency—response to user
  • Throughput—requests per second
  • Utilization—not idle most of the time on machine
  • Cost Efficiency—performance per unit cost

min, max, mean, standard deviation—infers reliability of the data you’ve obtained

  • rails log files (Logger::Debug)
  • rails analyzer tools (log to syslog)
  • script/benchmarker
  • vendor-specific db tools
  • apache bench
  • httperf—can define sessions
  • railsbench

config/benchmarks.yml config/benchmarks.rb

$RAILS_PERF_DATA, indexed by date and benchmark time

perf_run, perf_diff, perf_times, perf_comp

-log, set log level -nocache _path -sv1PV, run using Ruby Performance Validator (commercial, windows-only) -patched_gc

Top Performance Problems

  • slow helper methods
  • complicated routes
  • associations
  • retrieving too much from the db
  • slow session storage (AR store, esp. with action cached pages)
  • db performance is usually not a bottleneck (less than 10% of object creation time)
  • instantiating AR objects is more expensive
session containers
  • does not scale, loses when server crashes
  • file system—slower than AR store
  • SQLSessionStore—raw SQL queries
  • memcached—presumably scales best, very tunable
  • DrbStore
Cachable Elements
  • pages—fastest, difficult with logins
  • actions—2nd fastest option, caches results of controller actions, can use login id as part of storage key
  • fragments—can be made user-aware, several containers available

Components—avoid them

Filters—don’t rerun filters n times, pass context info explicitly

Instance Variables—don’t make them in the controller if you don’t need them in the view

Suggestions for Improvements

Slow Helpers
  • pluralize—do pluralize(n, “post”, “posts”), instead
  • link_to and url_for—code out the html directly, if you have lots of links. less GC. caching helps, as well.
AR issues
  • associations—in a belongs to use the :include options if you need the owner item later. could use piggy_back to just get the data you really need from the :has object… article.author_name vs. article.author.name
  • type conversion happens on each access, cache the converted values if you use them several times in one request (date for example)
Performance-Aware Ruby Programming
  • don’t add unnecessary method abstractions
  • use attr_accessors only for external access
  • cache data in class variables
  • use constants, not inlining

rubygc.patch from railsbench patches garbage collection

rails template optimizer, he is working on

Designing for Shared Hosts

Geoffrey Grosenbach

Design

keep your app small

page caching is the way to go
  • caches_page :action_name
  • cache_sweeper :foo_sweeper, :only => [:create, :update, :destroy]

    FooSweeper
        observe foo

        def after_save
            expire_foo(record)
        end

        def expire_foo(record)
            expire_page :controller => "", :action => "", :id => record.id
        end
    end

don’t use typo—it has expanded beyond “lightweightness”

don’t use lighty on a shared host, especially since it will be proxied through apache

use capistrano so deployment, at least, is consistent
  • set :checkout, :export
  • set :restart_via, :run
  • set :use_sudo, false

override the restart task

task :restart do
        run "#{currentpath}/script/process/reaper --dispatcher=dispatch.fcgi" 

write and run tests to get more stability

Maintenance

  • regularly run the reaper - ssh is the 51st process - daily from cron, using restart task above
  • override the fcgi kill request
  • use server monitoring
    • dwatch from nubyonrails.com
    • montastic
    • heartbeat.highgroove.com

troubleshooting

  • check your shebang line
  • ./script/server -e production
  • ./script/console production
  • tail -f apache.log production.log
  • time is the solution in some cases—wait 20 minutes for the changes to take effect
  • create 1 unix user per rails app

Martin Fowler—Why I like rails, even though I have never used it.

opinionated software

Design

uses the active record pattern

  • proved to be more useful than he had thought
  • bad pattern if you have to deal with dba’s
  • no one architecture or pattern works for all apps in a company

drive towards simplicity

  • versus EJB’s whic had enormous power and difficulty
  • spring and hibernate came in response
  • rails pushed that response forward => flexible and simple beats flexible and complicated

Quick != Dirty

  • smalltalk was fast to work in but also well designed.
  • quick and clean versus VB/PHP or enterprisey behemoths

testing is part of the process

  • TDD and extreme programming—well-timed to pick up the benefits of those trends
  • fast vs. clean is a false dichotomy
  • he also thought smalltalk had a future, too.

Conversations with Customers

  • customers should care about environments
  • with lightweight methodologies the relationship becomes conversational, a 2-way street, rapid feedback cycles with customers
  • lower cycle time engages the customer more effectively
  • java lowered cycle time for people who were using C
  • give users something and watch what they do with it
  • lightweight alters the mindset—focus on how the business works, instead of the plumbing of the framework
  • how can we make a difference to the business?

Ruby

  • knowledge of scripting is important
  • his progression was bash < perl < python < ruby
  • everythings is an object, especially the libraries
  • rails gets a lot of its mojo from ruby
  • rails should be simple enough to not need a conference
  • smalltalk wanted to be everything

post modern programming

  • modernist was strict lego blocks
  • real world is more like unix, a mashup, not so pretty—post-modern appreciates that
  • glue rails to other weird stuff (coin changers, etc.) using ruby
  • deal with the complexities—they cannot honestly be removed
  • gets out of the way and lets you get things done

The people in the community—the alpha programmers

Paul Graham—The Power of the Marginal

outsiders outnumber insiders

  • corrupt methods for selecting the elite—anti-tests
  • judge talent at its best and character at its worst
  • tradition is not as helpful a guide as it used to be

the starving artist

  • be in direct contact with the medium
  • seek out contrarian projects
  • cycle through projects quickly
  • responsibility is a contraint
  • getting an audience is easier on the web
  • audiences are learning how to be stolen
  • “just try hacking something together”
  • curiosity vs. duty
  • when you’re not sure what to do, make something
  • focus on the margins of the margin
  • you’ve won when they say “You’re unqualified and your work is inappropriate.”

Ajax on Rails

Stuart Halloway and Justin Gehtland—Relevance, LLC

If ajax is crack, rails is the free vial.

Prototype by Sam Stephenson

  • core support for dynamic web apps
  • hides browser oddities
  • used by scriptaculous and rico
  • driven and inspired by ruby on rails
  • simple and elegant
Example: Ajax Search
  • javascript:void%200—no-op form, does not submit
  • watch the field, check it twice per second (frequency: 0.5), submit the changed value via xhr, show spinner, hide spinner, update element
  • :only_path => false strips the relative pathing in url_for
  • server side renders a partial
Conclusions
  • helper methods are provided in Ruby that generate javascript for us
  • converts ruby hashes to JSON (javascript object notation)
xhr helper methods
  • link_to_remote—user clicks a link
  • form_remote_tag submits a form
  • observe_field—user changes a field
  • submit_to_remote—submits a form
Dealing with DOM id’s Degradable Ajax—“I know you’re lame, but I like your money.”
  • ajax apps should also work as plain old web pages
  • different url strategy—ajax to one url, POW to a different url
  • same url strategy—pass ajax specific header (xhr?), use partial for ajax, wrap partial in template/layout for POW
  • action=”/no_javascript” onsubmit=”code to do as javascript”—provide :url and :html

Scriptaculous by Thomas Fuchs

effects and widgets library built on prototype, driven by ROR, simple and elegant

autocomplete demo
  • text_field “user”, “favorite_language”
  • div class=”auto_complete” id=”user_favorite_language_auto_complete”
  • auto_complete_field :user_favorite_language, :url => { :action => ‘autocomplete_favorite_language’ }
  • autocomplete_favorite_language action returns a ul
drag and drop demo
  • draggable_element(domid, :ghosting => true, :revert => true)
  • drop_receiving_element(‘pending_todos’, :accept => ‘completed_todo (a css element)’, :with => “thing that splits out the id”, :url => {:action => :todo_pending, :id => @user})

javascript generator and rjs templates

  • rjs expressions: page.alert, page.redirect_to, page.call, page.assign, page.show, page.hide, page.toggle

    render :update do |page|
        page.replace_html...
        page.sortable...
    end

streamlined.relevancellc.com

  • coming next month at oscon
  • themable—looking for themers

Lessons from Blinksale and IconBuffet

Scott Raymond now full-time at Firewheel Design—blinksale api is not ready for the public yet (using the simply restful plugin and to_xml), being the lone developer

3 elements from Ancient Architecture to modern web apps: firmitas, utilitas, venustas

man is the measure of all things

Firmitas—strength, firmness, durability

The foundation. Not necessarily rigid. The first thing you build.

Working with Designers
  • templates first—basically done before even getting the programmer, able to provide an accurate estimate of time and money
  • mockups directory—in the public directory, checked into svn, checked out for the designer, they communicated through checkins for the first couple of months
  • started writing tests—created the assert_valid_markup plugin
    • checks against the w3c
    • can do :get or strings of code
    • can use as a class method, as well, like “assert_valid_markup :bar, :baz, :qux”
  • tight loops—3 or 4 times per day, translating the original templates to views, helpers, etc.
  • talk first and constantly—project management is communication, esp. in the last 20% of the project

Utilitas—usefulness, functionality

using ajax to provide a pleasing experience for customers—mini cart in the sidebar, originally using callback loops in prototype since rjs didn’t exist yet.

jacob’s well—fitness for a purpose, situatedness.
  • Reduced rate, 4-5 months. Last 2-3 weeks as coding.
  • Interviewed church members and staff. Serve that community well.
  • community aggregator from flickr and rss feeds of friends and neighbors—updated hourly with a cron job
  • all images are from members of the church in a flickr pool.
  • think about the goals
  • google maps—show in relationship to each other (public could find members who live near them)

Venustas—Beauty, Grace, Delight. Correlated to human intelligence.

  • nice ui, clean urls, beautiful code
  • single table inheritance—firms and clients derive from companies as subclasses
  • using has_many_through with conditions to get past due, open and closed invoices (has_many classname, through, source, class_name, conditions)
  • invoice has many payments, calculating total due for each invoice
    • needing to calculate late fees, hard to do in sql
    • came up with calculated_attr—specify what the total depends on

The BBC’s Programme Catalogue on Rails

Matt Biddulph

BBC has more than 80 years of history, back to lab coats. Archive is a 60’s-era warehouse, miles of shelves, can smell the formats decomposing, recordings back to 1937, wax cylinders for the earliest, until the mid-80’s 78 RPM records were the archival format

  • subject categories tags
  • experimental prototype beta
  • 2 months from 2GB pipe-delimited db to gold master of web 2.0 remix
  • went from “Native Infax” green screen app to web 2.0 with tags, feeds, ajax, et al
  • rigorous schema derived from library science to work from
  • all content tagged with conceptual categories, chief archivist enforces tag names, so that none are unnecessarily added
  • Good urls are beautiful and a mark of quality design.
  • Tom Coates of Yahoo
  • BBC 2.0 isn’t “on” the web, it is “part of” the web
  • URLs are foreign keys for the web
  • machine readable version of all entities, all urls
  • wikipedia links derived by specifying “en.wikipedia.org” while using the yahoo search api
  • cataloging nearly 1MM programs
  • legacy db hopefully has minimum number of joins
  • most important model goes at the center of the star schema, one order away from the sub-data.
  • they use ajax to run their more complex queries when they are needed vs. when the page is loaded
  • when using fulltext search in mysql, review he wacjy defaults in mysql.conf—parse the scores of the search results to get the “better bets.”
  • benchmarked at 30 requests/second initially, serving 96.5% of all requests in < 1 second, average of 37 milliseconds
  • clean xhtml can be rendered quickly at the browser end
  • read “building scalable websites” by Cal Henderson
  • load test with realistic urls—see siege as a way to randomize urls
  • deployment took four months, ending up on a server that was almost under someone’s desk
  • excited about mongrel, hates fcgi
  • becoming a reference for concepts
  • nightly updates are exports of updated and added records flagged as dirty in the main database
  • urls use secondary keys, not artificial ids, to maintain continuity for bookmarks or api users when the backend changes

Accelerating Rails with Lighty

Jan Kneschke—mail developer of lighty, works at MySQL AB, lives in Kiel, Germany, cares about performance, not a web designer

History

  • Jan 2003: Started as a proof of concept, outperformed apache and thttpd from the start
    • POC for the C10K problems: how to handle 10K parallel connections on one box
    • single process, single-thread, non-blocking IO
    • optimized core: event handling uses OS specific sys-calls
    • utilizes zero-copy tcp with the help of sendfile() and friends
  • Dec 2003: new config file format
  • Aug 2004: Conditionals
  • May 2006: Had 63,000 users in May 2006

Config

  • basic types: int, string, assoc array
  • conditionals used against the urls, using regex

    $HTTP["url"] =~ "^/app1/" { 
        server.document-root = "..." 
        url.access-deny = ("~", ".inc")
    }

Architecture

  • idling connections are cheap and spend no CPU time
  • ajax likes keep-alive
  • COMET builds on keep-alive
  • only a KB and one file-descriptor
  • youtube is on lighty (static content)

dynamic content

  • offload all cpu intensive work into a process
  • choose one of fastcgi, cgi, scgi, proxy
  • don’t use mod_ssi

the cgi’s

CGI

  • in 99% of cases slower than the other options
  • small process running 5,000 concurrently
  • meebo.com is an example

FastCGI

  • mainly for rails and php support
  • rails adopted lighty for its superior FastCGI support
  • installation on application side can be tricky
  • licensing problems
  • very powerful (keep alive, multiplexing, out-of-band communication)

Simple CGI (scgi)

  • slimmed-down, used by python community

Proxy

  • an http proxy module with load balancing
  • Fair, Round Robin and Hash (CARP) load balancing options
  • The interface to mongrel
  • one of the weaker parts of lighty
    • no output streaming
    • fail-over handling is missing
    • balancers broken in 1.4.11, but fixed in SVN

Accelerating Rails—the less you use the faster it gets

  • cache as much as you can
  • use the 404-error-handler to call Rails only for non-cached content
  • use Content-Length, if-Modified-Since and ETag for dynamic content
  • use CML

HTTP caching

Load Balancing

  • separate fastCGI

    fastcgi.server = ("fcgi" => (
        ( "host" => "10.0.0.1") 
        ( "host" => "10.0.0.2"))

  • use 1 lighty and 9 rails backend servers if you have 10 hosts
  • NFS to share the directories
  • a shared session storage (like memcache)
  • use graceful restart to have a low impact in the running requests
  • use a tcp multiplexer like LVS to add and remove backends at runtime

Special Modules

mod_secdownload—use rails to authenticate static file transfers
  • move sensitive files out of the document-root
  • uses temporary urls …/download///file
  • md5 is built on the filename, timestamp and a secret
  • timestamp is a unix timestamp for timeout
X-sendfile
  • authenticate in the app
  • offload static file transfers to lighty (X-sendfile: /data1/files/secret.xls)—does not have to be in document_root
  • no extra buffering
  • backend is released earlier
  • in 1.4.x only in mod_fastcgi
mod_flv_streaming—build your own youtube
  • FLV are flash video files
  • the netstream object in flash can only stream, can’t seek
  • workaround: create flv’s at runtime by seek into the FLV and prepend a new FLV header
  • youtube uses lighty but does not yet use flv-streaming

CML

  • short for “Cache Meta Language”
  • assumption > 95% cache hits
  • cost of a cache hit is mostly making the decision—cache hit or cache miss?
  • move the decision out of the application and make the decision simple
  • uses LUA as the language—easy to learn, fast, compatible, embedded, portable, small, extensible
  • will replace mod_rewrite in apache

debugging

Testing Rails Apps

Mike Clark—“Testing? What’s in it for me? Testing isn’t as fun as working on the app” but… “Test are, in part, the insurance for the app staying fun… You can add or fix things, worry free.”

  • Law of Unintended Consequences—almost all human actions have at least one unintended consequence.
  • Traversing the application manually to test does not scale. Reload button is not a regression testing tool.
  • If your app is small, it won’t be for long.
  • Have the confidence to make changes and tools to detect the inevitable rodents that appear.

ROR Tests: 898 in AR, 820 in AP, 370 in AS. Investment pays off every time the tests are run. ROR makes it easy to do the right thing. Instant guilt when the test stubs are written.

Some Unit Testing Basics


    def test_add
        assert_equal 4, 2+2
    end

write a few of them and put them in a test case… a collection of methods that make non-bogus assertions… computer remembers the low-level noise and requirements… happy dots

  • assert_equal
  • assert(boolean, message)
  • assert_nil
  • assert_raise(exception, ...) { block }
  • flunk(message)

all rails testing is based on Test::Unit, with some extra goodies

unit tests—test one model

start small, don’t start with the really, really hard stuff


assert !product.valid?
assert produc.errors.invalid?(:title)
...set a good product...
assert product.valid?, product.errors.full_messages

test price positive? test the basic boundaries
  • set price = -1 and test
  • set price = 0 and test
  • set price = 1 and test

fixtures test data, one fixture per model in a yaml file

testing for duplicate titles requires a database-stored model, created in fixtures

use erb in the test file to generate fixtures dynamically

call “fixtures :products” to initialize the fixtures—cleans out table and inserts the fixtures in the test database, when you run a test method transactions are used to prevent test methods from stepping on each other

assert_equal ActiveRecord::Errors.default_error_messages[:taken], product.errors.on[:title]

functional tests

test a controller:
  • index action prompts login—test access control
  • good login moves on
  • bad login loops you back

setup method makes it so we need no web server

    
    def test_index_without_user
        get :index
        assert_redirected_to :action => 'login'
        assert_equal "please login", flash[:notice]
    end
    

to do it with a user: dave = users(:dave)

basic format => action: get, post, xhr, request parameters, session values, flash value

custom assertions:
  • assert_response :success
  • assert_redirected_to
  • assert_template ‘store/index’
  • assert_tag: crawl the dom

mock objects—use them when weird dependencies become an excuse for not testing

Mike uses his 1 mock in the payment gateway.
  • put matching name in mocks
  • override the model’s function that you’re avoiding

Integration Tests—User Stories of progressing through the site

linked tightly with business language, has its only mini-domain-specific-language


open_session do |user|
    def goes_to_store
        get :index
        ...
    end
end

How am I going to test this? If code is difficult to test, it will be difficult to use.

Not just testing, designing better code in the first place.

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

  • rake—runs them all
  • rake test:unit or functional or integration
  • rake stats—compare code to tests, sheer volume
  • ruby /path/to/test.rb
  • rake test:recent
Are you testing enough?
  • rcov—coverage analyzer
  • insurance
  • bug reports
  • rake stats

Tips

  • work with unsaved records when you can
  • use fixture mechanism not record ids…
  • write custom assertions
  • use named routes

Testing helps you write better code… faster! (overall)

When to start?

  • today
  • when a bug is reported
  • when adding new features
  • yesterday

Resources on Rails

David Heinemeier Hansson

Saying “no” to a lot of things.

“We are bending the outside world to us.”

“Rails, in large part, is an imaginary world… The real world is a miserable place to be. The real world is where your held down by years of practices.”

There’s a lot more going on.

Book sales: Agile Web Development 40K, 7K in japanese, 3 more japanese original books on the way

43things.com—3.5 MM rails pageviews per day

Create Read Update Delete—the baseline of most of the work we do.

What they told you…
  • Simplistic—not enough, too simple for a complex world
  • Unfulfilling Works—not a satisfactory way of working
  • Unworthy, too basic
  • Shame

How I learned to stop worrying and love the CRUD

methods show create update destroy
http verbs get post put delete
sql select insert update destroy
actions find create update destroy

but its a pain in the ass to use, because the rest of the web wasn’t able to handle it

routes file:

ActionController::Routing::Routes.draw do |map| map.resources :person end

Why Bother?
  • consistent controllers—decisions are bad, free up brain cycles for important things
  • simplicity
  • discoverability

The Grand Prize—constraints are liberating, the world is crud, a straightjacket for your mind

:has_many’s :through operator is the core of habtm relationships—the “throughs” become crud.

  • users in groups become memberships—now you have something you can crud
  • accounts with plans become subscriptions—now you have something you can crud
Model beyond “things”
  • Relations
    • subscriptions
    • memberships
  • Events
    • closure
    • change
  • States
    • reviewed
    • accepted

The devil leads you to make random changes everytime you run into a problem.

The angel gives you crud. You have not thought this problem through. Forcing people to do the right things. Single auto-incrementing integers as id’s. If you want to indulge in insanity it should hurt. If you’re not testing, you should be. Model better things. Richer vocabulary about the application you’re working on.

“I’m not going to be indifferent. I’m going to make value and moral decisions about multiple ways of doing things.”

But! CRUD is not a goal, just an aspiration, a design technique.

Have to let out the steam of the exceptions. Sometimes special code needs special considerations. Crazy schemes crop up if there is no valve.

POST
  • /kases/1;close
  • /identity;aspect

you can model anything as crud, although occasionally it is not approriate

And there is more…

Answering to mime types—one controller for many clients

one action returning different results


    respond_to do |format|
        format.html for a person on the web, 
        format.js gets text/javascript back
        format.xml gets render :xml
        format.icl for their birthdays
        format.atom
    end

flexible input model

can, by the same idea, create an item
  • .html returns a redirect index
  • .xml returns location of the created object
  • .js returns rjs
  • .mobile—Mime::Type.register :mobile, “text/x-mobile”

One More Thing—“Active Resource”

Started two days ago: Consuming the REST XML generated


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

# find
matz = Person.find(1)
matz.name

# create
david = Person.new(:name => 'David')
david.save
david.name = "David Heinemeier Hansson" 
david.save

people should be able to create things by hand

Rails Acceptance Testing with Open Source Tools

Dave Hoover

Watir for IE, FireWatir for Firefox—DSL is implemented in Ruby
  • very slow
Selenium 0.7
  • install the selenium gem
  • install the selenium_on_rails plugin
  • install the RedCloth gem
  • uses “selenese”

./script/generate selenium login
./script/server -e test

rake test acceptance

Sahi—lots of underscores but worth a look

Experience Report with Alex Chaffee

Next Year—2007 RubyConf in partnership with O’Reilly 5/17-5/20 in Portland, OR


About this entry