在单独的文件中使用DataMapper建模关联

时间:2010-11-01 22:30:15

标签: ruby associations datamapper

我正在使用DataMapper并尝试使用模型Project和Task之间的关联。我将模型放在单独的文件project.rb和task.rb中。当我尝试将它们相互关联时,我收到以下错误:

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

我收集这是由project.rb引起的,需要task.rb,反之亦然,因为如果我将其包含在其中一个文件中,则关联工作正常。这是代码:

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')

如果我从其中一个文件中删除关联,它可以正常工作,至少从一个方向:

require 'dmconfig'

class Project
  include DataMapper::Resource
  property :id,         Serial
end

DataMapper.auto_upgrade!
DataMapper.finalize

如果我希望关联从两个方向工作,那么将两个类放在同一个文件中是唯一合理的解决方案吗?或者,有没有办法可以将它们分开并仍然进行管理?

3 个答案:

答案 0 :(得分:9)

您需要在所有模型之后致电finalize,而不是在每个模型之后。 finalize所做的其中一件事就是检查您的模型,确保所有相关模型都是必需的。在需要所有库文件之后,应用程序启动过程是执行此操作的理想位置。我建议像:

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!

或者那种性质的东西。在您的应用程序中,您require 'dmconfig'并根据需要设置所有内容。在您调用finalizeauto_upgrade!之前,DataMapper会推迟检查关系的远端(例如,任务模型中的项目),因此请确保在执行此操作之前需要所有模型。

答案 1 :(得分:1)

看起来这可能是由task.rb

中的拼写引起的
  belongs_to,           :project

应写成:

belongs_to :project

对于它的价值,例如,在使用Sinatra时,我更喜欢将所有模型放在一个lib/models.rb文件中...至少只要这是可管理的。

答案 2 :(得分:0)

首先,在调用auto_upgrade之前调用DataMapper.finalize。其次,最好加载模型,调用finalize然后再做DataMapper.auto_migrate!而不是在每个模型定义后调用auto_upgrade。