Web Development
Web 2.0, Ruby, Rails, TDD, BDD,
rSpec, XMPP, BOSH, REST,
Javascript, Ajax, Google Maps API,
Google Gears API, CSS,
Java, C#, Social Network, RMagick

Subscribe in a Reader

Script Console Tricks

Category: By chamnap
Script console in rails helps me very much to debug my applications. However, I usually encounter an annoying problem with ActiveRecord. I want to see the generated SQL that has been executed. I never have enough time to figure out this until last week. Just add the following code to your environment.rb, you could see the generated SQL statement.


if "irb" == $0
ActiveRecord::Base.logger = Logger.new(STDOUT) # ActiveRecord
ActiveResource::Base.logger = Logger.new(STDOUT) # ActiveResource
end


For more information:
http://weblog.jamisbuck.org/2007/1/31/more-on-watching-activerecord
http://railscasts.com/episodes/48-console-tricks
 

My Presentation at Barcamp Phnom Penh 2009

Category: By chamnap
I did two presentations at Barcampp in last week. One is for people who starts learning about the web. I talked on many basic concepts, the history, and how the web works. Some of friends complained me that my slide is too much. Anyway, I think I missed several main points. I just feel it is a prime concept of the web, and it drives me really well since I started learning it. The other is about JavaScript in OOP way. It is the same topic but very compact as I used to do presentation in my office. I did fairly good with borey since some of the audiences interest my presentation.

 

Principles in Refactoring

By chamnap
This week, in my office we did a study group, and vorleak and I were moderators in that session. We studied the book from Refactoring the Existing Code by Martin Fowler. Here is the slide I prepared.

 

Action Caching

By chamnap
Recently, I have been working with RESTful web services. I came to a caching stage where I need to cache some requests that map to my actions. The problem is that I have actions with multiple possible routes, therefore those routes should be cached differently. For example:


/people/1?display=details
/people/1?display=summary
/people/1?display=details&format=xml
/people/1?display=summary&format=json


Fortunately, there is an option inside caches_action called :cache_path. All you need to do is to pass a proc object and return the path you want to cache. It is called with the current controller instance. In this case,

caches_action :index, :show, :cache_path => Proc.new { |c|
request_url = { :controller => c.params[:controller], :action => c.params[:action] }.merge(c.request.query_parameters)
c.url_for request_url
}


There is another problem when the request is coming without format, the cache returns the result with content-type: text/html. To solve this, add a before_filter inside application controller to assign the headers['Content-type'].


def set_default_response_format
response.headers['Content-type'] = 'application/xml; charset=utf-8' if params[:format].nil?
end
 

MVC

By chamnap
Many Rails newcomers, even some people who know MVC quite well, often confuse how to code in the right way. The controller are usually fat, and the logic spreads across the whole application. The views still messy because it contains logic and even worse people often code like a controller (query to db). However, the model are usually skinny. I could say there is no restrictions in the way you code. It is a set of disciplines that every developers must know in order to have a cheaper maintenance.

MVC has been successful for many reasons, and some of those reasons are “readability”, “maintainability”, “modularity”, and “separation of concerns”. You’d like your code to have those properties, right? The rules of thumb are:

1. Controller should be skinny. This is what it means to have a controller know what to do without knowing the details of how to do it.
2. Any complexity related to building a business logic will be specified and implemented in the Model.
3. Inside View, access to instance variables that have been defined in Controller. Try not to use if-else condition or loop as much as possible.

By putting everything in the right place, you would benefit from a lot of MVC pattern.

Good example can be found on:
http://www.therailsway.com/2007/6/1/railsconf-recap-skinny-controllers
http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model
 

Sending mail to developer about exception errors

Category: By chamnap
I want my application to send me a mail about any errors that occurs during production. Basically, I want to see a detail report like in development environment. All I have to do is to override rescue_action_in_public. This method by default calls render_optional_error_file method to render a static page based on status code thrown. rescue_action_locally method by default will render details diagnostics from a controller action. Therefore, I just combine all of these methods into rescue_action_in_public and add some code to send mail.

def rescue_action_in_public(exception)
   render_optional_error_file response_code_for_rescue(exception)

   @template.instance_variable_set("@exception", exception)
   @template.instance_variable_set("@rescues_path", RESCUES_TEMPLATE_PATH)
   @template.instance_variable_set("@contents",
   @template.render(:file => template_path_for_local_rescue(exception)))

