Pat,
Thanks for reply. The one year ago thing was a really bad example. Using
your terminilogy it looks like a rule that changes what my app does.
But I
was talking about a change in what the app is; i.e. a business rule.
I definitely don’t want to have business rules in controllers. From my
viewpoint in MVC the controller is a conduit that allows the business
domain
encapsulated by the model to be presented in views and in reverse allows
interaction with views to communicate with the model. In Rails though
its
very easy for the business domain to creep into the controller. I’m
beggining to think that Rails got this wrong. Perhaps it should have
specified a restrictive api between the model and the controller, I’ve
been
thinking of something like
get_collection
get_object
get_new_object
By giving completely open access to anything in the model including all
classes its real easy for controllers to get real messy. I think the
emergence of Presenters as well as skinny controllers is symptomatic of
that
problem
With a resource based approach the controller really should only be
requesting resources or more accurately representations of resources. It
shouldn’t be creating/specifying representations of resources. That is
outside the responsibility of a controller. Again using your terminology
REST restricts what an application does by using a standard set of verbs
to
do things. Now in Rails we can pollute this by putting all sorts of
stuff in
our restful methods, but really we shouldn’t. Instead we should use the
expressivness of what ‘is’ to get our functionality. If we do this then
our
controllers can be ultra skinny and our controller specs should be much
less
brittle. To change what our app ‘does’ we then add new routes,
controllers
and views to show a different representation from our model but still
using
our standard verbs.
If controllers only use the restrictive api I’ve suggested and we
combine
this with a ‘presenter’ layer (when required) on top of our model. then
controller specs really can be very straightforward and focus on their
key
responsibilities which are getting something and controlling i.e.
routes.
I’ll try and give a better example. In my business domain I have
products
and some of these products have refills which are also products.
Generally
when I want to look at all products I don’t want to see the refills.
This is
because the refills are bought and specified through their product. So
using
tags when I want to find ‘all’ products I’ll actually do the following
bizzarre thing
Product.find_tagged_with(‘refill’, :exclude => ‘refill’)
Now generally in Rails this will be done in my controllers index method,
and
with rspecs scaffold code we’d mock Product and test that this method
was
called the correct way. So as my call has changed from
Product.find(:all) to
this new call I have to change my controller spec. Now changing what all
products means has nothing to do with controllers and everything to do
with
models. What my controller should have done is called
Product.get_collection. Then when I change my definition of what
get_collection does then yes I have to update my model spec, but that
makes
sense, and my controller and its specs remain the same.
I don’t see controller specs as being fixed, but I do think they should
only
need to change when something a controller is responsible for changes.
Generally this is routing - controlling where we go - which is
fundamentally
how web applications do things.
Anyhow hope that makes sense and once again thanks for the input much
appreciated
Andrew
2008/12/11 Pat M. [email protected]