Potential gotcha with test setup in Rails 2.0

Wednesday, December 05

UPDATE 2: This is now fixed in Rails trunk.

UPDATE 1: Josh Peek has already created a patch that prevents this gotcha. Read the patch and give it a +1 on the Rails Trac if you’re so inclined: http://dev.rubyonrails.org/ticket/10382.

Rails 2.0 introduces a new (better) way to create your functional test cases. Instead of subclassing Test::Unit::TestCase directly, you can now subclass ActionController::TestCase, which will take care of the setting up the request/response environment for you. Here’s what a Rails 2.0 functional test might look like:

require File.dirname(__FILE__) + '/../test_helper'

class AuctionsControllerTest < ActionController::TestCase
  def test_should_require_login_for_create
    assert_login_required 'create'
  end
  # ...
end

Now, suppose you’re using the setup method to prepare a few things before each of your test methods run. You may remember that prior to this change, each functional test needed to define its own setup method in which it created a controller instance, and instances of TestRequest and TestResponse. Well, it still does. Only this setup method is moved to the new superclass, saving you the typing.

And therein lies the gotcha: if you go ahead and create your own setup method not realizing that you’ve inherited one, you’ll clobber the one defined in the superclass. So, when you’re defining your own setup method, remember to call the original one using super:

require File.dirname(__FILE__) + '/../test_helper'

class AuctionsControllerTest < ActionController::TestCase
  def setup
    super
    @current_user = login_as(:amy)
  end

  def test_should_require_login_for_create
    assert_login_required 'create'
  end
  # ...
end

Hopefully this will save you the 15 minutes I spent trying to figure out why this wasn’t working.

Seed Data in Rails

Friday, November 16

Someone asked me about this the other day, so I thought I’d write about it. In some of my applications, I need to “seed” the database with data. This might be a list of categories, sections, or other defaults.

There are a couple of ways you can do this. One way is to use migrations. You create records in your migration via ActiveRecord as you normally would, and when you run your migrations, the data is inserted. This works OK, except it obscures the location of the data. By the time you have a lot of migrations, you’re unlikely to remember that 003_create_categories.rb is also the place where you’re adding your default categories.

I like to think of migrations as being transient. As your schema grows and your project evolves, the chances of your migrations running perfectly from top to bottom diminish. When bootstrapping a database, it’s a much better idea to load the entire schema via db:schema:load than running through each transformation with migrations.

So, if we’re not using migrations for seed data, where do we keep it? I like to use YAML fixtures for this. You could use the test fixtures from test/fixtures, but this is an inappropriate location. If you were a new developer coming on to a project, why would you think to look in the test directory for seed data? Test fixtures are for your tests.

For seed data, I create a fixtures directory inside the existing db/ directory: db/fixtures. Then I use the following Rake task, called db:seed to load them:

namespace :db do
  desc "Load seed fixtures (from db/fixtures) into the current environment's database." 
  task :seed => :environment do
    require 'active_record/fixtures'
    Dir.glob(RAILS_ROOT + '/db/fixtures/*.yml').each do |file|
      Fixtures.create_fixtures('db/fixtures', File.basename(file, '.*'))
    end
  end
end

So, I might have something like db/fixtures/categories.yml. When I’m bootstrapping the project on a new machine (say, when deploying), I’d just do the following:

$ rake db:create:all
$ rake db:schema:load
$ rake db:seed

How are other folks out there dealing with seed data?

IRB History and Completion

Saturday, June 09

Found this on the RubyGarden wiki and it totally made my day. To get persistent history rocking in IRB, add the following to your .irbrc.

require 'irb/completion'
require 'irb/ext/save-history'
ARGV.concat [ "--readline", "--prompt-mode", "simple" ]
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history" 

Note that this will also add tab completion.

Two Things I didn't know about TextMate

Friday, January 20

The TextMate Manual was recently published and I made some time today to go through it. I always seem to work with an editor for far too long before I realize there’s some handy shortcut I’ve been ignorant of. Anyways, an editor like TextMate is full of these hidden gems—clever macros and commands that make life easier. Here are a couple of things I didn’t know.

CMD-T: Go to File

Until this moment, I had no idea the ‘Go to File’ window existed, let alone its CMD-T shortcut. I hate taking my hands off the keyboard to click on files in the project drawer, so the ‘Go to File’ command makes my day. It opens a window containing a flat list of all the files in your project, with a live, abbreviation-enabled search.

[This] window lists all text files in the project sorted after last use, which means pressing return will open (or go to) the last file you worked on. So using it this way makes for easy last-recently-used switching.

From 2.3 Moving Between Files

CMD-Return: Save some keystrokes

You know how when you type an auto-paried character, like a quote, or a brace, your caret ends up in between the pair? Well, this is generally useful, but really sucks when you’re at the end of a line because you have to move all the way to the end before making a carriage return. You can imagine my excitement when I learned about CMD-Return. CMD-Return will move to the end of the line and insert a newline for you. How great is that?

From 4.1 Auto-Paired Characters

Sweeping strategies in Rails

Monday, January 09

The caching mechanism in Rails is delightfully simple: add a caches_page declaration for a given controller action and a static copy of the rendered view is automatically saved to disk. Subsequent requests for the page are served without invoking Rails. As many have noted, sweeping the cache can be a pain.

Enter two recent articles that discuss some practical sweeping strategies: Lazily sweeping the whole Rails page cache from Thijs van der Vossen, and Rick Olson’s Referenced Page Caching

Both strategies advocate relocating the cache directory to a subdirectory of public (i.e. public/cache), a brilliantly simple solution that makes complete expiry of the cache trivial. I especially like Thijs’ laziness: FileUtils.rm_r(self.page_cache_directory)

Enable CPU frequency scaling in Ubuntu 2

Thursday, November 24

I’ve been using the CPU frequency monitor applet in Gnome to see the speed at which my Pentium-M chip is running, and noticed that it rarely gets up to the 1.6Ghz that it’s capable of. While I tend to prefer the dynamic scaling behaviour when running on batteries, when I’m plugged in I want top processor performance.

I did a little digging and found the answer (where else), in the README (/usr/share/doc/gnome-applets-data/README.Debian). It turns out that the cpufreq applet ships with the SUID bit unset (for security reasons), but you can enable it using by reconfiguring using dpkg-reconfigure:

$ sudo dpkg-reconfigure gnome-applets

Just choose ‘Yes’ to set the SUID bit for the cpufreq-selector executable and you’ll be able to left-click on the applet and set the the CPU frequency manually.

.vimrc

Thursday, November 24

Since I won’t have my iMac for a while, I’ve had to give up my beloved Textmate. In its absence, I’ve been doing most of my Ruby programming in console VIM. Since I’m tired of having to recreate my preferences in .vimrc every time I’m on another system, I’m archiving it here for future reference:

" no war for heavy metal
syntax on           " syntax highlighting
filetype on         " detect the filetype
filetype plugin on  " load filetype plugins

set nocompatible    " turn off vi compatiblity
set nowrap          " don't wrap long lines
set background=dark " I use a black background
set tabstop=2       " Ruby-style tabs
set number          " line numbers
set ai              " autoindent
set si              " smartindent

If you’re new to VIM or are looking for a few sensible defaults for programming, you might want to try these options (put them in ~/.vimrc). Pretty colors, syntax highlighting, line numbers, auto-indents, a small tabwidth, and a few others. Simple. Just the way I like it.

Good Things

Friday, October 28

The following things are good:

  • The Jargon File is a “a comprehensive compendium of hacker slang illuminating many aspects of hackish tradition, folklore, and humor,” which I often consult when I’m feeling less than leet.

GPG Quickstart Guide

Sunday, October 23

This is a quickstart, so let’s not waste any time. The first thing your going to need is a GPG Key, so fire up the terminal and from the command line, type:

$ gpg --gen-key

This will launch the GPG key-generation program. First you’ll be asked to select what kind of key you want: (1) DSA and Elgamal (default), (2) DSA (sign only), (5) RSA (sign only). If you want to sign and encrypt messages, DSA and Elgamal is what you want and is the default, so we’ll use that.

Next you’ll be asked to choose a keysize. A large keysize is more secure than a small one, but also takes longer for your computer to encrypt/decrypt data. The default value of 1024 is adequate, so we’ll use that. If you’re really paranoid, you can use 2048, which is currently gpg’s maximum.

You’ll then be asked to set an expiry date for your key. While expiry dates can be used for stronger security, you probably want your key to be valid indefinitely. Choose 0 (the default) to create a key that never expires and confirm your selection.

You need a user ID to identify your key. You’ll be asked for your Real Name, Comment and Email Address which will result in a user ID in this form: “Real Name (comment) <email@example.com>”. Go ahead an type in your user ID details and confirm your entry.

Finally you have to enter a passphrase. A passphrase is like a password, but is longer, can contain spaces, and is supposed to be impossible to guess. Think of a passphrase as a super-password. Use a long sentence, or a line from one of your favorite songs, spaces and punctuation included. Oh, and if you ever forget your passphrase, there is NO way to get it back.

All done? Congratulations! You now have a public and secret key in your keyring. To see all your keys, use the list-keys command:

