Friday, August 17, 2007

Turning off echo in the Ruby console

Finally found the info, so keeping it here for the record:

In .irbc:


module IRB
def self.echo_format
conf[:PROMPT][conf[:PROMPT_MODE]][:RETURN]
end

def self.echo_format=(str)
echo_format.replace(str)
end

def self.echo_on
self.echo_format = "=> %s\n"
end

def self.echo_off
self.echo_format = ''
end
end


Then in the console:


>> IRB.echo_off

Wednesday, May 30, 2007

Mongrel, Capistrano and Rollbacks

In the deployment chapter of the Agile Web Development with Rails book, (27.5 Setting up a Deployment Environment), they use mongrel_rails cluster::configure to generate a mongrel_cluster.yml config file. There is a problem though, with this generated config file, as is points to a PID file using a relative path log/mongrel.pid. The problem shows up when doing a rollback...

When rolling back with Capistrano, the "current" directory gets relinked to the "latest - 1" release, and the latest release is deleted. This means mongrel's running directory is deleted. As a direct result, mongrel cannot find log/mongrel.pid anymore. So when capistrano restarts the mongrel servers, they fail to delete their PID files. Because log/ is a shared folder between all the releases, upon restart of the "latest - 1" release, mongrel finds stale PID files in there and refuses to start.

The solution is simply to use fully specified paths for the pid_file in config/mongrel_cluster.yml

Tuesday, May 29, 2007

Hammering localized dates into Ruby's strftime

Ruby on Rails in not really built with internationalization in mind. So here is a quick and dirty monkey patch to hammer Japanese date locales into place. Add it to your environment.rb. Note the use of .replace instead of a simple =. This is to avoid Ruby's warning about reassigning an already initialized constant.

Date::ABBR_DAYNAMES.replace %w(日 月 火 水 木 金 土)
Date::DAYNAMES.replace %w(日曜日 月曜日 火曜日 水曜日 木曜日 金曜日 土曜日)
Date::ABBR_MONTHNAMES.replace %w(1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月)
Date::MONTHNAMES.replace %w(一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月)
class Time
alias :strftime_nolocale :strftime
def strftime(format)
format = format.dup
format.gsub!(/%a/, Date::ABBR_DAYNAMES[self.wday])
format.gsub!(/%A/, Date::DAYNAMES[self.wday])
format.gsub!(/%b/, Date::ABBR_MONTHNAMES[self.mon - 1])
format.gsub!(/%B/, Date::MONTHNAMES[self.mon - 1])
self.strftime_nolocale(format)
end
end

The original Japanese site this was based on is now 404, but for a more complete (true internationalization) solution involving gettext check this page. If localization is all you are after, the above should work just fine.

Saturday, May 26, 2007

Getting RadRails to work under Ubuntu, or how to work around the path requirements of the latest beta of RadRails

I was really looking forward to the latest beta of RadRails (released on May 15 2007), as it fixed the various "Run all (unit, functional, integration and all) tests" functions that were broken in the stable release. So I installed it as soon as it came out, but quickly discovered that a configuration page (that used to contain executable paths settings) had been removed...

The paths are now all derived from the location of the ruby executable. This places an unnecessary strong requirement on the way Rails and Rake are installed, and breaks as soon as you have a setup that the RadRails people consider "non-standard". This happens to be the case under Ubuntu, a pretty popular Linux distribution, currently ranked no less than #1 on distrowatch.com ;-)

I mentioned the above in this thread on the Aptana/RadRais forums, and thanks to Chris Williams prompt replies, we could get the problem acknowledged and fixed quickly. So, a fix should already be in CVS, but until it gets released, here is a clean (in the sense that it does not dirty up your /usr/bin) workaround under Ubuntu:

cd /usr/local/bin
sudo ln -s /usr/bin/ruby ruby
sudo ln -s /usr/bin/ri ri
sudo ln -s /usr/bin/rdoc rdoc
sudo ln -s /var/lib/gems/1.8/bin/rails rails
sudo ln -s /var/lib/gems/1.8/bin/rake rake

After these symbolic links have been prepared, add a Ruby interpreter (Windows > Preferences > Ruby > Installed Interpreters) with a home directory of /usr/local. If things still don't work after that, verify that, in the installed interpreters list, this /usr/local one is indeed the one with the check mark.

Ruby on Rails and SQL Server 2005, or how the database adaptor mishandles DateTime values before 1970 and after 2038

I almost hit a show stopper on a client's project yesterday. We needed a Ruby on Rails application to interface with their data warehouse that runs on SQL Server 2005. We did some initial testing, and we could connect to it fine, so we went ahead and started development... only to discover later down the line that a serious bug prevents us from using the actual data!

We were quite concerned when we found out that it is a known bug, opened over a year ago in the Ruby on Rails tracker, with a high priority and major severity, yet still not fixed. A tentative patch is provided, but reportedly, it does not apply properly. And in our case, even after applying it manually, it still would not work.

