Wednesday, July 4, 2007

Using Gravatar plugin to embed avatars in rails views

Gravatar offers service to keep your globally recognizable avatars (gravatar). This tiny plugin offers rails view helper to embed gravatars in your views. It can also be used in blog, forums applications to insert gravatar to be visible instead of email. Here is how to install it:

$ ruby script/plugin install http://tools.assembla.com/svn/hasham/plugins/gravatar_tag


Here is sample usage in an erb template:

<%= gravatar_tag "user@domain.com", :size => "60x60"%>


The first parameter which is a email that user signed up with on gravatar.com is required. The other parameters are same as rails image_tag view helper.

Monday, July 2, 2007

SVN Cache made simple with Capistrano 2

You normally don't want to do complete checkout of your source control on every deployment with Capistrano. The SVN cache keeps copy of source code on server in separate directory on each deploy this copy of source code is updated and deployed to releases directory.

Implementing this kind of SVN cache is super simple in Capistrano 2, Just set deploy_via variable to remote_cache like this:

set :deploy_via, :remote_cache

Sunday, July 1, 2007

Mongrel is multi threaded, but rails is not thread safe

The main reason why we need to run multiple mongrel instances (pack of mongrels) for any high traffic website is that Ruby on Rails code is not thread safe. This is not the case with other Ruby frameworks like Camping, Merb and Og + Nitro. There is a synchronized block around the calls to Dispatcher.dispatch (in dispatch.rb) rest is multithreaded. so to get any sort of concurrency in serving request we need to run multiple mongrel instances.

In my experience 128 MB RAM is required to run single instance of mongrel server. which means you should not run more than 8 mongrels on your 1 GB RAM VPS. If the rails could be thread safe it would require lot less server resources to deploy rails with mongrels.

Thursday, June 28, 2007

Ignoring common exceptions in exception_notification plugin

Exception Notification is a great plugin, that helps to you to get trace of exception on your app running in production mode. Without this plugin you probably would have to SSH to production machine and tail the production.log file to get last exception trace which is extremely inconvenient to do. FTP to get to production.log is also an option but production.log files tend to become too large. only problem is that you may get too many emails form this plugin especially when you have just launched your site in production mode.

some of the exception are not too much intresting like typical ActiveRecord::RecordNotFound exceptions, To ignore these kind of trivial exceptions you must overide it in rescue_action_in_public method of your application.rb file.

Here is how you do it:



def rescue_action_in_public(exception)
case exception
when ::ActiveRecord::RecordNotFound,
::ActionController::UnknownController,
::ActionController::UnknownAction,
::ActionController::RoutingError
render_404
else
render_500
deliverer = self.class.exception_data
data = case deliverer
when nil then {}
when Symbol then send(deliverer)
when Proc then deliverer.call(self)
end
ExceptionNotifier.deliver_exception_notification(exception, self, request, data)
end
end

Sunday, June 24, 2007

Capistrano 2 and custom SCM modules

I was using Capistrano 2 to deploy our latest project, as we had our SVN repository behind the corporate firewall and was not accessible remotely. I had originally planned to use a custom SCM module for local svn access.

I discovered that custom SCM modules are not supported at the moment in Capistrano 2.

If there are any workarounds i would be interested to know about them

Friday, March 16, 2007

STI vs. Polymorphic association

This is a common to have join between two tables based on condition. suppose we have table in database called comments and we can have comments on different thing like a video, profile or picture. So keeping DRY (Don’t repeat yourself) principle in mind while designing your database. You may want to have relationship between single comments table and videos or profiles table.

At database level you should have two fields in table one field (i.e. type) that identifies the type of comment whether it is a comment on video or it’s a comment on profile, and another field (i.e source_id) that contains id of the video or profile that comment was on.

In Ruby on Rails currently there are two ways to define this kind of association between your activerecord models:

Single Table Inheritance:

Here you ‘ll create a single table of comments and Comment AR class, there would be two additional classes ProfileComment and VideoComment inheriting from same Comment AR class. Instead of having association between Profile and Comment model there would be association between Profile and ProfileComment subclass. Same will be the case with Video model and VideoComment subclass.

If we take a look at comment table we ‘ll see that class name for each record will be automatically stored in type field. The reference to associated table would be in source_id field.


class Comment < ActiveRecord::Base
end
class VideoComment < Comment
belongs_to :video, :foreign_key => “source_id”
end
class ProfileComment < Comment
belongs_to :profile, :foreign_key => “source_id”
end


Polymorphic Association:

Since Rails 1.1 there is a simpler way to create this kind of relationship called polymorphic association. In case of polymorphic association you ‘ll have two fields called commentable_type and commentable_id, instead of type and source_id. The commentable_type field will store name of class which that instance relates to and commentable_id saves the reference to instance of that class. The relations will be created like this:


class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Video < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Profile < ActiveRecord::Base
has_many :comments, :as => :commentable
end

Pros and Cons:

  • The STI approach offers more flexibilty by allowing you to have additional fields that only have value in case of one sub class. For access from other sub class can be disallowed be overridden accessors.
  • The STI requires you to create a seperate class to implement a relation between two models, resulting in more classses. which is not case with polymorphic association
  • The STI results in more code.It is confusing to some programmers to understand relation between STI classes
  • The polymorphic association is very easy to implement.

Thursday, March 15, 2007

Using Net::https with Hpricot to parse html

My rails app that accessed sites to extract images from web pages started throwing this error (OpenSSL::SSL::SSLError). I was using open-uri to fetch pages.

I changed my code to use Net::https to fetch pages over SSL. Here is sample code to access a web page and print it contents to terminal over SSL.


require 'rubygems'
require 'hpricot'
require 'uri'
require 'net/https'


url = "https://www.orkut.com/GLogin.aspx?done=http%3A%2F%2Fwww.orkut.com%2F"

url1 = URI.parse(url)

http = Net::HTTP.new(url1.host, url1.port)
http.use_ssl = true

req = Net::HTTP::Get.new(url1.path)

res = http.start do |http|
http.request(req)
end

puts res.body