There's A Preferred Way To Do It - But Go Ahead If You Need To
I finally got around to watching DHH's keynote address at RailsConf 2006. It's good to listen to it while flipping
the slide deck.
David made a good point about Ruby's and Rail's opinionated nature. While they are opinionated, they aren't draconian; they allow for flexibility outside of convention if that's what you need.
The example he gives is Ruby's ability to call private methods externally. By convention you can't break that encapsulation and Ruby's nature is to discourage it and push you to do the right thing. BUT if you feel for some reason you absolutely must - perhaps you are doing some meta-programming or reflection - Ruby makes it possible and easy to do. The responsibility is ultimately left to the developer.
The new ActiveResource will be provide way of building APIs and mapping models, represented as Structs, to RESTful services much like ActiveRecord does with models and CRUD operations. A slick approach, providing a proxy to the REST service - simpler than a .NET generated proxy from a WSDL on top of SOAP and it's all done at runtime. Even nicer, both ActiveRecord and ActiveModel will descend from ActiveModel, enabling you to create subclasses for things like ActiveLDAP, ActiveSOAP and ActiveFileSystem, etc. and reuse the shared concerns such as model validations. He hasn't quite thought through associations between resources and database models. ActiveResource will be available as a separate gem.
DHH is truly a master of abstraction.
My favorite quote:
"Doing things by hand is another one of those constraints. If you have the initial assumption that things should be able to be done by hand without leaving you crying, it leads to better designs. And I think that is Ruby in general. At lot of Java people are crying "We need our IDEs!" Yeah, you do need your IDE in Java. You'd be insane to write Java without an IDE."
irb(main):003:0> class Foo
irb(main):005:1> def bar
irb(main):006:2> puts "baz"
irb(main):09:0> foo = Foo.new
NoMethodError: private method `bar' called for #<Foo:0x2c4acc0>