Настройка связей с DataMapper & Sinatra - PullRequest
5 голосов
/ 23 сентября 2011

Хорошо, это сводит меня с ума. Я прочитал статью и пример Ассоциации и пытался решить это в течение последних трех дней, и я устал от этого, заставляя меня чувствовать себя глупым, так что ...

Как установить ассоциации с DataMapper?

(Я использую DM с Sinatra с SQLite3. Все слова отлично подходят для отдельных таблиц с несколькими значениями и т. Д. Когда я начинаю пытаться связать их, у меня появляются ошибки.)

Допустим, у меня есть фруктовый сад с яблонями. У каждого дерева много яблок. В каждом яблоке много семян. Поэтому у каждого дерева есть много семян через яблоки

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!

Это правильно? Я продолжаю получать различные ошибки, когда я пытаюсь запустить это. Главным образом в соответствии с недопустимой ассоциацией или не может создать столбец NULL со значением NULL и т. Д. Что я не понимаю в этом отношении?

Далее, если у меня есть рабочая модель, как мне получить информацию из нее?

Если есть 3 дерева:

Tree.all.count 
=> 3

Если есть 2 яблока:

Apple.all
=>[#<Apple @id=1>, #<Apple @id=2>]  

Хорошо, круто. Но сколько яблок у дерева № 2? Сколько семян у дерева № 4? Сколько всего яблок? Сколько всего семян?

Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

12 голосов
/ 23 сентября 2011

Ваша модель выглядит немного смущенной:

Допустим, у меня есть фруктовый сад, полный яблонь.У каждого дерева много яблок.В каждом яблоке много семян.Поэтому у каждого дерева есть много семян через яблоки.

Таким образом, у дерева есть много яблок, яблоко принадлежит к дереву и имеет много семян, а семя принадлежит яблоку (и, в конечном счете, одному дереву).).

Мы можем почти (но не совсем) принять этот язык как есть и использовать его для создания ассоциаций.После небольшого перевода, чтобы получить правильный синтаксис, мы получаем следующее:

# 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

В вашем коде у вас есть семена с несколькими яблоками и деревьями, что на самом деле не имеет никакого смысла.

Какдля запросов:

Но сколько яблок есть у Tree # 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

Сколько семян у дерева # 4?

Ассоциация, которую мы добавили к Tree модели has n, :seeds, :through => :apples, означает, что у нас есть seeds метод, доступный в Tree объектах.

Tree.get(4).seeds.count

Сколько всего яблок?Сколько всего семян?

Просто:

Apple.count  # note singular not plural (it's a class method on Apple)
Seed.count

Попробуйте загрузить эту новую модель в irb (вам может понадобиться удалить файл orchard.db при изменении модели)и затем поиграем с некоторыми из запросов и методов создания , надеюсь, это даст вам лучшее представление о том, что происходит.

Создание ассоциаций

(См. Раздел «Добавление к ассоциациям» на странице связей .)

Чтобы добавить существующий Apple в Tree:

a_tree.apples << an_apple

Обратите внимание, что Tree связан не с одним Apple, а с коллекцией (это has n Apples), поэтому созданный метод - apples (т.е. он является множественным числом), и метода нетapple, поэтому вы видите ошибку no method.

Вы также можете создать новый Apple, связанный с Tree напрямую:

a_tree.apples.new    #created but not saved to database
a_tree.apples.create #created and saved to database

Вы также можетесоздайте ассоциацию наоборот, со стороны Apple:

an_other_apple = Apple.new
an_other_apple.tree = a_tree

, но вы должны быть осторожны, делая это таким образом,s новое яблоко не будет отображаться в коллекции a_tree с Apples (a_tree.apples не включает an_other_apple).Для того, чтобы он появился, вам нужно сохранить яблоко, а затем позвонить reload на Tree:

an_other_apple.save
a_tree.reload

Вам нужно остерегаться этого, так как вы можете получить Apple, который, кажется, находится в двух Tree с одновременно, если вы не будете осторожны.

1 голос
/ 23 сентября 2011

Я думаю, что это проблема плюрализации - ты не ненавидишь это?

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

  has n, :apples  # here
  has n, :tree, :through => :apples  # and here
end
0 голосов
/ 23 сентября 2011

Без особых знаний о Datamapper и после пропуска документации по datamapper, как насчет этих ответов?

Сколько яблок у дерева 2:

Tree.get(2).apples.count

Сколько семян у дерева 4:

Tree.get(4).apples.inject(0) {|count, apple| count + apple.seeds.count}
...