The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Finding the shortcut and using it effectively

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
David Heinemeier Hansson

Posts: 512
Nickname: dhh
Registered: Mar, 2004

David Heinemeier Hansson is the lead Ruby developer on 37signal's Basecamp and constructor of Rails
Finding the shortcut and using it effectively Posted: Apr 4, 2004 8:51 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by David Heinemeier Hansson.
Original Post: Finding the shortcut and using it effectively
Feed Title: Loud Thinking
Feed URL: http://feeds.feedburner.com/LoudThinking
Feed Description: All about the full-stack, web-framework Rails for Ruby and on putting it to good effect with Basecamp
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by David Heinemeier Hansson
Latest Posts From Loud Thinking

Advertisement

Charles Miller examines the getter/setter syndrome in Java1 from a usage (rather than the normal construction) perspective and devices a shortcut. Instead of using individual access methods, he proposes the unified set_properties that takes a hash of attributes and automatically assigns them on the object instance. Unfortunately, he fails to see its uses and discards the idea with a clever Simpsons reference (we like those).

That's a shame because he had the right idea.

In constructing Rails, I reached exactly the same shortcut—albeit with slightly more natural Ruby-like semantics by using a signature of Object#attributes=(attributes). More importantly, I found an extremely handy use for it. Passing data from the view to the model in a MVC-style application usually means doing it twice. In the view with input tags as part of a form and in the controller by picking attributes from the request and calling access methods on the model. That's inefficient at best and error prone at worst.

Instead Rails adopts a combination of PHP-like input names that turns form data into hashes and the unified attribute assignment to do as follows:

<!-- The view -->
<form>
  Name:    <input type="text" name="user[name]">
  Email:   <input type="text" name="user[email]">
  Website: <input type="text" name="user[website]">
</form>
 
# The controller action
def create_user
  user = User.new
  user.attributes = @params["user"]
  user.save
end

As the form is submitted by the user, the Rails controller turns user[name], user[email], and user[website] into a hash that contains the name, email, and website as keys and the user supplied input as values. This hash can be accessed through @params["user"] from the action method.

Now the clever part is that the name, email, and website keys from the form maps to attributes with accessors on the model. This relieves the controller of a per-attribute knowledge responsibility, which allows us to add new fields on the view and model without changing the controller.

Actually, we only lavishly spent three lines in the controller to make it slightly easier to follow each step separately. Normally, it would likely look as follows (if there's to be no validation of the attributes):

def create_user
  User.new(@params["user"]).save
end


Relief from per-attribute knowledge responsibility
In fact, the Rails framework goes even further in its attempt to relieve as many layers of per-attribute knowledge responsibility as possible. In your average web-application layer stack, it's not uncommon to have per-attribute knowledge spread across five concerns:

  1. The form: One input field per attribute.
  2. The action: The request is picked for attributes and they're assigned to the model.
  3. The model: Each attribute is specified on the model with a type and boiler-plate serving of accessor methods.
  4. The ORM: Column names are matched against model attributes and a type-conversion specified.
  5. The database table: All persistable attributes in the model are given a column with a name and a type.

Everytime the model needs to evolve to either add, remove, or change attributes, you have to change each concern in a similar but distinct manner to move forward. That's an extremely cumbersome, time-consuming, and—again—error-prone dance of repetition.

Rails allows you to cut all that clutter in between the form and the database table and only work at the ends when the model needs to evolve. The action, model, and mapping steps are all handled by building on the knowledge already present in the form and in the database table.

So let's imagine that our lovely user from the example above needs to also be identified by a instant message handle. In Rails, this would require the following changes:

  • Addition to view:
    IM: <input type="text" name="user[im_handle]" />
  • Addition to database table:
    im_handle VARCHAR(100)

That's it. Now you're free to enjoy the rest of the Sunny day on the lawn with a drink and a hat while your lesser fortunate friends is caught in the toils of per-attribute knowledge spread across the entire layer stack. So much for low coupling, eh?

1. That onerous expenditure of 8-12 lines boiler-plate access code per attribute in stark contrast to Ruby's use of just 1 line for all attributes. An inefficiency that it shares with C#.

Read: Finding the shortcut and using it effectively

Topic: Pretty Rublogs Previous Topic   Next Topic Topic: Using WEBrick

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use