RailsConf Europe 2006
I recently went to RailsConf Europe 2006. Rails is very exciting technology, but the Rails community is still a bit excitable. Anyway, here are my notes. Apologies in advance if I offend anyone!
Keynote - David Heinemeier Hansson on Rails
1.2 is out soon. Changes are
- entire dependency system. Modules auto-reload, paths will reasonably work, bolt in controllers and models.
- Routing also changes, to prevent issues like that before
hundreds of bug fixes - also some REST stuff - called SimplyRestful.
SimplyRestful
- Slapping a grid of conventions down on controllers. So controllers will look the same as you move from project to project.
- New scaffolder (not shiny like streamline) will look ugly by design. Intended as a supplement to the current scaffolder, but will work with the new restful style. Remember the intention behind scaffolders is for them to be a learning tool
- Basically there will be a convention based mapping for HTTP verbs to controller functions that map to database operations.
e.g. I create a controller for my blog posts called PostController. The scaffolder automatically define a function called index that is automatically routed to from GET /posts/. The scaffolder does this by writing up the routing file.
- Great quote: “that smells a little bit like configuration so we might need to change it”
- Automatically does things like giving you an XML based output of your page
ActiveResource
- Built on top of SimplyRestful but is an external GEM that has to be added onto 1.2. Not sure if it will ship with 2.0
- Like ActiveRecord but for HTPP. This is basically a way of creating a class that represents a remote restful service on another server - in the same way that an ActiveRecord class represents a remote table. Very, very neat.
- Great quote: “Woo hoo”.
- Unlike ActiveRecord, where the class can check what the schema is and therefore check any data sent to it, this does not do anything like reflection to create the class, so checking is not done (need to see what this means a bit more later).
- Great quote: “so all the stuff I talked about at the last conference actually works”.
SimplyHelpful
- The more they worked on other modules, the more they realised that views do not have sufficient conventions to make them transparent. So they now have a module called SimplyHelpful, which is views by convention.
- They want to ‘encroach’ on your HTML, CSS, JavaScript.
- Already a plugin, but this is really cutting edge now, though it does work and it is in production. Will be a part of 2.0
- Great quote: “if there is one convention that is easily guessable, then it makes me happy. The great thing with conventions, is that as soon as you lay them down it is like a super highway for information to run down.”
- effectively it builds a model of the html, scripts or whatever and lets you address it by convention.
- Also has lots of extremely nice syntactic sugar for the rhtml files that reduces the amount of code you need considerably.
Next release will be 2.0
Lots of Rails cruft still hanging around that will be removed for this release. Flagged as deprecated in 1.2.
Vendoritis
- This is a personal rant by DHH (and what an angry rant it was). There have been two big events recently that have been x-rays of Rails. The first was the security patch in the routing code, a 23 hour fix window, which they are proud of. Showed early signs of vendoritis
- Symptoms of this are ‘entitlement’ and ‘indignation’. The first is a belief that by downloading some open source you are entitled to the time of the developers. This is not a shop, the customer is not always right. You gain your entitlement by contributing to the project, code or insights. Similarly with indignation.
- One of the arguments was “do you want Rails to be the standard web platform or do you want it to be a hobbyist platform for people running their blogs”.
- There are a variety of treatments for dealing with this. None of them very polite. But it must be treated to stop it spreading. More important though is preventing it.
- Of course there are some valid criticisms, they just have to be reasonable. The JavaRanch terms of service are good to remember ‘be nice’. It matters how you say it.
- Core Rails team is like a mutex and is not fast at accepting patches. This shows that it is too big to work the way it currently does. Needs to split up into smaller communities that build plugins. For example l10n should be a plugin. Most of the new work the core team are doing is coming out as plugins.
Keynote - Kathy Sierra - Creating passionate users
- Great quote: “If you saw a man drowning and you could either save him or photograph the event - how would you tag it in flickr?”.
- People believe their decisions are 90% logic and 10% emotions, but even for geeks they are 10% logic and 90% emotions - to prove this she asked everyone who owned an iPod to raise their hand and the entire room raised their hands.
- Our goal is to give our users a higher resolution experience, in the same way that modern jazz afficionadas can actually hear distinct patterns, not just noise. (or so they claim).
- Good products are quick to get over the suck threshold and make it as far as the passion threshold. Too many people just hang around in between because of the fear of an upgrade dropping you down below the suck threshold.
- We assume we are teaching being about the tool, but actually we need to teach them what they can do using the tool. Particularly important when writing manuals.
- We treat people who are about to be customers to so much better information than those that are customers (not at Nominet of course!).
- You have to think “how can I help my users do extraordinary things?”
- Cognitive theory shows us that the mind is very sophisticated, but the brain is still in the stone age. It has a set of primal responses and filters.
- These responses include things like ‘what is unusual here’, and then all the normal apple pie stuff.
- When your brain is reading conversational documentation, it cannot tell that it is not involved in a real conversation and so it is forced into paying attention. When you read formal documentation your brain just switches off.
- So now you have their attention, what comes next?
- Some books to read “Flow” and “Mindhacks”. First one is about the psychology of optimal experience.
- The brain loves discovery, challenge, narrative, self-expression, social framework, cognitive arousal, thrill, triumph, accomplishment.
- These things can get them into the flow state. This is where they do not notice the passing of time and things appear to pass directly into their brains.
- Another book “Don’t make me think”
- Brains can’t stand to have something left unresolved. They need to know the ending. This means that presenting something as a problem of two possibilities can get it involved.
- remember, ‘just in time’ learning is so much better than traditional ‘just in case’, since you end up forgetting it if you are not interested.
- People are tribal and like to get the ‘nod’ - being recognised by others in the group. We also like to discuss with other experts rather than newbies.
- So give users social things. Why not try ‘t-shirt first’ development.
Rails speaks C
Why would anyone want to do this?
- gots lots of C/C++ code (know anyone like that?).
- speed for some algorithms compared to Ruby (not sure I always agree)
- integration
Primary ways of extending Ruby for C.
- Has a basic C API. But you need to manage all the memory carefully.
- Ruby/DL quite an old library for which a rewrite is long overdue. Basically links in OS dynamic libraries. However there is a limit of 8 or 10 callbacks in total. Limits on C types.
- RubyInline. Lets you write C code inline with your Ruby. Uses gcc at runtime (!) to compile and then cache the code in memory to use it.
- SWIG. Will have seen it with subversion, as this is how sv provides support to so many different languages. Automatically generates Ruby (and other language) modules directly from some slightly annotated C code.
So how do these apply to Rails?
- BackgrounDrb. Basically a way of running background tasks decoupled from Rails, based on the Distributed Ruby library (DRb). Define worker classes and then make calls to it, (which are asynchronous with callbacks?).
- DHH commented that he wanted to get ActiveResource to do some of this stuff, including talking to other languages. He also thinks that for most needs people can just send XML between servers, only switching to proper Ruby object (via DRb) for big object.
High performance Rails applications - James Cox
Based on real-life experience of getting a site running that is receiving millions of hits per day.
Language performance race
- Joel Spolsky has been ranting against Ruby and Rails performance
- some truth in it, but then the development speed is so much improved
Best way to beat this is proper planning. Don’t expect to do it all by refactoring. Good planning is always better.
Sometimes the most important thing to do is make it seem faster, even if it isn’t. Quick responses to the user even if it is still doing something
Tips
- ActiveRecord tricks, mainly obvious SQL stuff, but sufficiently hidden by Rails that you need to explicitly tell Rails so that it then generates the correct SQL.
- Use CachedModel (which uses memcached as the back end)
- template optimiser. Some templates are actually quite slow, it depends on how they are built.
- publish once, caching always wins. Every time you edit it, publish it, then cache it. Don’t expect anyone to wait for a page to be rendered.
- don’t use cached_pages
Infrastructure tips
- don’t use shared hosting
- 2GB RAM minimum and dual core processor (for a small Rails app)
- If you think you will have more than a couple of hundred thousand hits per week then you will need more than one server.
-
- eight server gem
- 2 x proxy web/static servers (small, 1GB, single core)
- 4 x application servers (medium 2GB, dual core)
- 2 x database servers (big, 4GB, dual/quad core)
- this can handle around 10 million hits per week
- don’t forget load balancing
- mysql replication works well (master/slave)
MySQL
- Much prefer this after six years of using it
- Do not use this for things like session keys since it queues things and performance can be poor (use memcache instead)
- Use InnoDB instead of myISAM for greater survivability *
- some specific config tips
-
- query_cache=0
- key_buffer_size=100M (sole most important thing to do, make this huge)
- max_allowed_packet=1M
- log-slow-queries=/var/log/mysql_slow_queries
- if networked DB then
-
- wait_timeout=90
- net_write_timeout=180
- net_read_timeout=60
- max_connections=500
Other tips
- Use mongrel (app server) with nginx (proxy server)
- If you have just one machine then Apache with fcgi threads is best. Otherwise use mongrel.
- Ditch keepalive, unless you are using Ajax that specifically requires it.
- Don’t do any hostname lookup
- Turn off any unneeded logging, including access logs
- Put the stats code at the bottom after the style code. Browsers process the page simulataneously and the styles code take longer, so let it have it first.
- Use NFS for file sharing or MogileFS and FS Clusters
Ruby stuff at .tel - Eleanor and Romek
- Web stuff without Rails: bitstruct, pcap, camping, webrick, markaby
- Camping is a microframework written in Ruby. (4k big).
- Lovely tool called bistruct allows you to look at things at the IP level.
- Used bitstruct to define UDP. (50 lines of code)
- Then added pcap to some bistruct stuff to do a udpdump programme. (50 lines of code)
- Then want on to build a web based DNS-sniffing application
- Used webrick beacuse you can add code blocks into it. Showed their own, very short Ruby app that uses the WEbrick library to load a server. Then showed the server object being started with a code block and then a new servlet object that just inherits from the webrick servlet library, but with custom code blocks.
- That’s the basics, then you move onto a proper application server.
- This is like writing your own version of Rails. You created a request/response object, then for each path you register that object and the handler.
- Then decides that they should have done it in Rails, rather than rolling their own.
- However their management did not understand Rails and did not want it
- So then started to use camping as a microkernel to do the page serving. Very small though - one file per application. Creates each app in its own namespace and each database handle is within that namespace.
- Used Markaby, an xhtml domain specific language. So this means that it creates new ruby language elements that are analogous to xhtml entities.
- Romek pointed out that text interfaces are much simpler than all of this.
Relational Database Engineering and Rails - David A. Black
- David notes that he is not a DBA, but a developer.
- Rails has a basic mapping between HTPP verbs (REST) and CRUD using convention in controllers. More so with SimplyRestful (as discussed above).
- [big chunk of stating the obvious - waste of time by a slow thinker]
- Suggests that you think of everything in terms of CRUD. For example logging in is actually and authenticated way of Creating a session.
Integrating Ruby and Java - Ugo Cei - Sourcesense
How to include Ruby in Java code and vice versa. Or call one from the other.
Explained a Java web site he wrote oszone.org, uses cocoom, spring, lucene, hibernate and rome (https://rome.dev.java.net - an RSS feed lib). Could see how to replace some of these with Rails and other Ruby equivalents
Gave an example - wanted to write an XML validation class but the standard Ruby XML parser is not good enough, so used jruby to call the Java XML parser.
RubyJavaBridge (RJB).
- These are libraries typically written in C, using JNI to call the Java. Ruby then calls the C code.
- no mapping from Java iterators to Ruby loops
- no data type conversions
- no support for javabean properties
- works and is being maintained but not very pretty to use. Your Ruby code looks too much like Java
- great quote: “not very Rubish” - pronounced ‘roobish’
YAJB (Yet Another Java Bridge)
- looks much the same as RJB
- can also be used to write Java code inside arguments to Ruby methods.
- uses javassist
SWIG (mentioned previously)
- e.g. Jakarta POI, nifty library for manipulating OLE2 compound document objects (office files), written in Java (compiled with gcj) with SWIG providing the Ruby bindings.
JRuby
- full featured Ruby interpreter written in 100% Java (whole talk about this later).
- Gives Ruby instant access to all Java libraries - with a very Rubish syntax.
- Cannot load Ruby extensions written in C
- Mostly able to run Gems and Rails
- Not as fast as C Ruby but the developers think they will beat the C Ruby performance by the end of the year. I believe him.
- But could wrap the C extension with JNI.
- Supports iterators etc.
- Might be some naming conflicts, especially with core Java libraries. Use modules or remap names.
- Runs Rails and Camping.
- Has a JDBC ActiveRecord adapter. Works with almost all proper databases.
Remoting
- Could of course use XML-RPC, but remember the network is not transparent. For example cannot return a collection, just a vector of hash tables.
- Uses the Apache XML-RPC on the Java side - bit clumsy because of the collections issue.
- Then showed SOAP using XFire. Client looks almost reasonable but some weird added bits of code.
Rails core team panel discussion
Why/when did you get to Ruby?
- Struggling to learn Python until realised it was Python that was wrong not him.
- Spend a week and then decided never to touch PHP or Java again.
- Got sick of the whitespace in Python
Apart from the obvious cases (such as real-time) when would the panel advise against using Rails?
- Lots of projects, including many enterprise ones, that are doomed to fail, so don’t use Rails for them.
- When you are paid by the hour instead of results
Is the principle “optimise developer cycles over CPU cycles” an inviolable principle of Rails?
- There is someone working a lot on optimising Rails.
- Incredibly rare for speed to actually matter. Always a tradeoff, but they are very rare.
- But when it matters, bottlenecks must be removed, such as the recent rewrite of the routing code
What work would you like to see to get the focus on accessible Rails apps? (what?)
- SimplyHelpful could be used to help generate more accessible code.
- Screen readers such as Jaws are living a decade in the past as far as browser technology is concerned.
- It is the screen readers that need to change to support Ajax, not us to stop using it.
- Ajax and accessibility just do not mix.
- On a separate thread Rails should be far better at dealing with utf-8 than it is.
Will any HTTP authentication stuff (RFC2617) be built into Rails?
- No, it is best done as a plugin
- Authentication is so much wider than this
- HTTP authentication does not do anywhere near as much.
What about adding RSpec to Rails?
- People in the rspec community are already doing this.
- TestUnit is fine so far. Not entirely convinced by it.
- Rest of the answers were too boring to record
Keynote - Jim Weirich - Author of Rake
- Playing it safe - writing Ruby libraries so they don’t annoy people.
- Someone recently asked “are Ruby open classes a poor fit for large projects?”. Gave a simple example of a class that has a list in it and prints out the contents of the list, assuming they are all strings. Suppose someone then amended the printing method to raise an exception if the list is empty - how would anyone be able to see all the implications of this?
- Also “the chainsaw infanticide logger maneuver” was a rant posted some years ago. A developer spent three hours trying to fix problems with the Ruby logger class, only to find that one of the libraries he had installed had fundmentally changed the behaviour of it, including using :nodoc so that there was no documentation on this. He then trolled through a number of other projects and discovered lots of idiotic changes to the logger class.
- Great quote: “an agile language lets you do anything but also gives every other idiot on the planet the chance to stab you in the back with a rusty pitchfork”
- So, quite obviously, we need some rules (some DHH conventions perhaps?).
- He then played us a video showing a clip from World of Warcraft (an online game). Very amusing, showing a group of players planning a large attack, but then one of them, who was not listening to the plan, runs in and so loses the element of surprise and they all die. The motto “guard against Murphy not Machiavelli”.
Tips
- Use namespaces. He ran a grep on a set of GEMs and found 10 classes called Node, all but one were in namespaces.
- The namespace should be the name of the project, not a generic name. e.g. HTML::Node is wrong.
- Before creating a project look in Rubyforge, Ruby Application Archive, gems
- Avoid top level functions and constants. His own project, Rake, violates this terribly.
- Prefer adding behaviour rather than modifying behaviour
- And here is a convention -> if you need to add behaviour to someone else modules then prefix your method name with your prefix name, i.e. def myproject_mymethod.
- There are some exception. For example he adds an ‘ext’ method to the string class that gets the extension if it is a file name. But in this case he actually tests to see if someone else has added an ext class before he adds his and prints out a warning if not.
- When adding public methods ask first. The developer can then decide.
- One solution is selector namespaces, but Matz has promised this for Ruby 2. Basically you choose whose extensions to use and in what order.
If you need to let your code handle libraries with global constants that is in the process of transitioning then you can redefine the const_missing method in your own module to spot if the globals are missing and then give you private mapping to them
alias :my_const_missing :const_missing def const_missing (const_name) case const_name when const == :My_Global My_Module.application.const_warning(const_name) My_Module::My_Global else my_const_missing(const_name) #calls the original end end
Can also use the method missing, which can me even worse if done wrong.
Require hooks. This is a redefinition of require. But in this case you call the original require first and then catch any error, which then leads to you use your own code, and if that fails then you reraise the original error.
Strong view that you should design by contract. Eiffel actually lets you do this in the code, but Ruby doesn’t. A contract is:
- What must be true before a method is called - precondition
- What must be true after a method is called - postcondition
- So, for real sqrt precondition is n >= 0. postocondition (result*result - n).abs < 0.001.
- When you replace it then you must have the same or a ‘weaker’ precondition.
- And you must have the same or ’stronger’ precondition.
- Replaced behaviour must be ‘duck type’ compatible.
Keynote - Why the Lucky Stiff - Author of Camping, YAML API and Try Ruby sandbox
All presented through cartoons. Described his book (http://poignantguide.net/ruby/), which is a technical book based on cartoons. Too off the wall to take good notes.
Showed some tricks with the splat operator *.
ary.push *IO.read('list.txt'), which automatically reads the file by lines.
case food when *items devour_that food end
(Though Ruby will soon have an ‘in’ operator. ‘for food in items do‘)
If VALID is a list, including ranges then ‘case ch when *VALID’ will work, because when uses a === not a ==.
0.to_a will give you an array with just zero in it and a warning that default to_a is deprecated. However [*0] does the same thing without any warning.
And the following very Perlish code
if str =~ /REGEXP/ puts "#$1: #$2" end
can be:
m, *sub = *str.match /REGEXP/
m contains true if it matched and sub is the array of matches.
When you load/require a library it does not load into the namespace of the module, but globally. ‘Why’ has a solution, which is his Sandbox extension, load the library into the sandbox and then eval the code inside it. Then showed an example of how to do this to partition rails apps so that /thisone and /thatone each have their own sandbox. Compartmentalises the service and for the first time allows two rails apps in the same web root using the same web server. (BTW everyone it seems uses Mongrel as their production Ruby web server).
With Sandbox you can specify exactly what libraries the user is allowed to load. You can load different versions of the same library in different sandboxes.
How to turn your enterprise job into a Rails playground in three easy steps
- Bad: He works for a bank now. Only use proven stuff, very conservative, don’t take risks, overseas HQ so more people to convince. Very comfortable, even the developers.
- Good: However does have a boss that pushes for change and allows flexible working roles. Want everything done now.
- Ugly: J2EE hell. Class loading issues, huge XML files etc.
Showed some invented statistics of unhappy develpers (95%) and happy Rails developers (5%). It is your civic duty to introduce Rails into your workplace for the happiness of others.
Three step plan
- Lull management into a false sense of security
- Steal
- Cheat
Step one. At the time they were organising bi-weekly talks for the team. Idea was to get some more fun stuff into work. Used this as a platform to get started talking about Rails. Gave management the time to learn to trust him.
Then along came a small project, with the following characteristics:
- no existing database
- low business risk, the bank would not fail on it
- small team (including the business people)
- nobody watching (no outside project management)
Requirements were:
- a new bank product
- augment internet applications with it
- tie into other client server applications
- wanted it right now
So decided to move all this into an ActiveWebService SOAP object.
Step two. Told boss that he knew exactly what he was doing. However he had never written a single line of Ruby before. Also told boss that it would be at least seven times faster than Java.
Some hard bits:
- connect to schufa, which is a secure service with client certs etc
- had to use a third party C module
- no idea what the production environment should be
- had never done any of this before, ever
So told management how he was going to manage these risks
- hard stuff in rjb or if needed to switch back to Java then could use jruby
- just went for Apache 1.3 with fastcgi
Did not tell anyone else what he was doing unless they asked. The server teams never asked so they never know.
Step three: Stole developers by promising them a good time. Had three developers working on it before they were officially assigned to the project because they liked the idea.
They then developed it.
- Used mysql for it.
- The active webservice was simple.
- Then did lots of iterations so the users could work out what they wanted.
- Used XML builder to build XML very easily.
- Did the authentication with a Ruby wrapper around openssl (in around two lines of code)
- The external C module was not difficult either
- Used xconf.rb to build libraries and then used SWIG to connect it to the Ruby word.
- so in the end there was no hard stuff. Ruby just glued it all together.
- tooke five months for three main developers to do.
- Around 5,000 lines excluding the unit tests
Then came deployment
- Wrote a one-click installer for the server team to keep them happy.
- Used capistrano with a small tweak for Solaris
- Unfortunately the server team do not like one-click installers and were quite annoyed
- They went off and complained to the overseas über-architect
But then their boss stepped in and saved them:
- Main argument was that they were almost done.
- Also claimed ‘this is only a pilot’ (great trick that seems to be used in lots of cases to get Rails into production).
- Final argument was that this could all run on JRuby real soon now (not that they had actually tried it).
- Also offered to port it to Oracle
- Then showed how much easier it is to learn Ruby than Java, winning the skills argument
Just when they thought it was all over, bar the port to Oracle, the DBA entered the scene. He thought they wanted to disrespect his ‘precious’ Oracle, with funny practices like foreign key listeners. Unhappy with the migration plans because of the unchecked SQL scripts (this DBA wanted to check all SQL to see if it was good enough!)
Final thoughts
- Don’t try to push too many things at once (pick your battles)
- Try and stick to the best bits of what you have, don’t get carried away with changing things for the sake of it
- Respect your local release processes, someone else is going to be told off if it goes wrong not you
It went into production and there have not been any problems. The business was happy with the result. The bank is now looking into using it again for a second pilot. Rapid prototyping using streamlined is now gaining ground.
JRuby - Charles Nutter - Lead developer
In case you don’t know, Charles started working for Sun last week. So it is official.
Why Java?
- pervasive
- well tested
- highly performant
What do Rails devs get from JRuby?
- lots of libs
- JDBC
- Good EE stuff, clustering, failover, deployment etc (surely this is container dependent not hotspot)
- extensive remote monitoring
- a gateway to the enterprise
What do Java devs get from using Rails on JRuby?
- a usable web framework (because the rest are not)
- a useful schema management tool
- markup that doesn’t suck (JSP etc)
- Four extra days per week
- happiness
Then demonstrated the classic depot app (from the pickaxe book) on JRuby and it worked fine. They do think that their port is still a bit slow though. Showed it getting some stuff out of a session bean with automatic backend persistence (EJB stuff). One line of code sets up a manager object that has all the methods needed for the controller.
Also used JMX to manage it, with a J2SE Monitoring and Management Console service that could inspect various mbeans. (I’m not sure how this works without a container, is it just a case of loading JMX into your Java runtime?)
Next
- fix broken bits
-
- marshal-based session (like calling super)
- interpreter bugs
- performance
- script based java EE/Java library support. i.e. write the equivalents of scaffold for the Java EE stuff. But not just for Java, to do things like auto build the session bean stuff mentioned above.
- implement remaining C extensions, Mongrel, SSL
- continue expanding ActiveRecord-JDBC
-
- abstract out schema definition. JDBC does not provide the schema data to ActiveRecord that it needs to do its automagic on properties that match fields.
- solidify automatic CRUD support. Mainly just adding types like decimal
- more GUI tool support
As far as they are concerned, JRuby is not finished until it fully supports Rails. Java EE works so much better with Rails. Actually makes it fun!
Keynote - The Web is a Pipe and More - James Duncan Davidson
- In the early days of Rails they used Apache and FastCGI to deploy. But this was fairly sticky from a sysadmin point of view with processes and other things going wild in odd ways. His blog covers all the things he tried.
- Switched to Mongrel (http://mongrel.rubyforge.org) and noticed that it was so much easier to manage. For example you can telnet to it since it is plain http, but a fastcgi server uses a proprietary protocol. Used Apache with mod-rewrite to then push different urls to different rails apps.
- So what will we be using in ten years time? Can we do something now so that we can just switch things in as we need, not make a major binary change?
- Sticking mongrel into all apps as a library means that all of them can easily be exposed as a web service (well not quite - you have to write the code) over http.
- [Huge amounts of boring waffle - this man needs a sound thrashing even if he did invent servlets and other good things]
- Mentioned the new google oss project hosting, it has a customised subversion that stores all the data in a google big table. See http://www.infoq.com/news/Reviews-Mixed-on-Google-Hosting
Keynote - Dave Thomas - Author of the pickaxe book
He showed us his new Rails logo, two fingers sticking up.
The FUD fightback against Rails has started.
- It is not a case of Ruby not being ready for the Enterprise, it is the Enterprise that is not ready for Rails.
- What happens if DHH goes mad. Too late for that. Anyway Rails is far more than one person.
Lots of stuff about why not to let the FUD get to us, starting with an analysis of the psychology of 9/11. All very rabble rousing. Standing ovation. Not worth writing down.


November 24th, 2006 at 10:54 am
Reading your notes I was struck by how much more coherent they were than our actual presentation. I think you may have been the only person there who actually understood a word of it :)