Let’s dive into code!

28 April 2009 1:42

I love screencasts! Screencasts are an easy and fun way to learn new technologies. If you want to avoid fluff, dive directly into code… screencasts are one of the best tools to achieve it!

I was impressed with a great work done by Geoffrey Grosenbach from PeepCode or guys like Bill Dudney or Ryan Bates who publish their recordings under Pragmatic Programmer umbrella. I have bought almost all material they have produced and it was money well spent.

After watching a few of their episodes I understood I would love to follow into their footsteps and start to produce my own screencasts. A few months later, working after hours I finished my online store and recorded Stripes fundamentals.

It is the first out of a series of screencasts that map out how to use Stripes to solve everyday web application development challenges in a simple and efficient way. The whole series is based on application-centric approach where the development of an online shop application drives the coverage of Stripes.

At code quest I don’t want to focus only on one domain or technology. The upcoming screencast will be dedicated to deployment on Ubuntu. I am recording it together with my friend Piotr Maj and it should be available by the end of May. Please stay tuned!

I hope screencasts published at code quest will help developers learn in a fast and efficient way. My goal is to produce high quality stuff at a reasonable price. And my hope is that you’ll help me achieve this goal. It is an agile project and you get to help steer.

I look forward to your feedback.

Do you like it? Please share it!

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • Wykop
  • Technorati
  • DZone
  • NewsVine
  • Slashdot
  • StumbleUpon
Posted in: Experiments | 1 Comment »

Patterns of project behavior

2 January 2009 6:08

Tom DeMarco is one of my favorite technical writers.

Recently, on a blog of one my friends, I have read a recommendation for Deadline by Tom DeMarco.

I fully agree with my friend that this easy, entertaining book provides some valuable ideas about how to improve a project and can be a great read for a software engineer who has been moved to project manager role.

In addition to Deadline I would like to recommend another book by Tom DeMarco I have just read - Adrenaline Junkies and Template Zombies.

Software engineers should be aware of elegant solutions to common problems in software design. They should know patterns for managing object creation, composing objects into larger structures, and coordinating control flow between objects. They should also recognize and correct bad habits of code and design.

I believe the same story is with project managers.

Project Manger should know good patterns to follow and anti-patterns that should be avoided.

Tom DeMarco together with the team of his friends from the Atlantic Systems Guild has done a nice job and described 86 patterns of project behavior.

Patterns can be read in a moment. Each pattern is about two pages long with titles that build strong association in the brain… e.g. adrenaline junkies, dead fish, project sluts, template zombies…

You won’t be surprised how often you will say… “Ahh… I recognize it… somebody is spying on my company… this is exactly what is happening right now in my project…”

I strongly believe this is a fun, interesting read for all software engineers and project members and… definitely the must read for project managers who want to avoid pitfalls and boost effectiveness of their teams.

Adrenaline Junkies and Template Zombies can be consumed in an evening or during a longer flight with very little effort.

If you normally fall asleep while reading books about project management, give Adrenaline Junkies and Template Zombies a try. I am sure you won’t be disappointed!

Do you like it? Please share it!

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • Wykop
  • Technorati
  • DZone
  • NewsVine
  • Slashdot
  • StumbleUpon
Posted in: Bookshelf, Peopleware | No Comments » tags:

How to write a custom form builder in Rails?

28 December 2008 6:00

Most of the current web applications contain many different types of forms. Usually they look very similar across the whole application and they are a source of repetitive code in your presentation layer.

In this blog post I would like to share with you how to minimize this repetitive code and make your form nice, concise and dry by writing custom form builders.

Let’s say you are building a new web application with your close friend. He is a ninja of css, a web standards orthodox and requires that application generate forms that look like the piece of html below.

<form action="/users" class="new_user" id="new_user" method="post">
<fieldset>
<legend>Sign up:</legend>
<dl class="required correct">
<dt><label for="user_login">Login</label></dt>
<dd><input id="user_login" name="user[login]" size="30" type="text" value="tomek" /></dd>
<dd class="notice">Lowercase letters (a-z) & numbers only - no spaces.</dd>
</dl>
<dl class="required error">
<dt><label for="user_email">E-mail</label></dt>
<dd class="error">can't be blank</dd>
<dd><input id="user_email" name="user[email]" size="30" type="text" value="" /></dd>
<dd class="notice">We won't get you spammed!</dd></dl>
...
</fieldset>
</form>

You are fully aware you cannot generate this kind of html with the standard helper methods provided by Rails.

On the one hand you don’t want to upset your friend and even start negotiations on how forms should be styled. On the other hand you would like to keep the code of your view concise and easy to maintain… let’s say more or less like the snippet below.

<% form_for @user do |f| -%>
<fieldset>
<legend>Sign up:</legend>
<%= f.text_field :login, :notice => "Lowercase letters (a-z) & numbers only - no spaces." %>
<%= f.text_field :email, :label => 'E-mail', :notice => "We wont get you spammed, we promise!" %>
...
</fieldset>
<% end -%>

