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.

August 20, 2008

How Do I ‘Refresh’ Individual Form Fields?

Filed under: ajax, controller, forms, model, rails, view — oomoo @ 11:13 pm

Recently, I wrote about creating a Ruby on Rails app that would create HTML formatted signatures for Outlook and web-based e-mail systems  (see: Outlook and the Double-Spaced Signature ).  This small application was my first chance to do true data-based entry using form fields (most of my prior RoR projects just tapped into existing databases for searching and presentation in a browser).

Well, most of my software development background has focused primarily on creating data-based applications with heavy data-entry and reporting, so I was eager to see if Rails was up to the task.  I used the Scaffolding classes built into Rails 2.1x to initially generate the pages (see, I wanted to call them screens or forms) to do the CRUD work, then I set about understanding how they worked and editing them to look a little better.

I understand the whole “disconnected” “stateless” model of web development, but I never dreamed it would be this dang hard to put a drop-down box and a couple of text fields inside form tags on a page and get them to interact with my database and with each other.  Of course, now that I know how to do it, it seems simple (and Rails is great again, the web makes sense, and all is right with the world).  Of course, what I could have finished in VFP in about 60 seconds took me many frustrating hours with more than one Rails/Ajax book thrown across the room.

For this application, I only have 2 tables (told you it was simple); Locations and Signatures.  The “Locations” table is a lookup table containing information that will be related to multiple “Signatures” (usually one Signature per person).

Locations Table:Locations schema

Signatures Table:Signatures schema

 

 

 

 

 

 

 

 

 

Locations.id  — Relates to —>> Signatures.location_id

Since each Signature relates back to a Location, if the Company changes their logo or web site, no change to the Signature record is needed, you need only regenerate the HTML signature for Outlook.  Okay, enough “database theory 101”.

Here is what I wanted to accomplish:

captured_Image.png Display a page where the user could select their “Location” from a drop-down combo field…

 

 

 

…once selected, the data from the “Location” phone/fax fields would automatically populate the first two phone fields of the “Signature” record. SigAfterLocation

…the phone fields would temporarily “highlight” to indicate to the user that something had changed

…then the fields would go back to their normal color, still containing the updated data from the Location record.

captured_Image.png[4]

 

 

 

 

Finally, the user “Saves” their Signature, and clicks the “Create My Signature” link which generates/downloads the HTML file containing their nicely formatted Outlook Signature.

captured_Image.png[6]

 

Piece-O-Cake!!!  No really, I wrote a complete version of this page using my desktop development tool (VFP) and it took me almost no time to have all the logic working and I even had a browser preview of the finished HTML that updated itself as you updated your signature.   Here is a screenshot of my desktop form written in VFP…

captured_Image.png[29]

 

We need our page to contain:

  • A Form (form_for)
  • A Drop-Down List (collection_select)
  • Some Labels (form.label)
  • Some Fields (form.field)
  • A Submit Button (form.submit)
  • Some way to know when a selection has been made from the drop-down list
  • Some way of updating the page based on the drop-down selection

 

    <% form_for @signature do |f| %>
    <div id="cbo_location_id", style="height: 31px">
        <%= f.label :choose_location, "Choose Your Location:", 
                    :style => "top: 5px; left: 3px; position: relative; color: white; font-weight: bolder;" %>

        <%= collection_select("signature", "location_id", @locations, "id", "loc_name", 
                              options ={:prompt => "...Select A Location", 
                              :include_blank => false}, 
                              html_options={:style => "top: 7px; left: 15px; position: relative;"}) %>
                              
        <%= observe_field("signature_location_id", 
                          :url => { :action => "location_lookup" }, 
                          :with => "'id=' + value") %>
    </div>
    
    ...other form fields here...

        <table width="350" height="150" cellpadding="0" cellspacing="0">
           <tbody> <tr> <th align="center"> <%= f.label :phone_desc, "Desc.", :style => "color: white;" %> </th>
                        <th align="center"> <%= f.label :phone_num, "Number", :style => "color: white;" %> </th></tr>
                   <tr> <td align="center"> <%= f.text_field :sig_p1_desc, :size => "10", :style => "" %>  </td>
                        <td align="center"> <%= f.text_field :sig_p1_num, :size => "20", :style => "" %>   </td></tr>
                   <tr> <td align="center"> <%= f.text_field :sig_p2_desc, :size => "10", :style => "" %>  </td>
                        <td align="center"> <%= f.text_field :sig_p2_num, :size => "20", :style => "" %>   </td></tr>
                   <tr> <td align="center"> <%= f.text_field :sig_p3_desc, :size => "10", :style => "" %>  </td>
                        <td align="center"> <%= f.text_field :sig_p3_num, :size => "20", :style => "" %>   </td></tr>
                   <tr> <td align="center"> <%= f.text_field :sig_p4_desc, :size => "10", :style => "" %>  </td>
                        <td align="center"> <%= f.text_field :sig_p4_num, :size => "20", :style => "" %>   </td></tr>
             </tbody>
          </table>

    <div style="height: 35px"> <p> <%= f.submit "&nbsp;Save&nbsp;" %>  </p>  </div>
  <% end %>

 

