Sonntag, 25. Januar 2015

Bitmask the boolean attributes!

Some database tables suffer from excessive boolean attributes. Especially when most are likely to be NULL.
Merging the boolean attributes into one single bitmasked integer attribute is a solution. Then the integer value represents multiple flags (booleans) bitwise. Metaphorical spoken: several boolean attributes are stacked into the value of one integer attribute
The advantages for bitmasking boolean attributes are:
  1. much lower attribute baggage: 1 integer (usually 4 bytes) can take up to 32 boolean attributes
  2. flexible database structure (a new boolean attribute does not require a database migration)
  3. readable semantic values (the values are meaningful compared to the boolean true/ false)
  4. dynamic access to the bitmask values, which feels more Rubyish
Although there are various pros, the downsides also have to be considered. Bitmasking definitely does not fit for every use case, like most patterns. Abusing it introduces more pain than relief, because it also:
  1. reduces readability in the database layer (the stacked integer value is hiding the meaningful attribute names)
  2. introduces a (very small) Ruby layer for processing the stacked values (back and forth)
  3. means to work around attribute representations, which rely on the database data type (like simple_form gem)
The gem bitmask_attribute lightens the workload for dealing with the bitmasking logic. It provides a nice API to deal with. So instead of a migration with only a few boolean attributes:
create_table :people do |t| 
  t.string :name
  t.boolean :product_owner, null: false, default: false
  t.boolean :developer, null: false, default: false
  t.boolean :scrum_master, null: false, default: false
  t.boolean :sales, null: false, default: false
end 
the same model can be refactored to:
create_table :people do |t| 
  t.string :name
  t.integer :roles
end 
The appropriate model:
class Person < ActiveRecord::Base
  bitmask :roles, 
    as: [:scrum_master, :product_owner, :developer, :sales]
end
and by now the bitmask can be used:
Person.values_for_roles
=> [:scrum_master, :product_owner, :developer, :sales]
person = Person.create name: 'Bob', 
  roles: [:scrum_master, :developer]
person.roles
=> [:scrum_master, :developer]
person.roles << :sales
person.roles
=> [:scrum_master, :developer, :sales]
person.roles? :developer
=> true
If the bitmask has to be represented by check boxes in the Ruby on Rails view:
<% Person.values_for_roles.each do |role| %>
  <%= check_box_tag 'person[roles][]', role, 
        @person.roles.include?(role), id: role %>
  <%= label_tag role, role.to_s.humanize %>
<% end %>
generates the HTML:








Using bitmask_attribute requires to think about the pros and cons in the forefront, because migrating the production data back to boolean attributes is awkward. Furthermore, when it comes to boolean attributes representing several states (especially when the combination of boolean attributes respresent those states), a state machine should be considered.
Further articles of interest:

Supported by Ruby 2.1.1 and Ruby on Rails 3.2.19

Sonntag, 18. Januar 2015

Filter the named parameters!

Named parameters are great for reducing complexity of method parameters in Ruby. Filtering the named parameters for relevance, by limiting the keys to the expected few, makes sense in some cases. Especially, if logic is bound to the API keywords.
An example Team class API could be:
class Team
  def initialize name, roles={}
    @name = name
    @roles = roles
  end

  def roles
    @roles.keys
  end
end
Team.new('Scrum', product_owner: 'Alice', 
  scrum_master: 'Bob').roles
=> [:product_owner, :scrum_master]
looks plausible.
But:
Team.new('Scrum', product_owner: 'Alice', 
  sales: 'Sarah').roles
=> [:product_owner, :sales]
is definitely not a Scrum team.
Every time the API expects certain named parameters, those have to be filtered, like:
class Team
  def initialize name, roles={}
    @name = name
    @roles = [:product_owner, :scrum_master, :developer].
      each_with_object(Hash.new) { |role, hash| 
        hash[role] = roles[role] if roles.has_key?(role) 
      }
  end

  def roles
    @roles.keys
  end
end
Team.new('Scrum', product_owner: 'Alice', 
  sales: 'Sarah').roles