$ gpg --list-keys

Create a revocation certificate

If you ever need to revoke this key (because, say, you forgot your long and difficult-to-guess passphrase), it helps to have a revocation certificate prepared. Right after creating a key is a good time to prepare a revocation, so let’s do it now.

$ gpg --gen-revoke packagethief > ~/revcert.asc

You’ll have to answer a few questions (the default answers are fine) and enter the passphrase you chose for your key. The above command will create your revocation certificate in the file revcert.asc. Now, keep in mind that if someone gets a hold of this revcert, they’ll be able to revoke your key and render all your encrypted messages unreadable. You probably don’t want this, so it’s a good idea to hide this somewhere OFF your computer. You could put it on another volume, save it to a disk and keep in somewhere safe, or just print it and keep it locked away in your filing cabinet. At the very least, you want to make sure that nobody except you can read it, so let’s change the permissions:

$ chmod u-w,go-r ~/revcert.asc
$ ls -l ~/revcert.asc
-r--------   1 packaget  packaget  260 Oct 23 10:30 revcert.asc

Now you (the owner) are the only one who can read the file. Note that we’ve even removed write permissions for the owner.

Using your key from within your mail program

Since most folks use a GUI-based email client like Thunderbird or Mail.app, here are some add-ins that you can use with your mail client to provide GPG functionality. These make it really easy to use GPG with your mail, adding sign/encrypt options to the Compose window and automatic decryption for encrypted messages.

  • Enigmail is an extension for Mozilla Thunderbird. If you use Thunderbird or Mozilla/Netscape, this is the cheese.
  • GPGMail is a plug-in for Apple’s Mail.app. Although its authors claim that “GPGMail is a complete hack, relying on Mail’s internal private API,” I’ve been using it for several months without issue. The latest version even has an installer.

The difference between signing and encrypting

Signing an email message using your key helps prove that the message came from you. This isn’t the same as encrypting the message, but is a common way to assert the authenticity of the sender. Your message is still sent in plain text and anyone can read it, but they can also use your GPG signature to verify your identity. I tend to sign most of the messages I send.

Encrypting is another story. To encrypt a message, you need the public key of the person to whom you are sending the encrypted message. When you use someone’s public key to encrypt a message, only the person who has the corresponding secret key can decrypt it. So, if I wanted to send an encrypted message to ‘John’, I would need his public key.

Obtaining your public key

To obtain your public key (a big block of ASCII characters that looks like garbage text), use gpg -a --export from the command line:

$ gpg -a --export packagethief

This will print your key to the screen (the -a option tells GPG to output in ASCII text). Sometimes it’s more useful to have this in a text file so you don’t have to copy/paste it. To do so, just redirect the output to a file:

$ gpg -a --export packagethief > ~/pubkey.txt

This will save your key in the file pubkey.txt in your home directory. You can now publish your key (say, on your website), so that others can use it to send you encrypted messages.

Changing your passphrase

Until today, I didn’t even know you could do this. You change the passphrase for a key by editing it. Not everything is editable (for example, you can’t change your user ID), but changing your passphrase is the kind of thing you might want to do from time to time.

$ gpg --edit-key packagethief
Command> passwd

You’ll be asked for your existing passphrase before you’ll be able to type a new one. To exit and save your changes, type quit at the prompt.

Related resources

My public key

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.1 (Darwin)