We need our form to:

  • Know that a selection has been made from the drop-down list:

       ( \app\views\signatures\edit.html.erb )

    <%= observe_field("signature_location_id",                           
                       :url => { :action => "location_lookup" },
                       :with => "'id=' + value") %>
  • Retrieve the chosen “Location” data:

      ( \app\controllers\signatures_controller.rb )

    class SignaturesController < ApplicationController
    
      def location_lookup
        @location = Location.find(params[:id])
      end
      ...other controller methods...
    end
  • Update/refresh the fields on the page that have changed, and highlight them: 
      ( \app\views\signatures\location_lookup.js.rjs )

    page[:signature_sig_p1_desc].value = 'p.' page[:signature_sig_p1_num].value = @location.loc_phone.strip page[:signature_sig_p2_desc].value = 'f.' page[:signature_sig_p2_num].value = @location.loc_fax.strip page.visual_effect :highlight, :signature_sig_p1_desc, :duration => 2 page.visual_effect :highlight, :signature_sig_p1_num, :duration => 2 page.visual_effect :highlight, :signature_sig_p2_desc, :duration => 2 page.visual_effect :highlight, :signature_sig_p2_num, :duration => 2

 

So, what is happening here?

  1. My drop-down list is:

        <%= collection_select…  %>
  2. When it’s value is changed, my “field observer” gets fired:

       <%= observe_field…  %>
  3. It’s "action" is defined as:

        :url => { :action => "location_lookup" }  
    which means it is going to call the controller action/method named "location_lookup"
  4. As a parameter, it is going to pass the "id" of the Location chosen:

       :with => "’id=’ + value"
  5. The "location_lookup" action/method in the controller "finds" the passed in Location ID:

       @location = Location.find(params[:id])
  6. Then (by magic) rails renders the contents of the RJS file.

    Actually, Rails will always look for an RJS file to exist that is named the same as the controller action/method.
  7. The RJS file will first update the field values with the contents of the Location data:

        page[:signature_sig_p1_num].value = @location.loc_phone
  8. Then, the RJS file will temporarily "highlight" the changed fields:

       page.visual_effect :highlight, :signature_sig_p1_num, :duration => 2

 

*Note – we didn’t need to use an RJS file, we could have achieved the same thing by putting the RJS code directly in the "location_lookup" controller action/method:

def location_lookup
  @location = Location.find(params[:id])

  render :update do |page|
    page[:signature_sig_p1_desc].value = 'p.'
    page[:signature_sig_p1_num].value = @location.loc_phone.strip
    page[:signature_sig_p2_desc].value = 'f.'
    page[:signature_sig_p2_num].value = @location.loc_fax.strip

    page.visual_effect :highlight, :signature_sig_p1_desc, :duration => 2
    page.visual_effect :highlight, :signature_sig_p1_num, :duration => 2
    page.visual_effect :highlight, :signature_sig_p2_desc, :duration => 2
    page.visual_effect :highlight, :signature_sig_p2_num, :duration => 2    
  end 
end

I just prefer to use the RJS file to keep my controller clean of view-specific things, and if you just think that the RJS is taking the place of the View (html.erb) that would normally be rendered after a controller action/method, then it makes sense.

*Note: "page" is an automatic reference to the existing web page object (DOM) that Rails is exposing so we can monkey around with it.  Now, isn’t that nice!

Since RJS is basically just "Railsified" javascript (AJAX), you can do just about anything to the existing web page.  You can add things, hide things, change all the colors, change the words, enable/disable things, and even insert calls to new javascript functions (like links to services on other web sites).

 

In review, the process involved really isn’t that different from what I had to code in my desktop VFP application.  The biggest difference was knowing what form elements to use (and their syntax) then just understanding that the full logic is done in pieces that are spread out over several files (view, controller, RJS).  In the end, the secret sauce for updating my field display is AJAX, simplified by the Rails helpers.

Happy Field Refreshing!!  –Oomoo

 

—UPDATE ––

Do you want to DEMO this application in your browser right now?

Just go here:  Outlook Signature Application

