Thursday, November 29, 2007

looking at merb

I've been spending a litte time getting acquainted with merb. Last night, I gave a quick highlevel overview of merb at our local Tech Vally Ruby Brigade. I've used my merb time to also get acquainted with two other gems that I've had my eyes on for a few months; HAML and DataMapper.

After the quick merb overview presentation, we then merb'd up a 'hello world', using DataMapper, Erubis and for fun a little HAML.

Some merb bullet points from the presentation:
  • Speed
    • Favors speed over magic.
  • Lightweight
    • small, concise code base - no code is the fastest code
    • prefer plugins (gems) over bloated core
  • Powerful
    • multi-threaded
    • very extensible (orm, template engine, test framework, javascript framework, etc.)
  • ORM Agnostic
    • Ships with support for Active Record, Data Mapper, Sequel, but really any ORM can be used.
  • Template Agnostic
    • Ships with support for Erubius, Markaby, Haml, etc
  • JavaScript Library Agnostic
    • Feel free to use Jquery, Prototype/ Scriptaculous, MooTools, etc.
    • merb uses a slick require_js/include_required_js combination
  • Test agnostict
    • Rspec, Test::Unit, test/spec etc.
  • Targeted Generators
    • You tell Merb what ORM, and Testing, you are using and the generators build the respective code
  • Provides API (instead of Rails responds_to)
    • provides :xml, :js, :yaml
  • Custom HTTP Exceptions
    • All the standard http error codes can be raised and then handled with controller/view patterns using an exceptions controller as a starting point. So, you can raise NotFound, BadRequest, NotAcceptable, etc
  • Parameterized Actions
    • You can define the params you want to grab out of the params collection in your method signature: def note_edit(title, body) will grab params[:title], params[:body]
    • This allows you treat your controller methods more like real methods with overloads.
    • For example: if you define:
      • def foo(param1, param2) ...end
      • def foo(param1)...end
      • Then some_url/foo/1?param2='foo' maps def foo(param1, param2)
      • and, some_url/foo/1 maps def foo(param1)

  • Uses standard ruby “gems” for plugins.
    • Your plugins (i.e. gems) can be installed in a application specific /gems folder or as standard “gem install”
  • Parts (which are like reusable components) can define their own layout, views and controller
Happy Merb'ing

simple 2 column content w/border nav

There are 1000's of css column layout tips and tricks available, a lot of which are focused around solving a fluid design pattern. A lot of these introduce extra mark-up (div's) for the purpose of creating faux column background so that columns look the same height. As we all know, extra divs that provide no semantic content suck. Be pragmatic, and when you need to use them to make a hard problem easy, then use them. But, when you don't, well...don't.

Often when you find yourself getting caught in a tangled mess of extra divs, and take the time to make it better, you find that the right answer is no extra divs. I was reviewing some code today where a few extra divs, and a bunch of extra style were being applied to over complicate a situation. The situation was a common one; the need to present some content and include a left nav menu to go along with the content. The extra work was being done to give the impression that the two columns were the same height. And extra work was being done to prevent the fluid layout choice from being all that...well fluid. In this case, the menu was always to be to the left of the content, and the menu width and content width were known (proportionatly speaking). So, extra work was done to prevent a break or wrap between the two the when browser text size or dimensions changed. In other words, fluid behavior wasn't desired to begin with.

In this case, a better solution was a much simpiler solution. First remove all extra divs, including anything wrapping the two for the purpose of a faux background in one of the columns. Also, treat the menu as what it was, an ordered list of things and don't wrap it in any extra tags. Define a border-left to the content with the width dimensions that was previously used in the extra div wraps around the menu stuff, and then float the ul (menu) to the left with a negative margin to place it in the left border. The left border is set with the background-color that was desired for the left column. No need to fake an attempt to get the left column to extend the same height as the content column, because a border does that by default.

Here is a simplified look at the type of solution:
<html>
<head>
<style>
#content{
float: left;
width: 42em;
border-left: 8em #2e3436 solid;
height: 20em;
background-color: #eeeeec;
}
#content-menu{
float: left;
margin-left: -8em;
color: #eeeeec;
}
</style>>
</head>
<body>
<div id="content">
<ul id="content-menu">
<li>foo</li>
<li>foo1</li>
<li>foo2</li>
</ul>
<p>here is some content</p>
<p>and some more content</p>
</div>
</body>
</html>

Saturday, November 17, 2007

rounded stuff

CSS3 will introduce the border-radius style that will finally allow rounder corners to simply be an element style property. Something like
.rounded{border-radius: 12px;}
will certainly reduce a lot of unnecessary markup muck that is currently used just to place an image on 4 corners of an element.

Most of my current web development(but definitely not all) is application development, where I usually know some about the user base. In these cases, I generally go with javascript (yes, done in a nice unobtrusive manor) just to keep the markup pure and free of the extra div's usually required for the css rounded corner techniques. If you are already using a javascript framework, this can become a piece of cake to implement. My current favorite combination is JQuery and the JQuery Corner script. Something like
$('.rounded').corner("round 12px") 
gets me there currently in a very unobtrusive way.

One of the payoffs of creating nice pure markup, and clearly separating style and behavior, is that when CSS3 is implemented in a browser that is the target for one of my web application projects, it becomes pretty simple to change from a javascript behavior approach to a style approach. The markup remains untouched, and all I'll have to do is remove one javascript behavior and trade it for one css style attribute.

Wednesday, November 14, 2007

monorail nvelocity property accessor

... the monorail nvelocity syntax for getting at a indexed property (like a dictionary/hash object) with a variable key is:

$dict.get_item($key)

I had immediately changed my $dict.Item($key) into $dict.getItem($key) when the first didn't work; thinking in terms of Velocity. But no dice.

The solution is right there in the monorail faq sheet, but I must have been searching with blinders on this afternoon, because for the life of me I couldn't find it or remember the syntax.