Oomoo

September 17, 2008

The “V” in MVC

Filed under: ajax, forms, IDE, MVC, rails, view — oomoo @ 8:42 pm

Probably one of the hardest adjustments to make when transitioning from Desktop forms development to browser-based is the endless number of code and template files that must be created and maintained just to have one working “form” (that you will now be calling a “page”). 

With a traditional desktop form, it usually isn’t hard to get your arms around all of the “players” involved in making your form work.  You may have many “layers/tiers”, but most of the pieces are probably written in the same language using the same IDE.  This is not the case when designing web pages/forms where the content for each page is spread across several files (at a minimum) each of which are probably using very different development languages and/or markup styles.  

Why have all of these “pieces” of code and/or markup all over the place?

  1. MVC (Model View Controller)
    The MVC architecture dictates separation between your data/business logic (model), your application code (controller), and the web page presented to the user (view). The “View” in “MVC” really means “a combination of all the pieces needed to create a finished page/form”. 
  2. DRY (Don’t Repeat Yourself)
    DRY is one tenet of Rails development.  It basically says “if you are copying/pasting the same code/markup into multiple files, that code/markup should be put into it’s own file which should just be pulled into the pages that need it at run-time.”  Yes, that is my own paraphrase 🙂
  3. WWW = Best Of Breed
    Web development has accelerated the pace at which tools and technologies are evolving.  We web developers love to complain about all the “disconnectedness” that exists in web-based apps, but we would really scream if some new technology came out and we had to wait a year for some company to boil out the impurities and then bloat it up so it could be “assimilated” before we could work with it (wait, I know that company…).  HTML, CSS, and JavaScript are poster-child technologies for “survival of the fittest” or should I say “survival of the most flexible but yet most simple”… nah, doesn’t have the same ring to it.

So, with just these three demands placed on us as a pre-requisite for developing a web form, it’s no wonder that we end up with so many disparate technologies and pieces all needing to converge without errors inside multiple versions of non-standard browser implementations across multiple operating systems.  Oh man, my stomach just knotted up right there… okay, Ruby and Rails to the rescue!

 

Anatomy Of A View

The following “pieces” are used to produce a single web page/form:

HTML (ERB)

The main part of a web page or “form”.  It resides in \app\views\modelname\myview.html.erb.  Many people consider this the “view”, but it is only one component of the view.  This one file actually contains many types of coding/markup/templating.

  • HTML – text, tags, tables, etc.
  • ERB – in-line Ruby including object/variable references, custom method calls, helper method calls, etc.
  • CSS – in-line style settings override external CSS stylesheet settings.
  • JavaScript – in-line JSP method calls  (can also contain JavaScript methods).
  • Images – icons, pictures, borders, backgrounds, etc. located in \public\images\
  • Flash – or Silverlight, or some other 3rd party client control.

CSS

Your cascading stylesheet(s) which control most of the presentation properties of your page/form.  You will almost always have at least one of these for each application.  It is very likely that you will have several.

  • CSS stylesheets are stored in \public\stylesheets\.
  • Which stylesheet to use is usually established in either an application-level or a controller-level Layout file like this:  
    <%= stylesheet_link_tag ‘mystyle’ %>

 

JavaScript

Your JavaScript classes/functions and 3rd party tools like Scriptaculous, Prototype, and JQuery.   Your application will usually use at least 3 JSP libraries.   Large AJAX-driven client applications can have…lots of them!

  • JavaScript code files are stored in \public\javascripts\.
  • Usually, the Layout file will include:
    <%= javascript_include_tag :defaults, :cache => true %>
    which will include the 5 most commonly used javascript libraries (including Scriptaculous and Prototype).
  • You can also specify
    <%= javascript_include_tag :all, :cache => true %>
    which will automatically include EVERY javascript file found in \public\javascripts\
  • You can also specify
    <%= javascript_include_tag ‘prototype’, ‘effects’, ‘controls’, :cache => true %>
    to control which libraries load or the order in which they are loaded.

 

Helper(s)

Helpers blur the line between a Controller and a View.  As Dave Thomas so brilliantly put it, “A helper is simply a module containing methods that assist a view.  Helper methods are output-centric.  They exist to generate HTML (or XML, or JavaScript)-a helper extends the behavior of a template.”

  • Helpers are stored in \app\controllers\helpers\ 
  • Controller-specific Helpers are named after their Controller with “_helper.rb” appended to the end.
  • The Application-wide Helper is \app\controllers\helpers\application_helper.rb