mQGiBENbnh4RBAC7s8cQhyDkow6IgfIYpkflFQ5lmK8Hlcm8AR3Jcg2IsltBY+ZG
jU/GyEwBJEsyyYxSZjy3/DVOsHMg2MGNNXE6TH0FQhpHnwgMgz2WQuyupSOnWz3o
5AI5ozBLS8+8CO8yufez6VNDsMr2nSJpwDgqCb2AN82nCkXJwtVWmZkPXwCgiOSN
fldP3ZtF6QyQXnrsCNxNUskD/jpLeCOk/VrZI2UJ8jKGMeyNZP7p/2CSo78ZpcYF
uu6Jtgtnrm2+F77ST7F5FGKTlioqeEi7Fw7j1Ve318bKfIn3hHB9E643mf6oD8FC
wb6ATIIsv2u50yqFt6k9F/oHnc6gddunTcM5ulX4+56dJXlFVL7c+PPsdkFsjLZY
kOmAA/4iQ5kmt8Fuwsep2Gs7fCQ+Wn6GmiGNwLjj/AC1IWwHdhHygPtS4xGshzvu
L5VEuxeA0/zwoEh1gNqAIe2SGFKysbXSmD8vnW+wvWJ0a9aAaCag8WiMQ4dYwKTy
NYtHjcQBwON6uGzwslyawO5WfF0zQwNGgun/0t58P0rghs7YZrQ1SmVmZnJleSBI
YXJkeSAoUGFja2FnZXRoaWVmKSA8cGFja2FnZXRoaWVmQGdtYWlsLmNvbT6IXgQT
EQIAHgUCQ1ueHgIbAwYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRCwvVj9bv2rJl/b
AJ9M2QEdxTgRj/kgg4OreczVyBMeiACfb1llQoLM0n/dp0Cb9hGbNvrHpi+5Ag0E
Q1ueJhAIAM6oQqDqkijWVSdl86PPWmV560yKUJ/hX1/OjOYKtVdbbNL6zXSTnu9Y
oB0t4RUq7E3bFHXYYOv+ndHCONE8IKv8LD58KLaO9TshyUHHH5uE1qEy0WfsBV/I
axNTETv8JYUr/kdgLMu2M/chpBmFgQEyXJBzN+iYNKmS6Py2th3xhAWmnNMtP4af
sDK/CLbf+TXkOrTn8312SuRDBVs/M95DtUEBVp0WoYhj8OPAe5uOXld2j731y4A0
fnsnldaV+prHjIwmHECHelDgti7H1lI7UkyPr92zYLU2akKgmQ+TIszn+XeNcOI+
aimSKetADgGTy+A8iuI7t6RP/rOerPsAAwUH/2jNqxWexpvH5ZGwsWI2qBl5bghz
ofzTp4yxa/dj6LuU6rLfO4Rvob0avWjy8d2+b5ABvXfRM2BkZWjGP4s8sKJ1lRUM
pGfCw9N9ouraQMXyoG+R7/ZKQhECQipBRpm1l7T0VazQ/36RUEFBj2uEOoyv8H5H
uQ/s0/FQBZX2YU49vQ7ujBiutbRdedomx3dYw3kPpI9axagjGfJBgMhMOxZa0Dt8
pXico+KYFsXu26L3bacl73vSvCiqVRZfkDC06TvelR6yx/OGzxHPo6kFtjcUYGV1
wAHwdphcKd8Fy3+Xmi/Onpq4sXlBSL9IG1EW+eBISurCNOzsT2It8OVhun6ISQQY
EQIACQUCQ1ueJgIbDAAKCRCwvVj9bv2rJha9AJ4/FxF/ECoRvlV7w5MLVHnFv3PG
tACff4IWVTIMlABOm+o6aVfYliUUHb4=
=sLot
-----END PGP PUBLIC KEY BLOCK-----

Database-agnostic dumps from mysql 1

Friday, October 21

MySql ships with a program called mysqldump for dumping table definitions and data from a database.

Usage: mysqldump [OPTIONS] database [tables]

There are a several of [OPTIONS], but when I want a nice, compact dump that I can use to create a schema definition, I use the following:

$ mysqldump -dr schema.ddl some_db --compact --compatible=mysql323,no_table_options --add-drop-table

This command results in a fairly database-agnositic schema definition in schema.ddl. There are no comments, no proprietary table or field definitions, and no data. The first option, -d, tells mysqldump to skip the data; -r tells it to output to schema.ddl; the rest of the options are verbose.

Creating new databases from this schema is painless. First, use the mysqladmin program to create a new, empty database:

$ mysqladmin create another_db;

Next, use the mysql client to execute the sql from schema.ddl:

$ mysql another_db < schema.ddl

Notes: For all three programs (mysqldump, mysqladmin, mysql), you can specify a user/pass with -u someuser -p . The commands executed will run as this user. Oh, and the -p option needn’t take an argument—you’ll be prompted for your password if you omit it.)

Kill Dash Nine

Wednesday, October 19

kill without a strength indicator is liking asking someone politely to go unconscious, while kill with a “-9” is like hitting them with a steel pipe.

from http://www.downes.ca/cgi-bin/page.cgi?post=31720

FIGlet

Wednesday, October 19

Today I came across FIGlet, a little program for making large letters (signatures, banners, etc.) out of plain text.

I think I always vaguely pictured computer nerds sitting around for days on end painfully positioning pipes and underscores to create these obscure pieces of internet art. Now I know better.

You can download and install FIGlet from http://figlet.org, but if you’re using a package manager you’ll probably find there’s a port for it.

I use Darwin Ports on OSX and installation was trivial:

$ port install figlet

Once FIGlet has been downloaded and installed, start it up by typing figlet at the CLI and then type whatever you want. Alternatively, pipe a file or the output of another command through FIGlet, or put your input right on the command line as an argument.

$ figlet Hello World!

