Archive for July, 2008

Rails 2.1 SWFUpload Example

Thursday, July 31st, 2008

There’s been a few posts lately on getting SWFUpload working with Rails 2.1, attachment_fu and the restful-authentication plugins.

To try and make things easier, I’ve made a sample - albeit basic - Rails application to show other people how I managed it.

I’ve created a project on Github to host it, feel free to check it out and let me know how you get on. The only instructions you should need are in the README file, but feel free to leave comments here if you do need a hand.

A Ruby/Rails interface to Mailbuild API

Thursday, July 24th, 2008

I’m pleased to announce the release of the first version of my Mailbuild API interface, which I’m distributing as a Rubygem.

To make it easier to figure out how to use it, I’ve also created a fully functional Rails application which demonstrates all the API calls available.

To use it all you have to do is grab a copy from subversion…

svn co http://mailbuild.rubyforge.org/svn/rails_mailbuild_example/

… make sure you have the mailbuild gem installed …

cd rails_mailbuild_example
# OS X/Linux users may have to prefix this with sudo
rake gems:install

… and edit config/initializers/mailbuild.rb, adding your own API key, List ID and sub-domain.

# You can get this information from your Mailbuild admin
Mailbuild.api_key = ''
Mailbuild.list_id = ''
Mailbuild.subdomain = ''

Hopefully that’s all there is to it, but if you run into any problems feel free to add a support request or bug report on Rubyforge.

Make Rails Engines 2.x reload in development mode

Wednesday, July 23rd, 2008

UPDATE: I’ve since stopped using this method. While it did allow for everything short of library files to be reloaded between requests, making the development process far less painful, I ran into a problem with ActiveRecord where deeply-nested (3 associations) models were behaving strangely on reload (they’d work fine first time, but not afterwards).


Since moving to Rails/Engines 2.1, I’ve been irritated with having to restart Mongrel each time I make a change to a controller or model in my engine. This wasn’t an issue in Engines 1.2 as it had a load of custom initialisation code, but with 2.x moving closer to the way Rails itself works - see this post on the rails plugin initialization process by Rick Olson for more details - it’s become a problem.

Unfortunately the solution Rick proposed in his post wasn’t working for me, but a thread on the Engines development mailing list has provided a solution - add the following to the init.rb file of your engine and you’ll no longer have to restart your web server to see changes in your files.

I’ve wrapped the code in a check to see if we’re running in the development environment, as in the majority of cases you’ll want things to work as normal in production.

if Rails.env == 'development'
  Rails::Plugin.class_eval do
     def reloadable!
       load_paths.each { |p| Dependencies.load_once_paths.delete(p) }
     end
  end
 
  reloadable!
end

Internationalisation in edge Rails

Wednesday, July 23rd, 2008

After the announcement yesterday that Rails 2.2 will have support for internationalisation (i18n) in the core, I read the linked articles and was slightly surprised that rather than unifying/replacing the i18n plugins currently available, it will actually provide an API which makes creating a back-end for handling your locales easier.

I’ve been using Globalite in the Rails project I’m working on and while it’s the best solution I’ve tried, I was always frustrated by the use of YAML for it’s locale files. Thankfully the changes in Rails 2.2 will likely mean a move to pure Ruby locale files, introducing the benefits of namespaces and the ability to override/extend generic files with site-specific ones.

Now we just have to wait a few months for the release and see what plugins adapt/appear to take advantage of it.

Configuring MySQL to use UTF-8

Tuesday, July 15th, 2008

A project I’m working on at the moment is going to have multiple language options available, not all of which use the same alphabet (e.g. Russian and Chinese).

To lessen the pain commonly associated with internationalisation on the web, it’s beneficial to use the UTF-8 character set. This short summary from the Unicode Consortium may help explain better;

Unicode provides a unique number for every character, no matter what the platform, no matter what the program, no matter what the language.

Unicode enables a single software product or a single website to be targeted across multiple platforms, languages and countries without re-engineering. It allows data to be transported through many different systems without corruption.

Thankfully MySQL has supported Unicode for quite some time now, even if it’s not configured to use it by default.

First, let’s check what our settings are at the moment;

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.01 sec)
mysql> SHOW VARIABLES LIKE 'character_set%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     | 
| character_set_connection | latin1                     | 
| character_set_database   | latin1                     | 
| character_set_filesystem | binary                     | 
| character_set_results    | latin1                     | 
| character_set_server     | latin1                     | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

That’s to be expected, but it’s not really what we wanted.

Find your MySQL configuration file (on most *nix system it’s /etc/my.cnf) and make sure it’s got the following statements under the relevant headers.

[mysqld]
default-character-set=utf8
default-collation=utf8_general_ci
character-set-server=utf8
collation-server=utf8_general_ci
init-connect='SET NAMES utf8'
 
[client]
default-character-set=utf8

Restart MySQL and make sure it’s working;

service mysql restart
mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+-----------------+
| Variable_name        | Value           |
+----------------------+-----------------+
| collation_connection | utf8_general_ci | 
| collation_database   | utf8_general_ci | 
| collation_server     | utf8_general_ci | 
+----------------------+-----------------+
3 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'character_set%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       | 
| character_set_connection | utf8                       | 
| character_set_database   | utf8                       | 
| character_set_filesystem | binary                     | 
| character_set_results    | utf8                       | 
| character_set_server     | utf8                       | 
| character_set_system     | utf8                       | 
| character_sets_dir       | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

