Automatically creating files for file_column models in Fixtures

I wanted to be able to have my testing regime automatically create files associated with model fixtures defined in the fixture files. Coincidentally, I’m using Sebastien Kanthak’s file_column plugin for managing files in models.

After looking at the Fixture class and the FileColumn module, I realised that I needed a way to store the model attribute(s) that were passed in the call to file_column. What FileColumn did was create the methods according to the attribute passed into the method but the attribute itself is not actually stored anywhere.

Time to extend FileColumn:

[ruby]require File.join(RAILS_ROOT, ‘vendor’, ‘plugins’, ‘file_column’, ‘lib’, ‘file_column’)

module FileColumn
module ClassMethods
@@file_column_attributes = {}
alias :aliased_file_column :file_column
def file_column(attr, options = {})
aliased_file_column(attr, options)
klass = self.name.constantize
@@file_column_attributes[klass] ||= []
@@file_column_attributes[klass] << attr
end

def file_attributes
@@file_column_attributes[self.name.constantize]
end
end
end[/ruby]

As the name implies, the methods in ClassMethods are class methods on the including class. So in order to store the file_column attributes, we need a class variable, @@file_column_attributes. This variable is a hash with the model class name as the key and an array containing the attributes.I'll also implement a class method so that I'll be able to do Model.file_attributes and know what attributes have been file_columnised.

Next, we'll need to change the way fixtures are populated to the test database. This involves extending the Fixtures class.

We'll do this in test_helper.rb

[ruby]
require 'fileutils'
class Fixtures
SAMPLE_FILE = File.join(Test::Unit::TestCase.fixture_path, 'files', 'sample.pdf')
include FileUtils

alias :original_insert_fixtures :insert_fixtures

def insert_fixtures
original_insert_fixtures
create_files(@class_name, values) unless @class_name.constantize.file_attributes.nil?
rescue NameError
# workaround for HABTM fixtures
end

def create_files(klass, values)
model_dir = File.join(Test::Unit::TestCase.fixture_path, 'media', 'uploads', klass.downcase)
values.each do |fixture|
klass.constantize.file_attributes.each do |attr|
create_file(fixture, attr, model_dir) unless attr.nil?
end
end
def create_file(fixture, attribute, parent_dir)
attribute = attr.to_s
dest_dir = mkpath(File.join(parent_dir, attribute, fixture['id'].to_s))
file_dest = File.join(dest_dir, fixture[attribute])
cp(SAMPLE_FILE, file_dest) unless fixture[attribute].nil? or File.exists?(file_dest)
end
end
[/ruby]

The extended insert_fixtures method first invokes original_insert_fixtures, then checks whether the model has any file_column attributes. If it does, the files defined in the fixtures will be created if they don't already exist.

EDIT: Running functional tests with rake test:functionals fails miserably even though running the tests individually is just fine.

2 thoughts on “Automatically creating files for file_column models in Fixtures

  1. Probably a stupid question, but where do I put the first piece of code which extends the FileColumn? test_helper.rb?

  2. In my case, I created file_column.rb in mocks to hold the FileColumn extension. But it will work if the code is placed in test_helper.rb as well.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s