Friday, May 30, 2008

active_scaffold Woes

I recently used this plugin in my current project to build the admin interface. It works great but I faced an interesting problem that i would like to share with an example.

class Order < ActiveRecord::Base
has_many :products
end

If you see the page generated using scaffolding for the Order model you will see some links to the products in one of the columns for each Order (provided you have included products as one of the attributes in the scaffolding configuration). Lets say you are not much interested in those links, you just want the count of products. You can use active record field overrides to achieve this by putting a helper method in your OrderHelper

module OrderHelper
def products_column(record)
record.products.size
end
end

For a small number of records it works well but as the number grows it becomes very slow because of the join query it makes behind the scenes and for a few thousand records it may actually hang your database server for a while.

So to avoid this, there is a simple way out, just use the virtual attributes. Create a virtual attribute for the Order model that returns the product count and include that as an attribute in the active scaffolding.

Tuesday, May 6, 2008

RMagick Tricks

Kudos to this great library but sometimes you are stuck with certain tasks where you have to look for some workarounds.
One of the common tasks is to wrap the text on in image.
You can accomplish it very well like this

image = Image.read("caption: text goes here")

You can specify other arguments by setting Image::Info attributes in the optional block like this

image = Image.read("caption: text goes here") do
self.size = "200x"
self.pointsize = 20
self.font = "Tahoma"
end
But the Image::Info class is a bit restricted e.g you can't set the font weight, style and a lot more things that you can do you using the Draw class.
So the best workaround is to insert "\n"s into the text.
To do this create your draw class object and call its method get_type_metrics and pass it the text and the image where you want to draw the text or any temporary image.

# create draw object
draw_title = Magick::Draw.new
# set the attributes
draw_title.stroke('transparent')
draw_title.font_family('Georgia')
draw_title.pointsize(17)
draw_title.font_stretch(Magick::UltraCondensedStretch)
draw_title.font_style(Magick::NormalStyle)
draw_title.font_weight(500)
draw_title.fill = '#000000'
tmp_img = Magick::Image.new(600,600)
tmp = draw_title.get_type_metrics(tmp_img, "You text goes here").

You can easily find where to put the "\n" by looking at tmp.width.