我正在使用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
如果我希望关联从两个方向工作,那么将两个类放在同一个文件中是唯一合理的解决方案吗?或者,有没有办法可以将它们分开并仍然进行管理?
答案 0 :(得分:9)
您需要在所有模型之后致电finalize
,而不是在每个模型之后。 finalize
所做的其中一件事就是检查您的模型,确保所有相关模型都是必需的。在需要所有库文件之后,应用程序启动过程是执行此操作的理想位置。我建议像:
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!
或者那种性质的东西。在您的应用程序中,您require 'dmconfig'
并根据需要设置所有内容。在您调用finalize
或auto_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。