Thoughts from the team at Mission Data

Rails fixtures with models using set_table_name

If you have a model that uses set_table_name you may hit a snag when trying to use fixtures and unit tests. The solution is twofold: name the fixture file using the legacy table name, and use the set_fixture_class method in your unit test. I coudn’t find this method mentioned in Agile Web Development with Rails, and there’s only a brief mention on the rubyonrails.com site. Still, some web searches turned up the answers.

Here is a simple example:

We’ll start with a table named libris_book that contains book entries. The name libris_book won’t really fly with the Rails pluralized table name approach. It’s easy, however, to fix that disconnect in the model:

class Book < ActiveRecord::Base
  set_table_name 'libris_book'
end

Let’s take a look at our data:

~/src/libris$ script/console
Loading development environment.
>> Book.count
=> 1230

Good enough. Now, we’ll be good little coders and write some unit tests using fixtures. We’ll create a fixture file and our test class:

books.yml

test_book:
  title: Life in Lawrenceburg
  author: Darren Day

book_test.rb

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

class BookTest < Test::Unit::TestCase
  fixtures :books

  def test_fixtures
    assert_equal(2,Book.count)
    test_book = books(:test_book)
  end
end

Looks good, but it won’t work!

~/src/libris$ rake test
(in /home/darrend/src/libris)
/usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake-0.7.2/lib/rake/rake_test_loader.rb" "test/unit/book_test.rb"
Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake-0.7.2/lib/rake/rake_test_loader
Started
E
Finished in 0.01133 seconds.

  1) Error:
test_fixtures(BookTest):
ActiveRecord::StatementInvalid: Mysql::Error: Table 'libris_test.books' doesn't exist: DELETE FROM books
...

Ugh. That doesn’t look pretty. After some googling around the following comes together

  • Rename books.yml to libris_book.yml. The fixture yaml file has to share the same name as the database table name.
  • Change the fixtures declaration to fixtures :libris_book.
  • Use set_fixture_class to connect the fixture to the model class.

Here is our new and improved book_test.rb file:

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

class BookTest < Test::Unit::TestCase
  set_fixture_class :libris_book => Book
  fixtures :libris_book

  def test_fixtures
    assert_equal(2,Book.count)
    test_book = libris_book(:test_book)
  end
end

6 Responses to “Rails fixtures with models using set_table_name”

  1. April 30th, 2007 @ 10:39 pm Chadwick responded:

    For schema names in fixtures, you can simply pass the fixture helper a string rather than a symbol. Ex:

    class UserTest

  2. May 25th, 2007 @ 7:47 am Aleksey Gureev responded:

    Thanks! Right what I was looking for!

  3. July 16th, 2010 @ 3:54 pm Nicolas Buduroi responded:

    Great information! Now, it would be great to have something similar for migrations.

  4. May 24th, 2012 @ 4:09 am Rails – changed a table name, now tests won’t run | PHP Developer Resource responded:

    […] http://www.missiondata.com/blog/systems-integration/80/rails-fixtures-with-models-using-set_table_na... […]

  5. September 13th, 2012 @ 1:46 pm Michiel Sikkes responded:

    Wow thanks! I know this is a post from the past. But this just helped me fix my problems, Anno 2012 ;-)

  6. November 21st, 2012 @ 4:05 pm S responded:

    Thanks for saving my time!

blog comments powered by Disqus