# send mail to developers
   mail = ExceptionNotifier.create_sent(@template)
   mail.set_content_type("text/html")
   ExceptionNotifier.deliver(mail)
end

Here is my ExceptionNotifier class, just extract needed variable to be available inside my view.

class ExceptionNotifier < ActionMailer::Base

   def sent(template)
      @subject = 'Bug Reports'
      @body["request"] = template.request
      @body["response"] = template.response
      @body["exception"] = template.instance_variable_get("@exception")
      @body["rescues_path"] = template.instance_variable_get("@rescues_path")
      @recipients = ['chamnapchhorn@gmail.com', 'ungsophy@gmail.com']
      @from = 'noreply@gmail.com'
      @headers = {}
   end

end

Here is my view, the default view for exception. I just change to locate new variables only.

<h1>
   <%=h @exception.class.to_s %>
      <% if @request.parameters['controller'] %>
         in <%=h @request.parameters['controller'].humanize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %>
      <% end %>
</h1>
<pre><%=h @exception.clean_message %></pre>

<%= render :file => @rescues_path["rescues/_trace.erb"] %>

<%= render :file => @rescues_path["rescues/_request_and_response.erb"], :locals => { :request => @request, :response => @response } %>
 

Handling Exception at the Application Level in Rails

Category: By chamnap
At last the point of the project, I found one more important thing that is quite useful and it could reduce the code 20%. That's when I did a handling service error on both server and client. I find myself have been repeating the code on the way. Luckily, after discussion with my colleague, I came up with idea to handle in application controller. It means that instead of handle exception on all of my controllers, I could just handle in a single place whenever exception has raised from these controllers.
Basically, there are two methods (rescue_action and rescue_action_in_public) that you would need to override based on your needs. By default, these two methods do the best job to handle exception both in development and production mode. rescue_action method will be called with an exception parameter that raises inside an action method. rescue_action_in_public method, however, is used for public exception handling (for requests answering false to local_request?). local_request? method tells which rescue_*** method to call.

http://api.rubyonrails.org/classes/ActionController/Rescue.html

More importantly, we can handle exceptions for specific controller instead of the whole. All you need to do is to override one of these methods inside that controller.

class PostsController < ApplicationController
   def rescue_action_in_public(exception)
      case(exception)
         when ActiveRecord::RecordNotFound then render :file => '/bad_record'
         when NoMethodError then render :file => '/no_method'
         else render :file => '/error'
      end
   end
end


We can even handle them in a much cleaner way rather than if/else statement by using rescue_from. What it does is that it maps an exception type to handler method. This handler method can take either an exception parameter or a non-argument. We can even specify a proc or block.

class PostsController < ApplicationController

   # Declare exception to handler methods
   rescue_from ActiveRecord::RecordNotFound, :with => :bad_record
   rescue_from NoMethodError, :with => :show_error

   def bad_record; render :file => '/bad_record'; end
   def show_error(exception); render :text => exception.message; end

end

http://ryandaigle.com/articles/2007/9/24/what-s-new-in-edge-rails-better-exception-handling
 

Maintaining Javascript Pop-Up Window Communication Across Window Opener Page Loads

Category: By chamnap
I came across a blog post that talks how to maintain a reference to javascript popup window while the parent window has been navigated away. This scenario doesn't want to reload the child popup window. I just quoted out from 1 Pixel Out. There is a really nick trick.

In the main window:

var popupWin = null;

function openPopup() {
   var url = "popup.htm";
   popupWin = open( "", "popupWin", "width=500,height=400" );
   if( !popupWin || popupWin.closed || !popupWin.doSomething ) {
      popupWin = window.open( url, "popupWin", "width=500,height=400" );
   } else {
      popupWin.focus();
   }
}

function doSomething() {
   openPopup();
   popupWin.doSomething();
}


In the popup:

self.focus();

function doSomething() {
   alert("I'm doing something");
}


http://www.bennadel.com/blog/89-Maintaining-Javascript-Pop-Up-Window-Communication-Across-Window-Opener-Page-Loads.htm
http://www.1pixelout.net/2005/04/19/cross-window-javascript-communication/
http://www.1pixelout.net/2006/12/15/cross-window-javascript-communication-20/
http://www.1pixelout.net/wp-content/downloads/popups20.zip
 

Cross-window Javascript communication