Well… in tis situation… there is no other way. You have to write your own form builder!

What is a form builder?

ActionView::Helpers::FormBuilder is one of the “hidden hero” Rails classes. It is used on a frequent basis but not everybody realizes it even exists.

Whenever you use form_for helper in your view template, you pass an instance of FormBuilder class to the block associated with the method. Look at the snippet above. This is f variable.

So… if you want to create your own LabeledFormBuilder class with the enriched functionality all you need is to subclass ActionView::Helpers::FormBuilder and instruct Rails to use it. There are a few ways to do it.

One of the solutions is to create a new folder with Ruby file that will contain LabeledFormBuilder class and add it to load paths of Rails environment.

Let’s say you have just created a folder named builders with labeled_form_builder.rb file under app directory of your application. In order to tell Rails to load ruby code located in this place you have to add one line to your environment.rb file.

# app/config/envirnoment.rb
Rails::Initializer.run do |config|
...
config.load_paths += %W( #{RAILS_ROOT}/app/builders )
...
end

Next time you restart the server Ruby code placed in the labeled_form_builder.rb file will be loaded.

It is high time you rolled up your sleeves and wrote custom form builder!

Below I would like to show exemplary implementation that may help you to stay on speaking terms with your css ninja friend. I will also share a trick that I consider very useful and cool.

# app/builders/labeled_form_builder.rb
class LabeledFormBuilder < ActionView::Helpers::FormBuilder

  %w[text_field password_field text_area].each do |method_name|
    define_method(method_name) do |field_name, *args|
      options = args.extract_options!

      # Create field
      field = @template.content_tag(:dt, label(field_name, options[:label]))

      # Add validation errors
      field += field_errors(field_name)

      # Add field element
      field += @template.content_tag(:dd, super)

      # Add notice message
      field += @template.content_tag(:dd, options[:notice], :class => 'notice') if options[:notice]

      # Render field container with all elements
      @template.content_tag(:dl, field, :class => field_style(field_name))
    end
  end

  def check_box(field_name, *args)
    options = args.extract_options!
    @template.content_tag(:dl, super + label(field_name, options[:notice]), :class => "checkbox")
  end

private

  def is_required?(field_name)
    object.class.reflect_on_validations_for(field_name).map(&:macro).include?(:validates_presence_of)
  end

  def has_errors?(field_name)
    object.errors.invalid? field_name
  end

  def field_errors(field_name)
    field_errors = ''
    if has_errors?(field_name)
      object.errors[field_name].each do |msg|
        field_errors += @template.content_tag(:dd, msg, :class => 'error')
      end
    end
    field_errors
  end

  def field_style(field_name)
    field_style = ''
    if is_required?(field_name)
     field_style += 'required'
    end

    if has_errors?(field_name)
     field_style += ' error'
    elsif !object.errors.empty?
     field_style += ' correct'
    end
    field_style
  end    

  def objectify_options(options)
    super.except(:notice, :label)
  end
end

Now let me share a trick with you. Please look at is_required method. In the line…

# app/builders/labeled_form_builder.rb
...
object.class.reflect_on_validations_for(field_name).map(&:macro).include?(:validates_presence_of)
...

… I use validation reflection plugin to find out if a given field is required or not.

I also use a piece of metaprogramming to provide own implementation of text_field, password_field, text_area helper methods.

The only thing that is missing to make this little example work is intruction to Rails to use LabeledFormBuilder instead of the default one. There are two ways you can do it.

First of all you can add builder attribute to form_for helper.

<% form_for @user, :builder => LabeledFormBuilder do |f| -%>
<fieldset>
<legend>Sign up:</legend>
<%= f.text_field :login, :notice => "Lowercase letters (a-z) & numbers only - no spaces." %>
<%= f.text_field :email, :label => 'E-mail', :notice => "We wont get you spammed, we promise!" %>
...
</fieldset>
<% end -%>

Secondly you can go to your environment config file and add one line to register your custom form builder as the default one.

# app/config/envirnoment.rb
ActionView::Base.default_form_builder = LabeledFormBuilder

That’s all! Now you can send a message to your friend that his html code is safe and you can open bottle of wine :-)

Do you like it? Please share it!

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • Wykop
  • Technorati
  • DZone
  • NewsVine
  • Slashdot
  • StumbleUpon
Posted in: Software | 6 Comments » tags:

Don’t cry for me Argentina

4 December 2008 8:49

I am back. I took almost one month of vacation to make my first steps to South America.

I was traveling around Argentina: learning tango in Buenos Aires, admiring glaciers in El Calafate, playing with whales and penguins in Puerto Madrid, watching the beauty of waterfalls and jungle in Iguazu and learning about history and culture heritage of Argentina in Salta.

Traveling is for me more about gathering new experiences rather than just pure relaxation. If a trip shook up my perception of the world and changed it a little then journey was a success.

