Как я могу иметь два отношения «многие ко многим» к одной модели в DataMapper? - PullRequest
0 голосов
/ 24 июня 2011

edit: Обновлен вопрос, чтобы показать мое использование :child_key => [:comparison_id], как предлагается в комментарии.

У меня есть две модели, которые выглядят так:

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

class Msrun
  include DataMapper::Resource
  property :id, Serial
  property :name, String
end

Сравнение происходит из сравнения двух наборов мсрунов. Я думал, что представлю это через два отношения «многие ко многим» от «Сравнения» до «Мсрун», но я бьюсь головой об стену о том, как это сделать в DataMapper. Я знаю, что отношения многие-ко-многим доступны, добавив что-то вроде этого:

has n, :whatevers, :through => Resource

Однако между этими двумя моделями будет установлено только одно отношение «многие ко многим». Я также попытался создать две модели соединения и вручную указать отношения, а также вручную указать дочерний ключ для каждого отношения следующим образом:

# Join model for the comparison-msrun many-to-many relationship.
class First
  include DataMapper::Resource
  belongs_to :msrun, :key => true
  belongs_to :comparison, :key => true
end


# Join model for the comparison-msrun many-to-many relationship.
class Second
  include DataMapper::Resource
  belongs_to :msrun, :key => true
  belongs_to :comparison, :key => true
end

class Comparison
  include DataMapper::Resource
  property :id, Serial

  has n, :firsts
  has n, :msrun_firsts, 'Msrun', :through => :firsts, :child_key => [:msrun_id]

  has n, :seconds
  has n, :msruns_seconds, 'Msrun', :through => :seconds, :child_key => [:msrun_id]
end

class Msrun
  include DataMapper::Resource
  property :id, Serial
  property :name, String

  has n, :firsts
  has n, :comparison_firsts, 'Comparison', :through => :firsts, :child_key => [:comparison_id]

  has n, :seconds
  has n, :comparison_seconds, 'Comparison', :through => :seconds, :child_key => [:comparison_id]
end

Запуск automigrate приводит к следующей ошибке:

rake aborted!
No relationships named msrun_firsts or msrun_first in First

Что я здесь не так делаю? Как я могу сделать эту работу?

Ответы [ 2 ]

0 голосов
/ 24 июня 2011

То, что вы наблюдаете, это тот факт, что отношения хранятся в наборе, подобном объекту под капотом, более конкретно, в наборе, который использует имя отношения как дискриминатор.Так что в вашем случае происходит то, что последнее определение перезаписывает первое, так как наборы не допускают дублирование записей (и в нашем случае замените более старую запись более новой, для целей набора идентичной).

Для этого есть практические причины.Нет смысла объявлять два предположительно разных отношения в одной модели, но называть их одинаковыми.Как бы вы их различали при попытке получить к ним доступ?Это проявляется в реализации DM, где метод, названный именем отношения, определяется в Ресурсе.Итак, что DM делает в вашем случае, пытаясь добавить дубликат к набору, так это то, что он просто использует последние опции для генерации реализации этого метода.Даже если бы он принимал повторяющиеся имена отношений, последняя связь привела бы к перезаписанной / переопределенной версии того же метода, что оставило бы вас с тем же чистым эффектом.

Как следствие, вам нужно будет определитьотношения с разными именами на ваших моделях.Когда вы думаете об этом, это действительно имеет смысл.Чтобы помочь DM с выводом используемой модели, вы можете передать имя модели (или саму константу) в качестве 3-го параметра в метод has или в качестве 2-го параметра для belongs_to

class Comparison
  include DataMapper::Resource
  property :id, Serial

  has n, :firsts
  has n, :first_msruns, 'Msrun', :through => :firsts

  has n, :seconds
  has n, :second_msruns, 'Msrun', :through => :seconds
end

class Msrun
  include DataMapper::Resource
  property :id, Serial
  property :name, String

  has n, :firsts
  has n, :first_comparisons, 'Comparison', :through => :firsts

  has n, :seconds
  has n, :second_comparisons, 'Comparison', :through => :seconds

end

Надеюсь, это поможет!

0 голосов
/ 24 июня 2011

Согласно DataMapper Документы

Я полагаю, вы можете сделать:

class Msrun
    include DataMapper::Resource
    property :id, Serial
    property :name, String

    has n, :firsts #This line could probably be omitted 
    has n, :first_comparisons, 'Comparison', :through => :firsts

    has n, :seconds #This line could probably be omitted 
    has n, :second_comparisons, 'Comparison', :through => :seconds
end
...