Update; Mo pointed out that it’s worth mentioning setting the charset and collation when creating tables too (good point!).

Here’s an example from the MySQL CREATE TABLE syntax docs;

CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci);

Testing is overrated

Saturday, July 12th, 2008

But the truth is, no single technique is effective at detecting all defects. We need manual testing, peer reviews, usability testing and developer testing (and that’s just the start) if we want to produce high-quality software.

Ignoring the (playfully) sensational headline, this is an insightful quote from a good article on not overstating the importance of automated testing at the expense of other QA techniques.

Informal design and code reviews is something I’d love to introduce at work, as I firmly believe they’d not only increase the quality of the end product but also our skills as individual programmers.

Testing is overrated at Rails Spikes.

Multiple users with svn+ssh

Friday, July 11th, 2008

Following on from my last post on moving from svnserve to svn+ssh, I had to then get this setup working for multiple users. This is how I achieved it on CentOS 5.2, hopefully it’ll prove useful for someone else.

This is based on a tutorial I found on the subversion dev mailing list.

# We need a group for our svn users
groupadd svnusers
 
# Add the users
useradd svn -g svnusers # this is the svn 'admin' user
useradd user1 -g svnusers
useradd user2 -g svnusers
useradd user3 -g svnusers
useradd user4 -g svnusers
# … etc
 
# Edit each svn user's .bashrc file, e.g.
su - user1
nano -w .bashrc
 
# Add the followng line to the bottom
umask 002 # allow user + group to write, no other. 
 
# Create the dir where we're storing the repo (as root)
mkdir -p /usr/share/subversion/repositories
 
# Set permissions on our new dir
chown -R root.svnusers /usr/share/subversion/repositories
chmod -R u+wrx,g+wrx,o-wxr /usr/share/subversion/repositories
chown -R root.svnusers /usr/share/subversion
 
# The following may be overkill
# chown -R root.svnusers /usr/share
 
# Rename the original svnserve command into svnserve.bin 
mv /usr/bin/svnserve /usr/bin/svnserve.bin
 
# Create a new svnserve file
nano -w /usr/bin/svnserve
 
# Paste the following into nano and save as svnserve
#!/bin/sh 
# wrap in order to put root in by default 
# Script implemented by Adrian Robert <arobert @cogsci.ucsd.edu> 
exec /usr/bin/svnserve.bin -r /usr/share/subversion/repositories "$@"
 
# Make our svnserve wrapper executable
chmod u+wrx,g+rx-w,o+xr-w svnserve
chmod u+wrx,g+rx-w,o+xr-w /usr/bin/svnserve
 
# Log in as the svn user
su - svn
 
# Create our repos
svnadmin create /usr/share/subversion/repositories/projects
cd /usr/share/subversion/repositories/projects/conf 
 
# Edit the repo conf
nano -w svnserve.conf
 
# Add the following under the [general] header
anon-access = none
auth-access = write

Moving from svnserve to svn+ssh

Wednesday, July 9th, 2008

After mentioning that I was using svnserve, a friend sent me a twitter message asking why I wasn’t using svn+ssh, so I thought I’d have a look. It turned out to be really simple to make the move, and I’m left with a nicer setup than before.

Firstly, let’s kill the running svnserve process as we’re not going to be using that anymore.

[user@server ~]$ ps aux | grep svn
user     2495  0.0  0.3  45856   940 ?          Ss    20:02   0:00 svnserve -d -r repository/
user     2501  0.0  0.2   3936    724 pts/0     S+   20:02   0:00 grep svn
[user@server ~]$ kill 2495

If you’ve specifically opened port 3690 (which is the default svnserve port) in your firewall you should close that again now. You can check your current firewall ruleset using the list flag.

[user@server ~]$ iptables --list

I happen to run ssh on a non-standard port, so to save myself having to specify this each time I’ve overridden the default tunnel subversion has setup for ssh. This stage is run on your local machine (or where you want to check out your repository).

local:~ cameron$ nano -w .subversion/config

Under the [tunnels] section, I added the following line. Note that XXXX is where my non-standard port is specified, and REMOTEUSERNAME is the username I’m using to connect to the server to checkout my repository. The -C flag enables compression, and seems to greatly speed things up.

ssh = /usr/bin/ssh -p XXXX -l REMOTEUSERNAME -C

Okay, so let’s try and check something out! I’m hoping you have ssh keys configured already, but if not here’s an SSH Keys Howto. Note you have to specify absolute paths now.

local:~ cameron$ svn co svn+ssh://yoururl/path/to/repository/trunk
A    trunk/wp-config.php
A    trunk/wp-pass.php
A    trunk/wp-rss.php
…

With any luck, that’ll checkout your repository.

If you already have a repository checked out and don’t want to delete it and checkout again, there’s a solution for you too. Change into your local working copy and run the following;

local:projects cameron$ svn switch --relocate svn://yoururl/repository/trunk svn+ssh://yoururl/path/to/repository/trunk

My Bloody Valentine

Sunday, July 6th, 2008

Went to see My Bloody Valentine at the Barrowlands with Sarah and my ears are still recovering. The following video is from a section of the gig that came in the middle of their last song, and is called ‘the holocaust’.

 

 

Candy Cigarette by Sally Mann

Tuesday, July 1st, 2008

The attitude, the pose, the fake cigarette… brilliant.

Via ffffound, photo by Sally Mann.