Layout(s)

A layout is kind of like an HTML/ERB fragment or snippet that gets pulled into your page template at run-time and is usually used to show data/text on the page this is generic across all views/pages for the Controller (like headers, footers, borders, etc.).   

  • All layouts are stored in \app\views\layouts\
    (defined by the constant TEMPLATE_ROOT)
  • Controller-specific layouts are named after their Controller.
  • The application-wide Layout named “application.html.erb”
  • The application-wide layout can be specified in \app\controllers\application.rb
  • Each Controller can override the application-level layout by setting the “layout” property or by passing
    :layout => ‘layouts/mylayout’
    directly in the render( ) method call.
  • You can suppress the use of any Layout by including
    :layout => false
    in the render( ) method call.

Partial

Partials are very much like Controller-level Layouts because they are HTML/ERB fragments that get pulled into your page and rendered at run-time.  The big difference is that Partials are typically used to display repetitive formatted information (like a grid with rows of records) using a code block (DO…END block).

Partials must be manually called for in your HTML/ERB file like this:
<%= render :partial => "clientlist", :locals => { :f => @f, :label_text => "Update"} %>

This will render the partial _clientlist and pass it the local variables (from the Controller) and the set the variable “label_text” to the value "Update"

Rails 2.0 introduced the ability for a Partial to have it’s own Layout.  Yes, it does seem a bit like nesting, but it is nice to have!  Now, we can do something like this in our HTML/ERB file:
<%= render :partial => "header", :Layout => ‘boxed’ :locals => { :post => @post} %>
which will pull in the Layout _boxed.html.erb, which will then pull in the Partial _header.html.erb.

  • Partials are usually used on a “per View basis” and are stored in \app\views\myview\
  • Partials are named beginning with an underscore (i.e.  _mypartial.html.erb)
  • Partial Layouts are stored in the same folder as the Partial and also begin with an underscore.
  • You can re-use a Partial Layout across your application if you store it in
    \app\views\application\

    Then, when calling the partial, just use 
    :layout => ‘layouts\mylayout’

RJS

RJS templates also blur the line between the Controller and the View.  They have access to all of the Controller objects/variables, but they also have an object reference to the current HTML “page” that is in the browser.  RJS templates allow you to infuse JavaScript into your views that is written using Rails “helper methods” (instead of actual JavaScript).  Separate RJS template files are not required (you can accomplish most of the same things with “render updates” directly in your Controller code). 

  • RSJ template files are stored in \app\views\myview
  • RJS templates are named for the Controller “Action” from which they are called with a “js.rjs” extension.
  • RJS templates are not actually “called”, if one exists, it is simply applied when the view is rendered.
  • Make sure you don’t try to name an RJS template the same thing as the View, otherwise the View gets rendered, not the RJS.

 

 

So…

I just showed you how you could easily have 7 or more separate files using 5 or more different technologies included in the 1 page you are trying to display to the user.  Hopefully, knowing is half the battle and at least the reasons “why” make a little more sense to you now.  I also gave you a fairly concise list of the places where the creation/display of a Ruby On Rails “View” can go wrong.  Using Ruby On Rails can sometimes seem like magic, and that is part of the fun.  But, you at least need to know that there “is” someone behind the curtain and try to get as familiar as you can with the plumbing because one day it will back up!

 

How To Debug

Debugging an application with hundreds of files and so many combined technologies is no small feat.  The first step is to remember that all of these “pieces” eventually get smashed back together into the HTML displayed in the browser!  So, you can view the source of the page in the browser (Using the IE Developer Toolbar in Internet Explorer, or even better, using the Firebug plugin for FireFox).

Use a full-blown IDE with a built-in debugger (like Aptana with RadRails, Steel Sapphire, Komodo, etc.)

Use the Logs!  Look at your log files, and don’t forget that you can pepper any problem code with manual log entries.

Use the IRB!  The interactive Ruby console will allow you to spy on your objects and variables as well as manipulate them in real-time.  Yes, it’s command-line Alice.

Use some of the great tools and techniques laid out in this post: Rails Guide – Debugging

 

*This post uses Rails 2.1 and Ruby 1.8.

Advertisements

1 Comment »

  1. Thanks for another very useful post.

    Particularly like the comments on “Best of Breed” which is an angle I had not considered much.

    Also re Helpers I find it is often hard to know whether they are required or just include a bit more code in the View so that is good guidance.

    Comment by Norman — September 19, 2008 @ 3:30 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: