设置与DataMapper和Sinatra的关联

Don*_*ano 5 ruby datamapper sinatra

好吧,这让我发疯了.我已经阅读了协会的文章和例子,并试图在拉斯三天内解决这个问题,我厌倦了这让我感到愚蠢,所以......

如何设置与DataMapper的关联?

(我正在使用带有SQLite3的带有Sinatra的DM.对于具有多个值等的单个表,一切都很好.当我开始尝试将它们关联起来时,我开始收到错误.)

假设我有一个装满苹果树的果园.每棵树都有很多苹果.每个Apple都有很多种子.因此每棵树通过其苹果有很多种子

require 'sinatra'
require 'datamapper'

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

# Trees in the orchard.
class Tree
  include DataMapper::Resource
  property :id, Serial

  has n, :apples
  has n, :seeds, :through => :apples
end

# Apples on a Tree.
class Apple
  include DataMapper::Resource
  property :id, Serial

  belongs_to :tree
  belongs_to :seed
end

# Seeds in an Apple
class Seed
  include DataMapper::Resource
  property :id, Serial

  has n, :apple
  has n, :tree, :through => apple 
end

DataMapper.finalize.auto_upgrade!
Run Code Online (Sandbox Code Playgroud)

那是对的吗?我尝试运行时遇到各种错误.大多数沿着无效关联的行或者不能创建值为NULL的列NULL等.我不理解这种关系?

此外,一旦我有了工作模型,我该如何从中获取信息?

如果有3棵树:

Tree.all.count 
=> 3
Run Code Online (Sandbox Code Playgroud)

如果有2个苹果:

Apple.all
=>[#<Apple @id=1>, #<Apple @id=2>]  
Run Code Online (Sandbox Code Playgroud)

好的.但树#2有多少苹果?Tree#4有多少种子?总共有多少苹果?总共有多少种子?

任何帮助将不胜感激.

mat*_*att 12

你的模型似乎有点困惑:

假设我有一个装满苹果树的果园.每棵树都有很多苹果.每个Apple都有很多种子.因此每棵树通过其苹果有很多种子.

因此,一棵树有许多苹果,一棵苹果属于一棵树,有许多种子,种子属于苹果(最终是一棵树).

我们几乎(但不完全)可以使用该语言并使用它来创建关联.经过一点点翻译以获得正确的语法,我们得到了这个:

# Trees in the orchard.
class Tree
  include DataMapper::Resource
  property :id, Serial

  has n, :apples    # "a tree has many apples"
  has n, :seeds, :through => :apples
end

# Apples on a Tree.
class Apple
  include DataMapper::Resource
  property :id, Serial

  belongs_to :tree # "an apple belongs to a tree..."
  has n, :seeds    # "...and has many seeds"
end

# Seeds in an Apple
class Seed
  include DataMapper::Resource
  property :id, Serial

  belongs_to :apple  # "and a seed belongs to an apple"
end
Run Code Online (Sandbox Code Playgroud)

在你的代码中你有多个苹果和树木的种子,这没有任何意义.

至于查询:

但树#2有多少苹果?

假设你指的是Tree具有id == 2:

tree_2 = Tree.get(2)
apples_of_tree_2 = tree_2.apples # this gives an array of apples
count_of_apples_of_tree_2 = tree_2.apples.count
Run Code Online (Sandbox Code Playgroud)

Tree#4有多少种子?

我们添加到Tree模型中的关联has n, :seeds, :through => :apples意味着我们seedsTree对象中有一个可用的方法.

Tree.get(4).seeds.count
Run Code Online (Sandbox Code Playgroud)

总共有多少苹果?总共有多少种子?

只是:

Apple.count  # note singular not plural (it's a class method on Apple)
Seed.count
Run Code Online (Sandbox Code Playgroud)

尝试将这个新模型加载到irb中(您可能需要orchard.db在更改模型时删除文件),然后使用一些查询创建方法,希望这会让您更好地了解正在发生的事情.

创建关联

(请参阅"关联" 页面 "添加到关联"部分.)

要将现有内容添加AppleTree:

a_tree.apples << an_apple
Run Code Online (Sandbox Code Playgroud)

请注意,a Tree与单个Apple而不是集合(it has n Apples)无关,因此创建的方法是apples(即它是多元化的),并且没有方法apple可以解释为什么你看到no方法错误.

您还可以直接创建Apple与之关联的新内容Tree:

a_tree.apples.new    #created but not saved to database
a_tree.apples.create #created and saved to database
Run Code Online (Sandbox Code Playgroud)

您也可以从Apple侧面创建相反的关联:

an_other_apple = Apple.new
an_other_apple.tree = a_tree
Run Code Online (Sandbox Code Playgroud)

但是你需要小心这样做,因为新的苹果不会出现在(不包括)a_tree的集合中.为了它出现您需要保存的苹果,然后调用上:Applesa_tree.applesan_other_applereloadTree

an_other_apple.save
a_tree.reload
Run Code Online (Sandbox Code Playgroud)

你需要注意这一点,因为如果你不小心的话,你可能会在同一时间看到Apple两个Trees.