Satya's blog - 2007/12/

Dec 16 2007 15:39 Annotating images with Imagemagick

Stick the following code in a shell script to put a text label into an image:

convert -density 100 -pointsize 12 -background '#00000066' -fill white \
label:" $1 " \
-strokewidth 8 \
-geometry "+10""+10" \
miff:-|\
composite -compose atop -geometry "+10""+10" - $2 $3

echo $2

Put it in a file "annotate.sh" and call it:
sh annotate.sh "the text" inputfile.jpg outputfile.jpg

Tag: howto

Dec 06 2007 18:06 Ruby on Rails validations

We all know how to validates_presence_of in Rails, right? You can also override the error_messages_for in your helper to customize the errors. Just paste in the source from http://api.rubyonrails.com/ and start hacking. Make sure it's validating the presence of (model)_id, if it's a lookup table column.

Want to make sure a number of lookup table values actually exist? Say you have a number of columns which are drop-downs, whose values come from lookup tables and you're just storing the lookup IDs ((model)_id) in the previous paragraph) in your "main" table. You can do this:

    validates_each :employer, :type_of_injury_code, :cause_code do |r,a,v|
        check_inclusion_in_list r,a,v
    end

    def self.check_inclusion_in_list(record,attrib,value,model=nil)
        if model.nil?
            model=attrib.to_s.titleize.camelize.gsub(" ","").constantize
        end
        unless value.nil?
            begin
                model.find(value)
            rescue ActiveRecord::ActiveRecordError
                record.errors.add attrib, 'must be selected from list'
            end
        end
    end

The validates_each statement is standard rails; it passes the record, attribute, and value to the block. Here, the block calls check_inclusion_in_list. That function gets the model name based on the attribute name like so:
:cause_code.to_s becomes "cause_code",
"cause_code".titleize becomes "Cause code",
"Cause code".camelize becomes "CauseCode",
the gsub gets rid of spaces, and constantize finds a suitable constant, in this case, the model CauseCode. We can drop the titleize and gsub calls, I forget why they're there.

Next, we run find(value) on the model, and if it can't find record with the given id, an exception is raised and caught, and we add to the record's error stack. Note that a nil value causes this validation to succeed -- you must validates_presence_of :cause_code_id separately!

Tag: rails howto

Dec 02 2007 10:11 Visa site broken, says Bluesmoon
Bluesmoon says the vfs-visa web site, which is a thing in India for applying for visas at the consulate, is broken. He lists the reasons why, and he tells us that they refuse to fix it or even understand the problem. Go read his blog post to see why they're living 9 years in the past and how they're screwing over innocent people. Unfortunately they're not the only ones, there are plenty of other web sites that require some ridiculous old malware to run, including lowering your shields (i.e. turn on javascript, flash, activex), and a ridiculous resolution (who tf runs at 800x600 this century?). Hello? 1992 called, it wants its web design back. And Jacob Nielsen called, he wants to boot you off the web.

Last updated: Dec 02 2007 11:43

Tag: rant

Dec 01 2007 23:02 Rails has_many :through

There are any number of blogs out there that will tell you how to do simple :through associations in Ruby on Rails. None of them will tell you how to set up checkboxes to populate and manage this many-to-many relation.

Suppose you have a model, 'rumor', which can have zero or more categories. Yes, this is basic acts_as_taggable functionality. Well, your form can have the following code, where you iterate over the categories and for each one, set up an input checkbox.

<% @categories.each do |t| %>
<input id="rumor_category_ids_<%= t.id -%>" name="rumor[category_ids][]" type="checkbox" value="<%= t.id -%>" 
<% if @rumor.categories.include?(t) %>checked="checked"<% end %> /> 
<label for="rumor_category_ids_<%= t.id -%>"><%= t.name %></label> 

The checkbox id attribute is simply parent model name, then the category_id column name pluralized (since it's an array of checkboxes) and the category id attribute's value. Example, rumor_category_ids_1. The name attribute follows rails convention, too: the parent model (rumor), the foreign key pluralized (category_ids) to indicate that it's an array, and an empty bracket to show where the IDs would go, in a semi-metaphorical way. So we get the array of IDs of the checked categories as params[rumor][category_ids] in our controller. the value attribute is, of course, the lookup table's (category, here) id attribute.

Since this could be the display of an existing record, we check the checkbox if the existing object (@rumor)'s categories include the current category of the loop (t). And the last line, we have a nice clickable label.

Last updated: Dec 06 2007 14:00

Tag: rails howto