Model Associations Using DataMapper in Separate Files

I am working with DataMapper and trying to use associations between Project and Task models. I have models in separate project.rb and task.rb files. When I try to connect them with each other, I get the following error:

Cannot find the parent_model Project for Task in project (NameError)

I understand that 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 is 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 in at least 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 in both directions, is this the only sensible solution to just put both classes in the same file? Or is there a way I can separate them and still manage?

+4
source share
3 answers

You need to call finalize after all of your models are needed, and not after each of them. One of the finalize things is to test the health of your models to make sure that all relevant models are required. The application download process, which requires all library files, is the ideal place to do this. I suggest something like:

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' # 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 like that. In your application, you require 'dmconfig' and have everything you need for this. DataMapper defers checking to the far end of the relationship (for example, projects in the Task model) until you call finalize or auto_upgrade! , so make sure all models are needed before you do this.

+9
source

It looks like this could be caused by a typo in task.rb

  belongs_to, :project 

should be written as:

 belongs_to :project 

And for what it costs, for example, when using Sinatra, I prefer to store all my models together in one lib/models.rb ... at least as long as it is manageable.

+1
source

First of all, call DataMapper.finalize before calling auto_upgrade. Secondly, it’s better to load models, call termination, and then do DataMapper.auto_migrate! instead of calling auto_upgrade after each model definition.

0
source

All Articles