Abuse of method_missing?
Am I the only one who thinks the following DSL-ey trickery is an
abuse of method_missing
?
Here's the creation of some named routes.
ActionController::Routing::Routes.draw do |map|
map.home '', :controller => 'main', :action => 'start'
map.user_page 'users/:user', :controller => 'users', :action => 'show'
end
You call arbitrary methods on the map
object, and that
creates a route whose name is the method you called.
Here's the declaration of an ActiveRecord model's attributes using Hobo's new migration-generating style.
end
I haven't looked into the code, but I assume the block is
instance_eval
'ed
against some object whose method_missing
builds up attribute
meta-data where the name of the missing method becomes the attribute name.
Introducing new symbols into your system by invoking them as methods on bizarre (sometimes hidden) objects strikes me as a nearly useless twisting of Ruby's flexibility. If you're working with something that's purely DSL-ish, that's one thing, but if we're talking about a tiny little internal DSL embedded in otherwise idiomatic Ruby code, and, needless to say, being edited by Ruby developers, this just seems to introduce confusion.
Of the two uses, I actually prefer Hobo's because it goes farther
than Rails' away from idiomatic Ruby and towards a DSL. Since I
actually see that I'm sending messages to map
when
creating a named route, it frustrates me that this object exposes
its functionality through method_missing
, and I'm therefore
unable to look up the API reference in the
normal way. What is that thing?
Does it have any methods that might conflict with my route names?
We know about connect
. Hopefully that's the only one.[1]
Do you think this sort of use of method_missing
is
advisable? How have you used and abused it?
[1] Actually, a look at routing.rb shows that
ActionController::Routing::Routes.draw
yields
an ActionController::Routing::RouteSet::Mapper
, which also
(in the neighborhood of line 1000[2]) defines named_route
:
not a likely name conflict, but arguably a clearer way to define your
routes.
ActionController::Routing::Routes.draw do |map|
map.named_route :home, '', :controller => 'main', :action => 'start'
map.named_route :user_page, 'users/:user', :controller => 'users', :action => 'show'
end
[2] Yeah, line one-thousand. The Rails team are trained professionals: please don't try that at home.
No comments:
Post a Comment