[rspec-users] Nosy controller specs

Pat Maddox pergesu at gmail.com
Thu Dec 11 18:15:57 EST 2008

"Andrew Premdas" <apremdas at gmail.com> writes:

> 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

You do.... find(:all), find(id) and new(attributes)

> 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

Oh.  I'm a software libertarian.  Arguments for locking stuff down are
NEVER going to fly with me.

Look, Ruby is a very powerful language.  As Spiderman teaches us, with
great power comes great responsibility.  Just because stuff can get
messy doesn't mean we need to lock down the language or framework.  It
means we need to be good developers, inventing useful conventions and

Do you know the secret to having a clean controller?  Don't write one!
Use something like make_resourceful.

> 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.

Well, yeah.  You're asking for a different thing now.  You need to
verify that somehow.  Either you use mock objects to expect a different
method call, or you write an expectation that you should see one product
and not another.

> 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.

If you really, really want that, why not just change Product.find(:all)
to return something different?  Same thing.  I don't like it, but same
thing :)

I think you're overlooking the fact that all of this stuff must occur in
context.  As in "show me all the products" is a straightforward
statement, yes, but is missing some info.  As you yourself have stated,
"all" can mean something different than "every single record which
exists in our system."  The clearest way to represent these contextual
differences, in my experience, is to create an intention-revealing
method and use that.


More information about the rspec-users mailing list