[rspec-users] Depot app, Demeter's law and troubles cleanly specing

BJ Clark bj at aboutus.org
Sun Apr 19 17:04:18 EDT 2009


The way I go about this is, IMO, pretty straight forward. I cringe  
when people start talking about generating html in models, since I  
think separation of concerns is much more important than law of  
demeter, and I think that the model most definitely shouldn't be  
concerned with how it needs to be displayed.

In your original example you have:
@order.items.each do |item|
  item.product.title
end

The way I would do this is:
@order.items.each do |item|
render :partial => "product/line_item", :locals => {:product =>  
item.product}
end

In other words, I might have the following partials:
product/_line_item
product/_product (full representation of product probably for detail  
page)
product/_search_item (for display in a search result)

etc.

All the partials simply take a product object. There is probably  
already some smart, intention revealing name, but I call them  
"nanoformats".
I'm not exactly an Academic, so I have no idea the validity of my  
approach, but this seems to get around the law of demeter enough for  
me (thought, obviously not totally since order still *technically*  
knows about order.items.products). Order doesn't actually know  
anything about products or it's internals, except that it has some.  
The partial could be reused in other places, and with semantic markup,  
can be displayed in very different ways with a little CSS. A change to  
Product only necessitates changes to the app/views/products/* files.  
Your Orders don't need to know anything, item probably doesn't even  
need to be updated. the partials can be spec'd independently of  
wherever they are being used.

Your view and your models are always going to be tightly coupled, and  
a change in your domain object should probably necessitate a change in  
your views. That's the way it *should* work. However, your views  
shouldn't be tightly coupled with each other but they will have to be  
coupled in some way or another.

-----
BJ Clark



On Apr 19, 2009, at 12:37 PM, Fernando Perez wrote:

>
>>   http://spin.atomicobject.com/2008/01/27/the-exceptional-presenter
> Interesting idea too. So basically I need to totally rethink and
> refactor the way my views display the information to the customer:
>
> Let's see how I currently display or not an add to cart button  
> depending
> whether or not the product is free.
>
> My very first quick and very ugly procedural hard to spec solution was
> to do in the view:
>
> <%- if @product.price >= 0 -%>
>  <%= display_button %>
> <%- else -%>
>  This product is free!
> <%- end -%>
>
> Then my second solution was to create an instance method so that the
> view doesn't know about the Product internal mechanism about it's
> freeness:
>
> <%- if @product.free? -%>
> This product is free!
> <%- else ... -%>
>
> Yeah I thought I was an OOP master and Demeter could rest in peace!
>
> But thinking about the GOF Builder and Exceptional Presenter design
> patterns you talk about, that would mean that the html output for a
> Product should therefore happen in the Model itself. And then in the
> show.html.erb, I simply call:
> <%= @product.display -%>
>
> and all the magic about whether or not the product is free and to
> display the button has already been handled inside the model (or  
> another
> related place) when it gets instantiated. Same applies to
> item.product.title, that would be handled elsewhere than in the view.
>
> However it might clutter the Model, so actually there is more to MVC:
> each Model should have a sub class or something that handles how the
> model instance will be presented to the view.
>
> How do you handle such issue? Are there some open source rails apps  
> that
> I could learn from?
> -- 
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users



More information about the rspec-users mailing list