tag:www.katrinaowen.com,2008:/posts~/scratch2011-02-03T20:21:28ZEnkiKatrina Owenkatrina.owen@gmail..comtag:www.katrinaowen.com,2008:Post/112011-02-04T04:21:00Z2011-02-03T20:21:28ZSchema loading for tests in rails<p>I’m reading The Rails 3 Way by Obie Fernandez, and it says</p>
<blockquote>
<p>Every time you run tests, Rails dumps the schema of your development database and copies it to the test database using an autogenerated schema.rb script.</p>
</blockquote>
<p>In my experience this isn’t quite what happens. From what I’ve observed:</p>
<ul>
<li><code>schema.rb</code> gets generated when you call <code>rake db:migrate</code></li>
<li>the schema gets loaded from <code>schema.rb</code> to your test database when you call <code>rake db:test:prepare</code></li>
<li>when you run tests, the calls to the database inside each of the tests are run within a transaction that gets rolled back at the end of the test</li>
</ul>
<p>In practice, you could therefore load seed data into your test database after calling <code>rake db:test:prepare</code> and you wouldn’t lose this every time you run your tests.</p>
<pre>namespace :db do
namespace :test do
desc "Init bare bones test data"
task :seed_db do
# your seed data here
end
end
end</pre>
<pre>Rake::Task["db:test:prepare"].enhance do
Rake::Task["db:test:seed_db"].invoke
end</pre>
<p>Is this a good idea? Well, It depends. I’m working on one project where it is extremely helpful. Perhaps when we’ve gotten things refactored a bit it won’t be necessary anymore.</p>tag:www.katrinaowen.com,2008:Post/92011-01-29T08:39:13Z2011-01-29T08:37:30ZRails 3 Scopes: With great power comes great responsibility.<p>I wrote one of the worst bugs of my career (so far) the other day.</p>
<p>The long and short of it is this:<br />
ActiveRecord::Relation may behave like an array in many ways, but it’s not an array. If you are doing something which is completely harmless to an array, but could be potentially destructive to an active record relation, make sure what you have <em>really</em> is an array.</p>
<h2>It goes like this</h2>
<p>Create a fresh rails3 project, and set it up to use rspec.</p>
<pre>$ rails new todo -T
# Gemfile
source 'http://rubygems.org'
gem 'rails', '~> 3.0'
gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'rspec-rails', '~> 2.4'</pre>
<pre>rails g rspec:install</pre>
<p>Create a simple model.</p>
<pre>rails g migration create_tasks</pre>
<pre>class CreateTasks < ActiveRecord::Migration
def self.up
create_table :tasks do |t|
t.column :description, :text
t.column :done, :boolean, :default => false
t.timestamps
end
end</pre>
<pre> def self.down
drop_table :tasks
end
end</pre>
<pre>rake db:migrate && rake db:test:prepare</pre>
<p>Add a scope</p>
<pre>class Task < ActiveRecord::Base
scope :done, where('done = ?', true)
end</pre>
<p>This is where it gets interesting.</p>
<pre>require 'spec_helper'</pre>
<pre>describe Task do
it "cleanly extracts from array" do
trucs = {:des => :trucs}
machin = {:un => :machin}
bidule = {:une => :bidule}</pre>
<pre> stuff = [trucs, machin, bidule]</pre>
<pre> extracted = stuff.delete(machin)
extracted.should == machin
stuff.should_not include(machin)
end</pre>
<pre> context "active record relation" do
it "extracts cleanly" do
jump = Task.create(:description => 'jump')
run = Task.create(:description => 'run')
walk = Task.create(:description => 'walk')</pre>
<pre> activities = Task.all # activities.class == Array</pre>
<pre> extracted = activities.delete(run)
extracted.should == run
activities.should_not include(run)</pre>
<pre> Task.all.should include(run)
end</pre>
<pre> it "doesn't. Sneaky bastard" do
jump = Task.create(:description => 'jump', :done => true)
run = Task.create(:description => 'run', :done => true)
walk = Task.create(:description => 'walk', :done => true)</pre>
<pre> activities = Task.done # activities.class == ActiveRecord::Relation</pre>
<pre> extracted = activities.delete(run)</pre>
<pre> Task.all.should include(run)</pre>
<pre> # fails
# incidentally, also fails on these:
# popped.should == run
# activities.should_not include(run)
end
end
end</pre>
<p>To quote the log:</p>
<blockquote>
<p><span class="caps">AREL</span> (0.2ms) <span class="caps">DELETE</span> <span class="caps">FROM</span> “tasks” <span class="caps">WHERE</span> (done = ‘t’) <span class="caps">AND</span> (“tasks”.“id” = 2)</p>
</blockquote>
<p>Yeah. Potentially really not good.</p>tag:www.katrinaowen.com,2008:Post/102011-01-13T04:00:00Z2011-01-30T13:30:11ZPostgreSQL template tables and rake db:test:prepare<p>I recently overcame the final hurdle to getting rspec hooked up within this legacy project that I’m working on (legacy in the sense that it has no tests, and is in production, and works).</p>
<p>There were three levels of fail with respect to running <code>rake db:test:prepare</code></p>
<h2>Fail #1: Configuration</h2>
<p>The database configuration file had the test environment looking at the same database as development. The first time I ran <code>rake db:test:prepare</code> it dropped my development database. Usually this isn’t such a huge disaster, but in this case we’re using a slightly sanitized version of the production database. It takes 45 minutes to scp it down from the backup server, and 4+ hours to load.</p>
<p>The solution, of course, was to change this:</p>
<pre>test:
adapter: postgresql
database: legacyproject_development</pre>
<p>to this:</p>
<pre>test:
adapter: postgresql
database: legacyproject_test</pre>
<h2>Fail #2: Bug in Schema Dumper</h2>
<p>This project happens to be using a homegrown plugin for PostGIS (because at the time we needed one there were no other available options). Since we’ve never needed to actually load the database from the schema, nobody had noticed that the schema definition of geometry tables were lacking the parameter for the <span class="caps">SRID</span>.</p>
<pre>wrong number of arguments (4 for 5)</pre>
<p>Fixing the custom schema dumper for the geometry tables fixed this issue.</p>
<h2>Fail #3: Missing PostGIS Functions and Tables</h2>
<p>The production and development databases had been set up manually to include the PostGIS goodies. <code>rake db:test:prepare</code> was now correctly creating the test database based on the schema, but was lacking everything PostGIS. Three options immediately came to mind:</p>
<ul>
<li>write a task that manually loaded all the postGIS stuff and have it run prior to the <code>rake db:test:prepare</code> task <em>(uhm, no thanks)</em>.</li>
<li>add the PostGIS stuff to the default postgresql template table, template1 <em>(I’d rather not)</em>.</li>
<li>create a special PostGIS template table <em>(yes, please)</em>.</li>
</ul>
<p>So I did:</p>
<pre>psql -d postgres -U postgres
CREATE DATABASE template_postgis WITH TEMPLATE=template1 ENCODING='UTF8';
\c template_postgis;
CREATE LANGUAGE plpgsql;
\i /opt/local/share/postgresql90/contrib/postgis-1.5/postgis.sql
\i /opt/local/share/postgresql90/contrib/postgis-1.5/spatial_ref_sys.sql
UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template_postgis';
GRANT ALL ON geometry_columns TO PUBLIC;
GRANT ALL ON spatial_ref_sys TO PUBLIC; </pre>
<p>And then all I needed to do define the database config so that it used this template instead of template1 when created the test database.</p>
<pre>test:
adapter: postgresql
template: template_postgis
database: legacyproject_test</pre>
<p>Ah, right. Not so simple. It would seem that noone has needed this config options, so rails doesn’t recognize the template option.</p>
<p>So we submitted a patch to rails. <a href="https://github.com/kowen/rails/commit/1050dc3f964ced1fa73009826109c40b507cfb47">Smallest patch in the history of rails</a> probably, at less than 30 characters</p>
<p><strong>#win</strong></p>tag:www.katrinaowen.com,2008:Post/82011-01-07T09:04:09Z2011-01-07T09:04:09ZA (silly) PostgreSQL gotcha<p>As I was setting up my latest project in Rails 3 with PostgreSQL, Cucumber, RSpec and various other goodies, I got this error when running <code>rake db:migrate</code>:</p>
<pre>PGError: ERROR: permission denied for relation schema_migrations
SELECT version FROM schema_migrations</pre>
<p>I took a quick look in my config/database.yml</p>
<p>And saw the following ridiculousness:</p>
<pre>development:
adapter: postgresql
encoding: unicode
database: myproject_development
host: localhost
pool: 5
username:
password: productionpassword</pre>
<p>Updating username to myproject and password to be blank did the trick.</p>tag:www.katrinaowen.com,2008:Post/72011-01-05T08:55:54Z2011-01-05T08:54:59ZUsing PostgreSQL with Rails 3, Cucumber & RSpec<p>One thing that tripped me up when trying to set up a new project using PostgreSQL rather than sqlite3, is that when running <code>rake db:test:prepare</code> I got the error message:</p>
<pre>/path/to/rake:19:in `<main>'
Couldn't create database for
{"adapter"=>"postgresql", "encoding"=>"unicode",
"database"=>"myproject_test", "host"=>"localhost",
"pool"=>5, "username"=>"moi", "password"=>nil, "min_messages"=>"WARNING"}
rake aborted!
FATAL: database "test" does not exist</pre>
<p>This despite having just run <code>createdb -O moi test</code></p>
<p>I recreated the database, checked that it was, in fact, there (<code>psql myproject_test</code>, and ran the rake command again. Boom. Same error message.</p>
<p>Turns out the user “moi” was allowed to drop databases, but not create them.</p>
<pre>psql myproject_development;
ALTER USER moi CREATEDB;
\q</pre>
<p>Et voila.</p>tag:www.katrinaowen.com,2008:Post/62010-12-28T07:54:00Z2010-12-27T21:55:57ZLazybones: Skeleton Rails3 App<p>I’ve set myself a 30 day challenge for the month of January. Nevermind that January has 31 days.</p>
<p><em>Every morning, I’m going to get up an hour early (yes, weekends included) and practice programming.</em></p>
<p>This is different from programming at work. For one, I don’t need to deliver anything. I basically want to be able to do some deliberate practice on <span class="caps">TDD</span>/<span class="caps">BDD</span> and refactoring, as well as explore some gems that I’m unfamiliar with.</p>
<p>I have a couple of projects that I can use for this. One is OverkillCMS:<br />
<a href="http://github.com/kowen/overkill">git://github.com/kowen/overkill.git</a></p>
<p>This is a simple <span class="caps">CMS</span> for a friend of mine which I’m making simply to practice full <span class="caps">TDD</span>/<span class="caps">BDD</span> using rspec and cucumber. That, and because her current website requires her to edit html and css, and she’s not a programmer.</p>
<p>Another is Carbon Dating – An Open-Source Ruby on Rails Dating App<br />
<a href="http://github.com/kowen/c14">git://github.com/kowen/c14.git</a></p>
<p>This one is also inspired by some friends of mine. They’re running a tiny niche dating site that uses some of the ugliest <span class="caps">PHP</span> code you will ever see. It’s an embarrassment to cowboy coders everywhere.</p>
<p>In preparation for these two projects, I went ahead and found out how to set up a rails 3 project per my own preferences (rspec, cucumber, jasmine, haml, sass, compass, watchr, metric_fu) and documented it here, along with some convenience files:</p>
<p><a href="http://github.com/kowen/lazybones">git://github.com/kowen/lazybones.git</a></p>tag:www.katrinaowen.com,2008:Post/52010-12-18T11:32:03Z2010-12-18T11:31:30ZZeo: Hacking Sleep<p>I purchased a zeo.</p>
<p>I received it yesterday, have tried it once, and so far I’m impressed. It’ll be exciting to see how much data I can get out of it.</p>
<p>It was able to report:</p>
<ul>
<li>how long it took me to fall asleep (33 minutes)</li>
<li>how long I slept, total (10 hours, 25 minutes)</li>
<li>how many times I woke up during the night (6. Ouch. I only remember 3 of them.)</li>
<li>how much deep, light, and <span class="caps">REM</span> sleep I got (plenty!)</li>
</ul>
<p>The headband was comfortable and non-disruptive. I toss a bit, and slept on my sides and my stomach, and the headband didn’t budge.</p>
<p>My ZQ score was 114. Sky high, according to the pamphlet they included in the package. Apparently in my age bracket the average is around 80.</p>
<p>Interestingly, when I woke up, my subjective judgement was that I had slept “okay”.</p>tag:www.katrinaowen.com,2008:Post/42010-12-17T20:27:00Z2010-12-17T12:20:30ZEncoding issues: cucumber<p>In my standalone test runner which uses ruby 1.9.2, cucumber driving firewatir, and using rspec matchers I have a test that looks like this:</p>
<pre><code>Scenario: Single logout flash
Given I am logged in with "username"/"password"
When I log out
Then I should see "Du er nå logget ut"</code></pre>
<p>That last bit is in Norwegian. The project this code tests has support for two Norwegian written languages, and English (sort of). Actually, let’s not go there.</p>
<p>The browser is set up like this:</p>
<pre><code>Watir::Browser.default = "firefox"</code></pre>
<pre><code>def browser
@browser ||= Watir::Browser.new
end</code></pre>
<p>The test should be passing, but I get the following error on the line with the Norwegian text in it.</p>
<pre><code>incompatible character encodings: ASCII-8BIT and UTF-8 (Encoding::CompatibilityError)</code></pre>
<p>Tthe step definition for the failing step is:</p>
<pre><code>Then /^I should see "([^"]*)"$/ do |term|
browser.text.should include(term)
end</code></pre>
<p><span class="caps">ASCII</span>-8BIT isn’t really an encoding, as far as I can tell. It’s unencoded bytes (and is therefore aliased to <span class="caps">BINARY</span>).</p>
<p>There are a few places this can blow up, I think.<br />
1. The file itself could be encoded wrong.<br />
2. The regex could be having trouble with utf-8, so the <code>term</code> could be unencoded<br />
3. the <code>browser.text</code> could be unencoded.</p>
<p>My first reaction was to add <code># encoding: utf-8</code><br />
to the top of each of my files in the project. I should have thought of it earlier — I’ve been having to do this on a lot of projects with Norwegian output lately. Unfortunately that didn’t change the output for the failing scenario.</p>
<p>Next I dug into at the documentation for the <a href="http://www.ruby-doc.org/core-1.9/classes/Encoding.html">ruby encoding class</a> and tried setting default internal and external encoding in the <code>env.rb</code> file:</p>
<pre><code>Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8</code></pre>
<p>No dice. The output remained the same.</p>
<p>Next, I tried forcing the regex to deal with utf-8 properly (<code>/matcher/u</code>)</p>
<pre><code>Then /^I should see "([^"]*)"$/u do |term|</code></pre>
<p>The output was unchanged.</p>
<p>Reluctantly, I tried what feels like a fairly dirty hack:</p>
<pre><code>browser.text.force_encoding('utf-8').should include(term)</code></pre>
<p>This worked.</p>
<p>So it seems like FireWatir’s text comes back unencoded.</p>tag:www.katrinaowen.com,2008:Post/32010-12-13T16:32:06Z2010-12-13T16:26:56ZRepeat after me: hypothesis<blockquote>
<p><em>I have a theory that a butterfly is actually a pegasus that flew too high and died of asphyxiation and then was reborn as a caterpillar.</em></p>
</blockquote>
<p>In short, if it is “just a theory”, then it’s not a theory at all. It might be a hypothesis, or a hunch, or a guess, or sometimes even a conjecture. But certainly not a theory.</p>
<p>And, for the record, evolution is /not/ “just a theory”. It’s well-substantiated, well-supported, and well-documented, explaining scientific observations. I.e. <strong>a theory</strong>.</p>
<p>Just sayin’.</p>tag:www.katrinaowen.com,2008:Post/22010-12-08T16:23:04Z2010-12-08T16:21:07ZOrder of Callbacks/Validations on Active Record<p>Every once in a while I find myself wondering about this. So here it is, for the record:</p>
<p>The order of callbacks and validations on a rails active record model is</p>
<p>1. before_validation<br />
2. before_validation, :on => :create<br />
3. after_validation<br />
4. after_validation, :on => :create<br />
5. before_save<br />
6. before_create<br />
7. after_create<br />
8. after_save</p>
<p>ActiveRecord wraps this whole thing in a transaction, so if anything anywhere in this chain fails, the whole thing will be rolled back.</p>
<p>Good to know!</p>tag:www.katrinaowen.com,2008:Post/12010-12-07T20:00:00Z2010-12-08T07:43:17ZSurvival of the fittest<p>It seems like every time I hear the phrase <em>survival of the fittest</em> it’s used to mean something like <em>the one with the most muscle will win when you duke it out</em>.</p>
<p>Quick reminder: In biology, being <em>fit</em> isn’t about being physically powerful. It’s about having offspring that survive long enough to have offspring.</p>
<p>The phrase “survival of the fittest” is almost redundant, in that it basically states that the genes that survive are the ones that get passed on.</p>
<p>Traditionally this is all about luck and randomness. Humans have recently (in evolutionary terms) added inventiveness into the mix.</p>