View_rubbish

Developing components considered bad form in Rails

20 Nov 2008 at 8:01pm 6

On a typical modern website, most pages are dynamically generated from various database tables.  There is normally the main content area which contains content such as the latest news stories.  Then there are usually various boxes in a side bar such as the latest pictures from the galleries which contains the latest content in various other tables.

In a modern Model-View-Controller based website the View layer gets it's content to display via the Controller which in turn gets it from the Model layer.  This separation of concerns helps to keep things nice and clean.  For example, the controller gets a request for the homepage so it runs the appropriate action (a piece of code to handle a specific request within a controller).  The action then asks for the latest news stories from the model layer and passes them through to the view layer to be displayed in the layout.

The question comes to how does this work for the side bar content such as the latest pictures.

Symfony


In Symfony this is done through components.  A component is effectively
a lightweight action (one portion of a controller) with it's own view. 
So the main layout template of the site will have an area for each
specific page to include it's own content and then a number of specific
areas, one for each component.  When the view layer is rendering
itself, it encounters the component portion and makes a request to the
controller layer to run the component, have the component render it's
view and return the content ready for displaying in the overall site
template view.


There is a simpler way of getting content in to a template called
partials.  Partials are very simply a small snippet of PHP/HTML that
are executed within the view layer without being able to call back up
to the controller layer.  So, the difference between a partial and a
component is that the partial can only access variables that the view
has access to and a component has it's own set of instance variables
created by the component code that don't share a "namespace" with the
instance variables created by the requested page's action code.


Rails


Rails had components introduced in Rails 0.10.0, but they were never
really used (as opposed to Symfony where their use is commonplace).  In
2006 they were pretty much announced as deprecated, including by the
meister of Rails DHH.  The
reason given for their deprecation was that they were never considered
good style, so were a bit of a ill-considered addition to Rails.


The Rails recommended way of achieving the same goal (according to a
few Rails developers I've talked to) is to have "before filters" run at
the Application Controller (the daddy of all Controllers) level that
sets instance variables and then have the application layout include
partials, passing in those instance variables.


Thoughts


I know there are supposed to be performance problems with instantiating
another controller layer from within the view.  And I know it's
technically cleaner for the view layer not to call upwards, the view
should only be called by the controller not vice versa.  However, I
can't help feel that this is throwing out the baby with the bath
water.  I like the fact that the code for the component is encapsulated
in one place rather than mucking up my application controller.  I like
that the instance variables for my component don't clutter up my
"global" variable namespace (e.g. if there was a latest news stories
component on every page and I'm viewing the list on the homepage, I'd
like to use @latest_stories or something similar in both cases but I
can't if they have different numbers of records/sort order/etc).


For now, I'm doing things in the best way I can and following Rails
conventions.  However, maybe I could do things cleaner by moving the
component filters out in to a separate components module, have the
instance variables prefixed with component_ and then include the module
in my application controller - so at least it doesn't look as dirty.


I can't be the first one to encounter this, surely?  How do you guys
cope with components and the like in Rails?  Help me in the comments...

Other articles you may like:

6 Comments so far

Rob Young

Rob Young wrote on 20 November 2008 at 20:46

I have to agree, I prefer the Symfony way of doing it. It feels much cleaner to have small, self contained components that combine everything required for a page component rather than having it spread across the application.

Kyle

Kyle wrote on 20 November 2008 at 21:20

Rails components performance was abysmal, back in the day. This might have something to do with the deprecation. I still practice component-oriented development, but use a helper function to contain the "component". Heavy models, Heavy helpers, very light controllers.

stephen

stephen wrote on 21 November 2008 at 03:16

you might want to look at cells plugin..

here's their page:
http://cells.rubyforge.org/

and pointing you to an interesting article about it so you could try it:
http://mikepence.wordpress.com/2008/03/16/cells-bring-clean-re-use-to-your-rails-views/

Andy Jeffries

Andy Jeffries wrote on 21 November 2008 at 08:55

@Kyle: I've never been sure on the whole heavy helpers part. Since starting using Rails I've been trying to do things the Rails way (as I said in a previous article - http://andyjeffries.co.uk/articles/rebuilding-a-site-from-symfony-to-rails - Rails helps you become a better developer, I'm sure of that). That obviously mean fat/heavy models, skinny/light controllers. But putting too much in a helper makes me a wonder if I'm breaking some unwritten style rule (like having too much HTML in a helper)

@Stephen: I'm reading this article now - very interesting, thanks a lot for the link. I'd heard of Engines (which is of interest as Symfony plugins can effectively act like a Rails Engine would) but not Cells.

Amir Abiri

Amir Abiri wrote on 21 November 2008 at 19:51

I agree. (with the rails way).

On of the fallacies of components is that the controller logic, which in turn does most of the use of the model layer, is fragmented across many different seemingly unrelated objects.

However this often leads to unoptimized code, as there is no unified perspective between these different bits of code. May I remind you some of the websites the you and I are familiar with, who have reached 200 and even 300 queries on the homepage. Most of this was the fault of components.

I still think components have their place, but I agree with the principle that the controller layer must collaborate with itself better.

(How big of a party are you gonna throw on monday about me saying I agree with Rails?)

Pam Lingao

Pam Lingao wrote on 25 May 2011 at 17:46

[url=http://www.keylessproperty.com/]keyless locks[/url] are the easiest way to be able to acquire virtually any entrance door. Standard head of hair which amenable having a key experience induced many people protection issues. The robber been trained in buying these individuals could easily purpose stability breaking aided by the perfect products. For this reason, keyless entrance door tresses really are remarkably preferred. You will discover several types that can be handled without using an important. These people involve biometric, touch pad and even remote controlled head of hair. Choosing which unfortunately securer is best for you will be determined by your personal secureness must have.

Click here to have your say...


You can use <b>+</b>, <i>+</i> and <blockquote>+</blockquote>