I'm working with DataMapper and trying to use associations between models Project and Task. I have the models in separate files project.rb and task.rb. When I try associating them with each other I get the following error:
Cannot find the parent_model Project for Task in project (NameError)
I gather this is caused by project.rb requiring task.rb and vice versa, since the association works fine if I just include it 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.auto_upgrade!
DataMapper.finalize
task.rb
require 'dmconfig'
require 'project'
class Task
include DataMapper::Resource
property :id, Serial
belongs_to :project
end
DataMapper.auto_upgrade!
DataMapper.finalize
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 remove the association from one of the files it works fine, at least from one direction:
require 'dmconfig'
class Project
include DataMapper::Resource
property :id, Serial
end
DataMapper.auto_upgrade!
DataMapper.finalize
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?
You need to call finalize
after you require all your models, not after each one. One of the things finalize
does is sanity check your models, to make sure all the relevant models have been required. The application boot process, after requiring all the library files is an ideal place to do this. I suggest something like:
class Project
include DataMapper::Resource
property :id, Serial
has n, :tasks
end
class Task
include DataMapper::Resource
property :id, Serial
belongs_to :project
end
require 'dm-core'
require 'dm-migrations'
require 'project'
require 'task'
# note that at this point, all models are required!
DataMapper::Logger.new($stdout, :debug)
DataMapper.setup(:default, 'sqlite://' + Dir.pwd + '/taskmanager.db')
DataMapper.finalize
DataMapper.auto_upgrade!
Or something of that nature. In your application, you require 'dmconfig'
and have everything set up with that one require. DataMapper defers checking for the far end of relationships (say, projects in the Task model) until you call finalize
or auto_upgrade!
, so make sure all the models are required before you do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With