Sonntag, 26. Januar 2014

Be always unobtrusive! ...coding Javascript

It's always a good idea to separate logic and presentation, especially coding Javascript. For reading more about unobtrusive Javascript and why going for it, take a look at the reference links at Wikipedias "Unobtrusive Javascript" article.
And here is a short but revealing example (using jQuery as Javascript library).
The index.html lists 3 languages:

  • Ruby
  • Python
  • Javascript
which looks and behaves like:
  • Ruby
  • Python
  • Javascript

After refactoring the index.html to:
  • Ruby
  • Python
  • Javascript
and moving the Javascript into the application.js:
$(document).ready(function(){
  $("#languages li").click(function(event){
    $(this).toggleClass("selected");
  });
});
both logic and presentation looks much cleaner.
The refactored example:
  • Ruby
  • Python
  • Javascript
Please note, now the separated Javascript logic is observed onto the 'li' tags right after the DOM was loaded. Besides the HTML list elements are scoped by the 'ul' id ('languages').
Never pollute your HTML with any Javascript.

Supported by jQuery 1.10.2

Use Rails model association!

It is always recommended to use the defined model association instead of querying directly. And there are many reasons, why you should follow that advice. Example.
The models:
class Task < ActiveRecord::Base
  belongs_to :person
end

class Person < ActiveRecord::Base
  has_many :tasks
end
The Controller:
class TasksController < ApplicationController
  @task = Task.find_by_id params[:id]
  @person = Person.find_by_id @task.person_id
end
It generates the queries:
Task Load (6.6ms)  SELECT `tasks`.* FROM `tasks` WHERE `tasks`.`id` = ? LIMIT 1  [["id", 1]]
 => Task id: 1, ...
Person Load (0.8ms)  SELECT `people`.* FROM `people` WHERE `people`.`id` IS NULL LIMIT 1
 => nil
The task @task is not associated with any person. Querying for the tasks person directly is bad practice, because it is a waste and even generates an accidential SQL statement (The condition "WHERE people.id IS NULL" is simply horrible). Refactor it with:
@person = @task.person
 => nil

Rails does not fire a SQL statement, because it checks, if the task object is associated at all.

It saves you a SQL query (if not associated).
It prevents you from duplicating a class name (Person).
It is more readable.

Supported by Ruby 1.9.3 and Ruby on Rails 3.2.1