Luckily, we managed to get things working with a slight modification, and wrote a monkey patch for it. Here is the code, to include in your environment.rb (You do not need the fix from the bug tracker: it is included in this monkey patch). Insert usual disclaimers here (use at your own risks, yadda yadda...):


# Monkey patch fix to bug #3430
# See http://dev.rubyonrails.org/ticket/3430
# This is adapted from the patch on that page, with
# a slight modification to make it actually work.
class ActiveRecord::ConnectionAdapters::SQLServerColumn

def type_cast(value)
return nil if value.nil?
case type
when :datetime then cast_to_time(value.to_s)
when :timestamp then cast_to_time(value)
when :time then cast_to_time(value)
when :date then cast_to_date(value)
when :boolean then value == true or (value =~ /^t(rue)?$/i) == 0 or value.to_s == '1'
else super
end
end

def cast_to_date(value)
Date.new cast_to_time(value)
end
end

Friday, May 25, 2007

Getting to_yaml to generate proper UTF-8 and not "!binary"

The linked article (in Japanese) contains a fix that lets YAML handle multibyte characters properly. This can be very useful when generating test fixtures from existing data. Here is a quick summary if you do not read Japanese:

By default, YAML does not support multibyte characters:

>> puts "あ".to_yaml
--- !binary |
44GC

Changing YAML's default encoding, or passing an :Encoding to the to_yaml call did not help.

The author wrote a monkey patch, that among other things, patches the String base class... Hmm, scarry... But it seems to work, as the following test shows:

>> puts [["あ", "い"], {"う" => ["え"]}, Struct.new(:name).new("お")].to_yaml
---
- - "あ"
- "い"
- "う":
- "え"
- !ruby/struct:
name: "お"


Also, some helpful Japanese fellow has created a Rails plugin for this fix. Here are the links to the SVN repository, for the 0.1.0 release, and the trunk.

Ajax Progress Indicator Generator

Downloading free ajax load indicators, GOOD! Generating custom ones that match exactly your site's color scheme, BETTER! And the generated gifs are of course totally free for use.

I used the tool before and it was already great, but the newer version (release last month) is even better, with 7 new types to choose from, a preview in the selection list, and an integrated color picker!

Many kudos to Yannick Croissant for this nice tool.

Ruby function timer

For quick performance tests, I often need to time the execution of some function. Here is a short function to do it in Ruby:

def time_func(&block)
start_time = Time.now
yield
end_time = Time.now
return end_time - start_time
end

Usage is straightforward:

time_func do my_test_function(args...) end

Thursday, May 24, 2007

Quick copy-pastable SQL query to check PostgreSQL locks

We recently faced some lock-related issues with PostgreSQL (due to the "serializable" transaction isolation level we are using), resulting in processes locked in an INSERT WAITING state, and an unresponsive web frontend. The database itself was fine though, so we did some pocking around using psql in order to find the source of the lock. A simple select * from pg_locks; shows only not so helpful OIDs. It is of course straightforward to get meaningful names, it is just a pain to type it every time, so here is the quick copy-paste ready version we used during this debugging:


SELECT
c.relname,
l.transaction,
l.pid,
l.mode,
l.granted
FROM pg_locks AS l
LEFT OUTER JOIN pg_class AS c
ON l.relation = c.oid
ORDER BY l.pid, l.granted, c.relname;

Wednesday, May 23, 2007

Quick Python script skeleton generator

A friend sent me this useful little script to get a quick skeleton code for small Python shell scripts. Perfect when writing quick filters.


#!/usr/bin/python
"""
pskel

A Python skeleton maker for shell scripts
"""


print '''
"""
APPNAME

APPDESCRIPTION


Usage:
APPUSAGE

Synopsis
SYNOPSIS
"""

import sys
import getopt

def main():
#Parse command line options
try:
opts, args = getopt.getopt(sys.argv[1:], 'h', ['help'])
except getopt.error, msg:
print msg
print "for help use --help"
sys.exit(2)
#Process options
for o, a in opts:
if o in ["-h", "--help"]:
print __doc__
sys.exit(0)
#Do the rest here
if o == '-v':
#handle options
pass
#Process arguments here
#Call Processing methods here

if __name__=="__main__":
main()
'''

UnixODBC on Ubuntu Feisty

Here is what we did on Ubuntu Feisty, to get unixODBC to work and connect to an SQL Server instance.

export ODBCINI=/etc/odbc.ini
export ODBCSYSINI=/etc
sudo apt-get install freetds-dev libdbd-odbc-ruby unixodbc-dev sqsh tdsodbc

After that, following the setup (from the setting of /etc/freetds/freetds.conf) of the wiki page worked like a charm. Or almost: the test with isql did not work too well, as we could not execute any sql statement and kept getting [ISQL]ERROR: Could not SQLPrepare errors... But the test in the interactive Ruby shell did work, and our Rails application can now use SQL Server just fine.