Now, go get working on your signature.

Setting up SSH keys is easy

Sunday, October 16

You can use SSH Keys to avoid having to enter your password when you log in to a remote machine. Think of your key as being your computer’s unique thumbprint. When you ssh into another computer, your thumbprint is checked against a list of pre-authorized thumbprints and if a match is found, you’re allowed in—no password required.

If you’ve never done this before, you’ll need to create a DSA key pair (the thumbprint). You only need to do this once.

$ ssh-keygen -d

Just hit enter to accept the defaults, and leave the passphrase blank. Your public key will be saved to the file ~/.ssh/id_dsa.pub

Now that you have a key, all you have to do is copy it to the authorized_keys file on the machine you want to log in to.

$ scp ~/.ssh/id_dsa.pub username@example.com:~/.ssh/authorized_keys

Nice. Now you’ll be able to log in without your password, which is really helpful when you want to do things like schedule backups using rsync, or if you’re lazy.

Just don’t lose your laptop.

Ten tips for Rails beginners

Sunday, October 09

So, you’ve finished the TODO lists, the cookbooks, and the ubiquitous byob (build your own blog) demonstrations from the Rails tutorial canon, and you’re impressed enough to begin building your first real-life Ruby on Rails application. It’ll be easy, you think. One hour—tops. Just like in the movie.

I bet at first, things are going smoothly. You’re generating controllers and models, you’re scaffolding, adding columns to the db, some validations here, some associations there, and life is good. You take a break, go have a cigarette, even, basking in the small victory of a rapid iteration. All that’s left to do now is get the user authentication system working… you know, that common thread that runs through the entire application. Easy, you think. You’ve read about that login generator that Tobias (xal) made. That’ll work.

Some hours later, after having gem install‘ed the login generator, gotten it working, realizing that you needed ACLs, poring over the wiki reading about implementing ACLs, and deciding to sit down with a cup of coffee and ActiveRecord’s api documentation, it hits you. You don’t know a lick of Ruby.

  • Tip the first: eventually, you will need to learn Ruby.
  • Tip the third: when you generate scaffolding, Rails will always pluralize the Controller name. Don’t let it confuse you.

$ ./script/generate scaffold Person

The above will make a people controller and a Person model. This doesn't happen if you name your model and controller explicitly.
  • Tip the fourth: you will make mistakes. And when you screw up the plural/singular conventions when using generators (and you will), you can destroy output generated by generators just as easily as you can generate it:

    $ ./script/destroy scaffold Person

  • Tip the fifth: if you only want two databases for your application (i.e. when developing), in your ./config/database.yml just reference your development connection under the production section:
development:
  adapter: mysql
  database: stickball_development
  host: localhost
  username: root
  password: secret

test:
  adapter: mysql
  database: stickball_development
  host: localhost
  username: root
  password: secret

production:
  development
  • Tip the sixth: do not use TAB to indent the word ‘development’ underneath the heading ‘production’ in database.yml. Despite its outward appearance, YAML is no ordinary text file. It’s special. If you find yourself getting an error like /usr/lib/ruby/1.8/yaml.rb:119:in `load': parse error, you might have TABs. Spaces are the answer.
  • Tip the eighth: you should subscribe to the mailing list. You will learn a lot in there. Oh, and search the archives before you post anything to see if your question’s been answered already. Or, you can just lurk, always reading - never posting - waiting for someone else to ask your question, just like you did in high school and at supper.
  • Tip the ninth: learn to look under the hood by running irb from inside your development environment. From your Rails application directory, run

$ ./script/console

and watch Rails load your environment up for you. Now you have access to all your Models and can do things like person = Person.find(:first) and anything else you might do in your Controllers.
  • Tip the tenth: watch your development.log file while running your application. Rails’ logging for the development environment will show you every sql query issued by ActiveRecord, every Action, and every View rendered, along with statistics.

$ tail -f ./log/development.log

As you watch the ActiveRecord queries scroll past, think quietly to yourself—‘heh, I didn’t have to write any of that sql’. Isn’t that nice?

Hopefully these tips will help you as you continue to learn the Rails framework. And if things seem overwhelming, take heart—frameworks can be a difficult thing to learn. You sort of have to figure out where things go, what features are available to you by virtue of said framework, and how to code within the framework’s paradigm. Eventually, though, you’ll know the framework by heart. Really, it won’t take long.

Webmin theme: Tiger

Monday, October 03

David Harrison has created one deadly theme for Webmin

A completely new ‘Tiger-like’ look for Webmin featuring dropdown menus, AJAX search and high colour icon

http://www.stress-free.co.nz/content/view/141/2/