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
- 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
- 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
- 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
- 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
- hotness would be a hit if they understood it
- not just grandma
- idealism—change the world for everybody
- 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
- who’s going to use it
- how will they use it
- how often will they use it?
- 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
- 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
- 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
- does not scale, loses when server crashes
- file system—slower than AR store
- SQLSessionStore—raw SQL queries
- memcached—presumably scales best, very tunable
- DrbStore
- 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.
- 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)
- 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
- 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
- helper methods are provided in Ruby that generate javascript for us
- converts ruby hashes to JSON (javascript object notation)
- 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
- bruce williams—end up with div id as @person.dom_id
- 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
- 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
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
- 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
- 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
- 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
- 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
- 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
You’re currently reading “RailsConf 2006 Recap,” an entry on planet jerry!
- Published:
- June 29th 10:30 AM
- Updated:
- August 8th 03:00 PM
- Sections:
- Ruby and Rails



0 comments
Jump to comment form | comments rss [?]