【问题标题】:Why is one of my tables not being populated if I use DataMapper's "has n" and "belongs_to" methods?如果我使用 DataMapper 的“has n”和“belongs_to”方法,为什么我的一个表没有被填充?
【发布时间】:2012-10-30 09:17:05
【问题描述】:

我现在正在使用 sqlite3 上的 DataMapper。我必须定义创建两个表的模型:“公司”和“应用程序”。

每个应用都属于一家公司,每个公司都有许多应用。我想在我的模型中表示这种关系,但是我向每个类添加了“has n”和“belongs_to”方法,当在一堆应用程序上调用#create 时,App 类停止工作,它们没有插入到数据库中。

如果我没有关联方法,那么一切正常。

这是我的 DataMapper 代码:

DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/app.db")

class Company
    include DataMapper::Resource

    property :id, Serial
    property :company_name,
    property :company_id, Text, :unique => true

    has n, :apps
end

class App
    include DataMapper::Resource

    property :id, Serial
    property :app_id, Integer
    property :bundle_id, Text
    property :game_name, Text
    property :company_name, Text
    property :created_at, DateTime
    property :rank, Integer

    belongs_to :company
end

DataMapper.finalize.auto_upgrade!

puts 'Database and tables created'

这是我用来填充表格的代码

companies_in_chart.each do |company|
    @add_company = Company.create(
        :company_name   => company["company_name"],
        :company_id     => company["company_id"]
    )
end
puts "Inserted companies into database"

apps_arr.each do |app|
    @new_app = App.create(
        :app_id         => app["app_id"],
        :bundle_id      => app["bundle_id"],
        :game_name      => app["game_name"],
        :company_name   => app["company_name"],
        :created_at     => app["DateTime"],
        :rank           => app["rank"]
    )
end
puts "Inserted apps into database"

编辑:新代码

#Set up database and apps table
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/app.db")

class Company
    include DataMapper::Resource

    property :id, Serial
    property :company_name, Text,    :required => true, :lazy => false
    property :company_id, Text,      :required => true, :lazy => false, :unique => true

    has n, :apps
end

class App
    include DataMapper::Resource

    property :id, Serial
    property :app_id, Integer,      :required => true
    property :bundle_id, Text,      :required => true, :lazy => false
    property :game_name, Text,      :required => true, :lazy => false
    property :company_id, Text,     :required => true, :lazy => false
    property :created_at, DateTime
    property :rank, Integer

    belongs_to :company
end

DataMapper.finalize.auto_upgrade!

puts 'Database and tables created'

#Insert apps and companies into database
apps_arr.each do |app|

    # Creates a new company based on app entry if the company does
    # not exist in the companies table
    @add_company = Company.create(
        :company_name   => app["company_name"],
        :company_id     => app["company_id"]
    )

    @add_app = App.create(
        :app_id         => app["app_id"],
        :bundle_id      => app["bundle_id"],
        :game_name      => app["game_name"],
        :company_id     => app["company_id"],
        :created_at     => app["DateTime"],
        :rank           => app["rank"]
    )
end
puts "Inserted app and companies into database"

@company = Company.first
ap @company # => #<Company @id=1 @company_name="Rovio Entertainment Ltd" @company_id="rovio">

ap @company.apps # => [] --I was hoping it would return all of Rovio's apps in the database

【问题讨论】:

    标签: ruby sqlite associations datamapper belongs-to


    【解决方案1】:

    应用未创建,因为您必须在创建应用时附加公司。

    如果您想添加不附属于任何公司的应用程序,请在您的应用程序模型中使用它:

    belongs_to :company, :required => false
    

    在创建应用程序时附加公司:

    #Insert apps and companies into database
    
    apps_arr.each do |app|
    
      # Creates a new company based on app entry if the company does
      # not exist in the companies table
    
      company = Company.first_or_create(
        :company_name   => app["company_name"],
        :company_id     => app["company_id"]
      )
    
      app = App.first_or_create(
        :company        => company, # you missed this
        :app_id         => app["app_id"],
        :bundle_id      => app["bundle_id"],
        :game_name      => app["game_name"],
        :company_id     => app["company_id"],
        :created_at     => app["DateTime"],
        :rank           => app["rank"]
      )
    end
    puts "Inserted app and companies into database"
    

    我在 CIBox 上成功复制了您的代码,并且运行良好。

    the code and live demo here

    如您所见,它创建了一个公司并将其附加到创建的应用程序中。

    Company.first.apps 返回创建的应用程序,因此关联正常工作。

    【讨论】:

    • 感谢您的回复。我已尽我所能按照您的建议进行操作。请参阅我的问题以获取我的新代码。
    • 好的。我通过添加:company =&gt; company 更改了我的代码,我还将符号:add_app:add_company 更改为变量companya(我没有按照您的建议用户app,因为该变量名称已被使用由each.do |app| 编写。此代码确实将所有应用程序和公司添加到他们的表中,但company.first.apps 仍然返回一个空数组,而不是第一家公司的所有应用程序,所以我认为关联不起作用。
    • 哦,我也尝试将 company = Company.first_or_create(...) 更改为 c = Company.first_or_create(...) 但随后我收到错误“in block in &lt;top (required)&gt;': undefined local variable or method company' for main:Object (NameError)”,因为它无法识别变量 @ 987654337@:company =&gt; company
    • 你需要调整一下你的代码。 here 是我将如何重组它。另请参阅实时工作演示的更新答案。
    • 非常感谢您的帮助。我想我成功了。你是完全正确的:我需要重构一大堆我认为将成为下一个任务的东西!有趣的是,您的代码似乎生成了两个索引:unique_companies_company_idindex_apps_company。我的代码从未生成似乎需要的第二个。再次感谢您的帮助!
    猜你喜欢
    • 2011-11-11
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多