Category: By chamnap
It reminds me about uploading via iframe that I did a year ago when my colleague asked me to help with login openid in a popup window. It's a similar story with this problem. Actually, login with openid could not place in a iframe because you could the code that prevents this.

<script type="text/javascript">if(top == self) { document.write(""); } else { top.location.href = "http://www.yahoo.com"; }</script>

Now, let's see a quick summary on this basic communication.

Communication from parent to child window, you need to a reference of the child window so that can call any function in the child window.

// Create a new popup window
var popupWin = window.open(url, "popupWin");

// To call functions defined in the popup:
popupWin.doSomething();

Communication from child to parent window, you need to use this way:

window.opener.doSomethingOnParent();

Here is the problem, the parent window needs to know when the uploading (in iframe) or logging in (in popup window) is done. The only way that the parent window can notified by the child window after finish processing. Usually, for uploading and logging in with openid, the action in your controller would render a view back. The trick is here on the onload of the body, you could notify the parent window.

def login
@status = "something"
end

#view
<html><head></head>
<body onload="window.opener.handleOpenIDResponse('" + @status + "');window.close();">
</body>
</html>

That would solve the problem, and you could send any information back through your view.
 

has_and_belongs_to_many or has_many :through?

Category: By chamnap
Well, I had been quite confusing about these two topics before I read some rails books. These are just different ways to do many to many relationships in ActiveRecord.

has_and_belongs_to_many (habtm)
habtm is the very old way since rails 1.2. It creates a link between associated models through an intermediate join table.

class CreateProjectsProgrammers < ActiveRecord::Migration
   def self.up
      create_table :projects_programmers, :id => false do |t|
         t.column :project_id, :integer, :null => false
         t.column :programmer_id, :integer, :null => false
      end
   end
   def self.down
      drop_table :projects_programmers
   end
end
class Programmer < ActiveRecord::Base
   has_and_belongs_to_many :projects # foreign keys in the join table
end
class Project < ActiveRecord::Base
   has_and_belongs_to_many :programmers # foreign keys in the join table
end

Note that an id primary key is not needed in the join table and there is no join model, only join table. Here we will face a problem when we want to add extra columns on the join table. If it is in rails 1.2, we would have used push_with_attributes to do this. However, push_with_attributes has been deprecated in favor of a far more powerful technique, where regular Active Record models are used as join tables (remember that with habtm, the join table is not an Active Record object).

To conclude, habtm is a simple way to do a many-to-many relationship using a join table when the join table doesn't have extra columns. You will need to upgrade the relationship to use has_many :through once you need to add additional columns.

has_many :through
Records in the join table of habtm implementation has no independent existence. Later, we will find it very soon that the join table has a life of its own and should have a model when we add extra columns on that join table. Let's talk about relationship between article, user, and the join model is reading.

When a user reads an article, we can record the fact.

class Article < ActiveRecord::Base
   has_many :readings
end
class User < ActiveRecord::Base
   has_many :readings
end
class Reading < ActiveRecord::Base
   belongs_to :article
   belongs_to :user
end

reading = Reading.new
reading.rating = params[:rating]
reading.read_at = Time.now
reading.article = current_article
reading.user = session[:user]
reading.save


Here we lost what habtm solved. We could not ask a user which articles that they has read and vice versa. To solve this, use :through options inside has_many.

class Article < ActiveRecord::Base
   has_many :readings
   has_many :users, :through => :readings
end
class Reading < ActiveRecord::Base
   belongs_to :article
   belongs_to :user
end
class User < ActiveRecord::Base
   has_many :readings
   has_many :articles, :through => :readings
end

Now, you could do query both direction:

readers = an_article.users
articles = a_reader.articles


Unlike a normal has_many, ActiveRecord won’t let us add an object to the the has_many :through association if both ends of the relationship are unsaved records. The create method saves the record before adding it, so it does work as expected, provided the parent object isn’t unsaved itself. To add extra attributes:


user.readings.create(:read_at => Time.now,
         :rating => params[:rating],
         :article => Article.new)


Choosing which way to build a many-to-many relationship is not always simple. If you need to work with the relationship model as its own entity, use has_many :through. Use has_and_belongs_to_many when working with legacy schemas or when you never work directly with the relationship itself.

http://blog.hasmanythrough.com/2006/4/20/many-to-many-dance-off
http://blog.hasmanythrough.com/2006/4/17/join-models-not-proxy-collections