I’ve been working with DataMapper and trying to use associations between models Project and Task. I had the models in separate files project.rb and task.rb. When I tried associating them with each other I got the following error:
Cannot find the parent_model Project for Task in project (NameError)
I gathered this was caused by project.rb requiring task.rb and vice versa, since the association worked fine if I just put the require in one of the files. Here’s the code:
project.rb
require 'dmconfig' require 'task' class Project include DataMapper::Resource property :id, Serial has n, :tasks end DataMapper.finalize DataMapper.auto_upgrade!
task.rb
require 'dmconfig' require 'project' class Task include DataMapper::Resource property :id, Serial belongs_to :project end DataMapper.finalize DataMapper.auto_upgrade!
dmconfig.rb
require 'rubygems' require 'dm-core' require 'dm-migrations' DataMapper::Logger.new($stdout, :debug) DataMapper.setup(:default, 'sqlite://' + Dir.pwd + '/taskmanager.db')
If I removed the association from one of the files it worked fine, at least from one direction:
require 'dmconfig' class Project include DataMapper::Resource property :id, Serial end DataMapper.finalize DataMapper.auto_upgrade!
If I want the association to work from both directions is the only reasonable solution to just put both classes in the same file? Or is there a way that I can keep them separated and still manage it?
Well, as it turns out, there’s a better way to set these files up. Here’s the revised version:
project.rb
class Project include DataMapper::Resource property :id, Serial has n, :tasks end
task.rb
class Task include DataMapper::Resource property :id, Serial belongs_to :project end
dmconfig.rb
require 'dm-core' require 'dm-migrations' require 'project' require 'task' DataMapper::Logger.new($stdout, :debug) DataMapper.setup(:default, 'sqlite://' + Dir.pwd + '/taskmanager.db') DataMapper.finalize DataMapper.auto_upgrade!
All of the required files are loaded in the config file. Also note that finalize
should only be called when all of the necessary models have been loaded, not after each model individually. I have some concerns about how this will affect resources when there are more models, not all of which are necessarily going to be used at the same time, but I can’t seem to put it into concrete terms, so we’ll let it fly for now. It’s unlikely that the resource consumption of a list manager will ever reach something worthy of concern anyway.