Sonntag, 2. März 2014

REST in piece! ...a Ruby on Rails perspective

REST means Representational State Transfer and there is also a comprehensive REST dissertation.
This is just a short summary from the Ruby on Rails point of view.
Hence:
  1. A resource service is represented by an URL (Uniform Resource Locator) (e.g. /rails_app/people)
  2. The exact resource itself is represented by the URI (Uniform Resource Identifier) (e.g. /rails_app/people/1)
  3. HTTP verbs are used for addressing the operation (in Ruby on Rails only: GET, POST, PUT and DELETE)
  4. A resources operation can provide various documents (HTML, XML, JSON or others)
This could be a typical RESTful Rails controller, having the Rails standard actions (REST operations):
class PeopleController < ApplicationController
  # HTTP verb: GET
  def index
    respond_to do |format|
      format.html
      format.xml
    end
  end

  # HTTP verb: GET
  def show
    respond_to do |format|
      format.html
      format.json
    end
  end

  # HTTP verb: GET
  def new
    respond_to do |format|
      format.html
    end
  end

  # HTTP verb: GET
  def edit
    respond_to do |format|
      format.html
    end
  end

  # HTTP verb: POST
  def create
    respond_to do |format|
      format.html
    end
  end

  # HTTP verb: PUT
  def update
    respond_to do |format|
      format.js
    end
  end

  # HTTP verb: DELETE
  def destroy
    respond_to do |format|
      format.js
    end
  end
end
In that example the response documents vary from simple HTML to Javascript and were elaborated extensively by the ActionController#respond_to.
RESTful controllers and the pathes to their actions are well structured:
Path HTTP verb Action Behaviour
/people GET index Returns a collection of people
/people POST create Creates a new person
/people/new GET new Returns the form a new person
/people/1 GET show Displays the person having ID: 1
/people/1 PUT update Updates the person having ID: 1
/people/1 DELETE destroy Deletes the person having ID: 1
/people/1/edit GET edit Returns the form for editing the person having ID: 1
To be explicit: there are only a few cases, where your controllers should have other or more than those 7 actions. They already cover the resources lifecycle in terms of CRUD (Create Read Update Delete). And they never should behave different than the mentioned behaviour.
Create your Ruby on Rails controllers in a RESTful style!
It helps you to establish well structured interfaces depending on the path, the HTTP verb and the MIME type.

Supported by Ruby 1.9.3 and Ruby on Rails 3.2.1

Sonntag, 23. Februar 2014

Inject readability! ... a Ruby iteration.

Ruby's Enumerable offers a bunch of iterators for dedicated tasks. One of them is inject (Enumerable#inject Ruby API). It provides you with power and the ability to write concise and meanful code. And it's just readable.
The original iteration using Enumerable#each calculates the 5 factorial:
def factorial factorial_number
  result = 1
  (1..factorial_number).each{|number| result *= number }
  result
end
factorial 5 => 120
can be refactored to the more descriptive:
def factorial factorial_number
  (1..factorial_number).inject(1){|result, number| result *= number }
end
factorial 5 => 120
There are 2 points to be noticed.
  1. you can initialise the iterators looping variable (result) value by just assigning it to inject
  2. inject returns the calculated iterators looping variable itself
    (while Enumerable#each returns the array again)
And by the way, you even could leave the initialising value (1) in this example.
Another example using the above mentioned factorial function puts all factorials into a Hash:
factorials = {}
[1, 2, 3, 4, 5].each do |number|
  factorials[number.to_s] = factorial(number)
end
factorials => {"5"=>120, "4"=>24, "3"=>6, "2"=>2, "1"=>1}
which can be easily refactored to:
[1, 2, 3, 4, 5].inject({}) do |factorials, number|
  factorials[number.to_s] = factorial(number)
  factorials
end
=> {"5"=>120, "4"=>24, "3"=>6, "2"=>2, "1"=>1}
This refactoring may not as obvious as the first example in the first view. But consider you save an initialising line and you make sure to everyone what your intention is:
you process an Enumerable (Array) and return an Enumerable (Hash) without having cumbersome code snippets. At least the Hash object doesn't need to be declared outside the iteration, which is far cleaner.
Be explicit in your code intentions!
There is an alias for Enumerable#inject, called Enumerable#reduce. It's really a matter of taste which one you prefer.

Supported by Ruby 2.1.0

Sonntag, 16. Februar 2014

Next please! ... a Ruby iteration.

The Enumerators next helps to follow the guard pattern for enumerables. I already introduced the guard pattern itself in Return early! ... a Ruby guard pattern example. The following refactoring will map it to an iteration.
First the original code creating ".rb" script files starting with a Ruby shebang:
%w(people.csv task.rb job.rb).each do |file_name|
  if File.extname(file_name) == ".rb"
    File.open(file_name, "w") do |file|
      file << "#!/usr/bin/ruby"
    end
  end
end
which can be easily refactored to:
%w(people.csv task.rb job.rb).each do |file_name|
  next if File.extname(file_name) != ".rb"
  File.open(file_name, "w") do |file|
    file << "#!/usr/bin/ruby"
  end
end
Often the main purpose for next is readability, but it also can prevent you from maintaining awkward code. The idea behind is once again to stop processing the current iteration item as early as possible and process the next item.
Be explicit in your code intentions!

Supported by Ruby 2.1.0

Sonntag, 9. Februar 2014

Return early! ... a Ruby guard pattern example.

The guard pattern means to improve readability, maintainability and stability. And it is a cheap refeactoring technique.
A simple original Ruby code:
class Person
  # weight in gram and height in centimeter
  attr_accessor :weight, :height

  def bmi
    if weight.nil? or height.nil?
      0
    else
      height_in_meter = height * 100
      (weight * 1000) / (height_in_meter * height_in_meter)
    end
  end
end
can be refactored to:
class Person
  # weight in gram and height in centimeter
  attr_accessor :weight, :height

  def bmi
    return 0 if weight.nil? or height.nil?
    height_in_meter = height * 100
    (weight * 1000) / (height_in_meter * height_in_meter)
  end
end
The improvement by just simply returning the result when it is known is obvious.

Supported by Ruby 2.1.0

Sonntag, 2. Februar 2014

Delegate Javascript! ...if you can.

Unobtrusive Javascript is the modern way to code Javascript, as I already stated in "Be always unobtrusive!". On this basis you can go even one step further: event delegation. How event delegation works in detail is well explained by the W3C. Please read about the event capture and event bubbling carefully.
Here I want to give a revealing example. Therefore I will extend the "Unobtrusive Javascript" example inserting some additional list elements.
I use jQuery to help me out writing the example, but event delegation is not library specific.
The index.html was extended with an input element:
  • Ruby
  • Python
  • Javascript
And the application.js:
$(document).ready(function(){
  $("#languages li").click(function(event){
    $(this).toggleClass("selected");
  });
});
  • Ruby
  • Python
  • Javascript

Please try it and type in your favourite language and hit the enter key. It will be added (as a simply Ajax response also could do). But also note that your new added language won't be marked green, clicking on it.
It's because the Javascript was observed directly to the list element.
Delegating the event and its functionality to the container 'ul' will solve the issue. The changed application.js:
$(document).ready(function(){
  $("#languages").delegate("li", "click", function(event){
    $(this).toggleClass("selected");
  });
});
Please note the jQuery function 'delegate'. It does the job and delegates the Javascript click event to the 'ul' container element.
Try it, add a new language and click on it:
  • Ruby
  • Python
  • Javascript

Event delegation saves you massive direct observes.

Supported by jQuery 1.10.2