This web-based application is a full-featured signature generator for Outlook.  You can use it to create your signature or just use it as an educational tool.  This application was completely written at (and is hosted on) Heroku!!

(hint:  If you enter your “Location” and “Signature” information, be sure to delete it before leaving the site)

In fact, you can download the full source code here:  Download Source Code

March 11, 2008

MVC Simple Sample

Filed under: controller, model, MVC, view — oomoo @ 12:45 pm

Assumptions: 

    – MySQL Database named “mydata_development” 
    – Table named my_orders 
     
     

Point YML to correct Database: 

    – File Location:  \config\database.yml 
    development:
      adapter: mysql
      database: mydata_development
      username: root
      password:
      host: localhost 
     
     

Model for Table “my_orders”: 

    – File Location:  \app\models\my_order.rb 
    class MyOrder < Activerecord::Base 
    end 
     
     

Controller: 

    – File Location:  \app\controllers\admin\myorders_controller.rb 
    class MyordersController < ApplicationController
      #scaffold :MyOrder – uncomment to have a full on-the-fly web CRUD scaffold.
     
      def index
        @myorder = MyOrder.find :first
      end
     
      def new
        @myorder = MyOrder.new 
        @myorder.ordPK = 3
        @myorder.ordCustPONum =
      end
    end 
     
     

View: 

    – File Location:  \app\views\myorders\index.rhtml 
    <h1>MyOrder#index</h1>
    <p>Find me in app/views/myorders/index.html.erb</p> 
    <%= @myorder.ordPK %>
    <%= @myorder.ordCustPONum %> 
     

To Run: 

March 6, 2008

A View In Pieces

Filed under: rails, view — oomoo @ 12:05 am

“A View is used to render a particular action of a controller in the browser.”

A “View” can be split into components: a layout, a view, and a partial depending on the complexity of a page.

Layout

The layout is a page template which will be used to render several views. Thus, it is reusable.

It contains some elements such as HTML header and footer, menus, design elements, etc. that you want to be the same across several views.

Layouts are stored in /app/views/layouts/

View

The view is used to render a particular action of our controller in the browser (like index, list, show_detail, edit, etc.).  Views are stored in:
/app/views/<name_of_model>/<name_of_view>.html.erb

Examples:
/app/views/customer/index.html.erb
/app/views/customer/list.html.erb
/app/views/customer/edit.html.erb

Partial
A partial is used to render only a part of a page. It gives you an easy way to generate a common piece of rails code/html over and over, for example, iterating through a list of orders for a customer. In Ruby terms, it is much like a Ruby “block”.  It can be really useful when working with Ajax. (for example, refreshing a a table of items without refreshing an entire page).
Partial filenames always begin with an underscore

Partials are stored in
/app/views/<name_of_model>/_<name_of_partial>.rhtml.erb
/app/views/customer/_customer_list.html.erb
 

Index
If you name your initial view page “index.html.erb”, you do not need to specify it’s name in the browser.

For example, if your view is: \app\views\orders\index.html.erb
browse to http://localhost:3000/orders will display the index page.

If you use some other view filename, you just need to specify that view name in the address.
For example, if your view is: \app\views\orders\list.html.erb
browse to http://localhost:3000/orders/list to display the page

Simple View Example

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” http://www.w3.org/TR/html4/strict.dtd“>
<html>
  <head>
    <meta http-equiv=“Content-Type” content=“text/html; charset=iso-8859-1” />
    <title>Orders</title>
  </head>
  <body>
    <h1>Order Detail</h1>
    <p>Find me in app/views/orders/index.html.erb</p>
    Order ID: <%= @order.id %><br/>
    Order #: <%= @order.ordPK %><br/>
    Customer PO #: <%= @order.ordCustPONum %><br/>
  </body>
</html>

View-Related File Locations

Views \app\views\<modelname>\<myviewname>
Helpers \app\helpers\<modelname>_helper.rb
Images \public\images\
Stylesheets \public\stylesheets\
JavaScripts \public\javascripts\
Layouts \app\views\layouts\
Partials \app\views\<modelname>\_<partialname>.rhtml.erb

Link a CSS Stylesheet into the HTML by using:

<%= stylesheet_link_tag mystyle.css” , :media => “all” %>
   
…instead of…
<link href=”style.css” mce_href=”style.css” rel=”stylesheet” type=”text/css” />

Link in Javascript by using:

<%=javascript_include_tag :defaults %>
    
…or…
<%=javascript_include_tag “prototype”, “effects”, “dragdrop”, “controls” %>

*I got much of this post from a web training presentation that I can’t find to give credit, I apologize!

Blog at WordPress.com.