=> [:product_owner]
Please note, that :sales was filtered out, like any would have been except :product_owner, :scrum_master or :developer.
The Hash filtering logic is likely supposed to be repeated. And that is why extending the Hash is plausible.
Ruby on Rails already has in their ActiveSupport gem. The Hash#slice does exactly filter a Hash for keys. So the example in Ruby On Rails would rather look like:
class Team
  def initialize name, roles={}
    @name = name
    @roles = roles.slice :product_owner, :scrum_master, :developer
  end

  def roles
    @roles.keys
  end
end
Team.new('Scrum', product_owner: 'Alice', 
  sales: 'Sarah').roles
=> [:product_owner]
Furthermore Hash#slice! even replaces the hash itself with the given keys. But beware it returns a hash with the removed key/ value pairs.
Further articles of interest:

Supported by Ruby 2.1.1 and Ruby on Rails 4.1.8

Sonntag, 11. Januar 2015

Customize the Rails FormBuilder!

Tolerating as less as possible Ruby logic in the Ruby on Rails views is a basic pattern.
But instead of putting the logic into a Helpers method or Decorator class, moving it into a customized FormBuilder is worth a consideration.
Especially when it:
  1. is tied to a form
  2. is repeated
  3. generates tags (or even multi tag widgets)
Lots of Ruby on Rails views suffer from Ruby blocks with only logic inside (generating the over and over same HTML tag structure) or iterations like:
<% form_for @recipe do |f| %>
  <% (1..10).each do |rating| %>
    <%= f.radio_button :rating, rating %>
    <%= f.label "rating_#{rating}", rating %>
  <% end %>
<% end %>
What if the view could be refactored to:
<% form_for @recipe, builder: Forms::CollectionFormBuilder do |f| %>
  <%= f.labeled_radio_button_group 1..10, :rating %>
<% end %>
Please note the defined option builder:, pointing to the customized FormBuilder.
The better readability is obvious, aside from the less coding. It can be achieved by creating a new class (collection_form_builder.rb) in lib/forms:
module Forms
  class CollectionFormBuilder < ActionView::Helpers::FormBuilder
    def labeled_radio_button_group collection, method, options={}
      collection.inject(''.html_safe) { |html, value|
        checked = object.send(method).eql? value
        options[:id] = "#{method}_#{value}"
        html += @template.radio_button_tag("#{@object_name}[#{method}]", value, checked, options) + 
        @template.label_tag(options[:id], value)
      }   
    end 
  end 
end
by inheriting from ActionView::Helpers::FormBuilder. Thus some instance variables stated by FormBuilder#form_for are available:
  1. @object (the object assigned to form_for itself, like @recipe)
  2. @object_name (the objects name, like "recipe")
  3. @template (the current view (an instance of ActionView::Base); this object provides all methods available in your view)
  4. @options (the options assigned to form_for)
  5. @proc (the block assigned to form_for)
The @template object is coupled with concat (for output) and @proc (which provides the binding from your view). And it provides access to all standard ActionView::Base helper methods, including the custom helper methods (e.g. defined in ApplicationHelper). Furthermore partials can be rendered with @template:
@template.render partial: "fancy_widget", 
                 locals:  { object: @object }
Besides overwriting existing FormBuilder methods can make sense:
module Forms
  class LabeledFormBuilder < ActionView::Helpers::FormBuilder
    def check_box method, options={}, checked_value="1", unchecked_value="0"
      text = options.delete :text
      @template.content_tag(:label) {
        super(method, options, checked_value, unchecked_value) +
        (text or checked_value).to_s.html_safe
      }
    end
  end 
end
which generates the typical check box tag embraced by a label tag:
<% form_for @recipe, builder: Forms::LabeledFormBuilder do |f| %>
  <%= f.check_box :published, text: 'Published', id: nil %>
<% end %>
resulting in HTML:

Further articles of interest:

Supported by Ruby 2.1.1 and Ruby on Rails 4.1.8

Sonntag, 4. Januar 2015

Splat in Ruby method parameters!

Some methods have to deal with collections. The method definition for assigning a collection should not look like:
class Recipe
  def initialize ingredients=[]
    @ingredients = ingredients
  end
end
because sending the message then is as awful as:
Recipe.new ['Banana', 'Chocolate', 'Almonds']
or even worse:
Recipe.new ['Banana']
But the splat (*) operator in Ruby can solve it. The code can be refactored to:
class Recipe
  def initialize *ingredients
    @ingredients = ingredients.flatten.sort
  end

  def ingredients
    @ingredients.join(', ')
  end
end
and sending the message again:
recipe = Recipe.new 'Banana', 'Chocolate', 'Almonds'
recipe.ingredients
=> "Almonds, Banana, Chocolate"
or assigning just one object:
Recipe.new 'Banana'
Even assigning an Array works, because Array#flatten flattens the collection into an one dimensional array:
ingredients = %w(Banana Chocolate Almonds)
recipe = Recipe.new ingredients
=> #<Recipe:0x00000003de66a8 @ingredients=["Almonds", "Banana", "Chocolate"]>
In general the splat (*) operator can be used to split an Array:
one, two, three = *[1, 2, 3]
one
=> 1
two
=> 2
three
=> 3
and to collect an Array:
*numbers = 1, 2, 3
numbers
=> [1, 2, 3]
With the help of the Ruby splat (*) operator method parameters can be variable from zero up to many and handled as an Array internally. No archaic Array assignments anymore. And flatten the collection parameter with Array#flatten increases the flexibility of the API method.
Further articles of interest:

Supported by Ruby 2.1.1

Sonntag, 28. Dezember 2014

Reduce Ruby method parameter complexity!

In Ruby land it is approved that more than 3 method parameters are far too much. Such bloated parameter lists are a code smell. And they smell like a logic overload, which by the way is hard to test. So looking for breaking them apart into smaller pieces is definitely the first step. But even if there is only a small thing going on, there are chances to decrease parameter complexity. A small parameter list is fundamental for a maintainable method. The smaller the parameter list, the less it is likely to change and the greater the chances the method keeps on being stable. Aside from that, a long API parameter list is harder to satisfy and harder to read:
  def foo name, value, state, start_at, end_at, is_new
    # something weird is going on
  end
Never waste time (money) and cheerfulness by trying to deal with code like the above. Refactor it! There are several options, depending on the use case.

1. Deal with parameter objects!

If the method signature consists of parameters, which are likely to be properties of the same object, it is healthy to assign the entire object itself.
class Food
  attr_accessor :name, :kcal, :freshness_date
end

class Consumer < Person
  def eats food_name, kcal, freshness_date
    return if self.allergies.includes?(food_name) or 
      freshness_date.eql?(Date.today)
    self.kcal += kcal
  end
end
can be refactored to:
class Consumer < Person
  def eats food
    return if self.allergies.includes?(food.name) or 
      food.freshness_date < Date.today
    self.kcal += food.kcal
  end
end
With parameter objects, the method signature is way more resistant against changes and therefore more stable in the long run. Furthermore if the logic needs to be reused, the method can be extracted into a module easily.

2. Introduce named parameters!

The more generalized the methods logic or the lower the abstraction level, the more the methods parameter list is likely to consist of optional parameters. Sometimes such methods look like:
class Food
  def initialize name, kcal=0, freshness_date=nil, preservative=nil
    @name = name
    @kcal = kcal
    @freshness_date = freshness_date
    @preservative = preservative
  end
end
Food.new 'Apple', nil, nil, false
which is awkward (since nil is always a bad choice). It should be refactored to:
class Food
  def initialize name, options={}
    @name = name
    @kcal = options[:kcal]
    @freshness_date = options[:freshness_date]
    @preservative = options[:preservative]
  end
end
Food.new 'Apple', preservative: false
Please note the way more expressive object instantiation. Besides adding new optional parameters to the options Hash is easy and does not affect existing code.

3. Replace Parameter with Explicit Methods!

Some use cases do not require a parameter list at all and those parameters should be set explicitly. The object instantiation example again:
class Food
  def initialize name, kcal=0, freshness_date=nil, preservative=nil
    @name = name
    @kcal = kcal
    @freshness_date = freshness_date
    @preservative = preservative
  end
end
Food.new 'Apple', nil, nil, false
but his time defining values with explicit messages:
class Food
  attr_accessor :kcal, :freshness_date, :preservative
  def initialize name
    @name = name
  end
end
apple = Food.new 'Apple'
apple.preservative = false

Further articles of interest:

Supported by Ruby 2.1.1