My visit to Argentina was definitely successful. My perception of South America and Argentina in particular has changed.

I made friends with people from Chile, Peru and a few other countries, experienced the beauty of Argentina which I will try to share on the natrasie.pl.

I am sure I will come back to this part of the world. Don’t cry for me Argentina. I will be back!

Hasta la vista.

Do you like it? Please share it!

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • Wykop
  • Technorati
  • DZone
  • NewsVine
  • Slashdot
  • StumbleUpon
Posted in: Life | 1 Comment » tags: ,

Internationalization in Rails 2.2

18 October 2008 1:00

In the darkness of a night, exhausted after long hours of your day-work, you build a new kicking ass web application.

You want to change the world and make your application accessible to all good people out there… that’s why your a new-born baby has to speak several languages!

Now with Rails 2.2 it is easy! All you need to know is two API methods: I18n.transate aka I18n.t and I18n.localize aka I18n.l …and somebody who can help you with translation to exotic languages like Chinese, Thai or Polish.

In this post you will find a quick, step-by-step tutorial how to add internationalization to your Ruby on Rails application. Please be aware it is a very simple example and you have to “live on the edge” to fully benefit from this post… ok… no more fluff and let’s dive into code together!

First of all let’s create Rails app, freeze edge and create resource to test things out.

rails speak2me
cd speak2me
rake rails:freeze:edge
./script/generate resource friend
./script/generate migration AddNameToFriend name:string

Now it is time to create a directory named locales which will contain our translations….

mkdir config/locales

…and create there two translations for English and Polish language

# config/locales/en-US.yml
"en-US":
  main:
    hello: "Hello Darling!"
# config/locales/pl-PL.yml
"pl-PL":
  main:
    hello: 'Witaj Kochanie!'

In the release 2.2 of Ruby on Rails framework there was introduced the I18n module.

In the configuration file we will encapsulate details of what locales are available, where they are kept, and what is to be used as the default. Let’s create i18n.rb file under initializers directory.

# config/initializers/i18n.rb
I18n.load_path += Dir[ File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}') ]
I18n.default_locale = "en-US"

We have just configured I18n module and now it is right time to get use of it in our controller and view files.

First of all let’s add method to set locale. We will create a before_filter in the common base class for all of our controllers.

class ApplicationController < ActionController::Base
  before_filter :set_locale
protected
  def set_locale
    session[:locale] = params[:locale] if params[:locale]
    I18n.locale = session[:locale] || I18n.default_locale
  end
end

Next we will add index.html.erb file with localized version of greeting.

# views/friends/index.html.erb
<%= I18n.t "main.hello" %>

The only thing left is to update route configuration and test things out.

# config/routes.rb
ActionController::Routing::Routes.draw do |map|
  map.resources :friends
  map.root :controller => 'friends'
end

Open your browser and have fun… default locale is en-US but as soon as you change locale param you will get polish version of text.

I have mentioned that in order to localize you Rails 2.2 application you should be aware of two API methods: I18n.transate and I18n.localize.

So far we used only alias to one of the methods - I18n.t. So… what is a function of I18n.localize method?. Well.. this one basically allows you to format Date and Time objects for a certain locale. In order to see it in action we should update our file with polish locale and add one line in view file.

# views/friends/index.html.erb
<%= I18n.t "main.hello" %>
<%= I18n.l Time.now %>
# config/locales/pl-PL.yml
"pl-PL":
    main:
        hello: 'Witaj Kochanie!'

    date:
        formats:
            default: "%d.%m.%Y"
            short: "%e. %b"
            long: "%e. %B %Y"
            only_day: "%e"

        day_names: [Niedziela, Poniedziełek, Wtorek, Środa, Czwartek, Piątek, Sobota]
        abbr_day_names: [N, Pn, Wt, Śr, Cz, Pt, So]
        month_names: [~, Styczeń, Luty, Marzec, Kwiecień, Maj, Czerwiec, Lipiec, Sierpień, Wrzesień, Październik, Listopad, Grudzień]
        abbr_month_names: [~, Sty, Lut, Mar, Kwi, Maj, Cze, Lip, Sie, Wrz, Paz, Lis, Gru]
        order: [ :day, :month, :year ]

    time:
        formats:
            default: "%A, %e. %B %Y, %H:%M"
            time: "%H:%M"
            short: "%e. %B, %H:%M"
            long: "%A, %e. %B %Y, %H:%M"
            only_second: "%S"

        am: "przed południem"
        pm: "po południu"

That’s all folks!

For more details about internationalization in the latest version of Ruby on Rails I strongly recommend to visit Sven Fuchs’s blog. You will get knowledge directly from a source.

Do you like it? Please share it!

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • Wykop
  • Technorati
  • DZone
  • NewsVine
  • Slashdot
  • StumbleUpon
Posted in: Software | 3 Comments » tags: