ActiveRecord has_n ассоциация - PullRequest
       10

ActiveRecord has_n ассоциация

2 голосов
/ 31 декабря 2008

Мне было интересно, как лучше всего моделировать отношения, в которых объект связан ровно с n объектами другого класса. Я хочу расширить отношение has_one до определенного значения n.

Например, TopFiveMoviesList будет принадлежать пользователю и иметь ровно пять фильмов. Я полагаю, что базовая таблица sql будет иметь такие поля, как movie_id_1, movie_id_2, ... movie_id_5.

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

Ответы [ 3 ]

2 голосов
/ 02 января 2009

Я думаю, что реализация этой модели через модель соединения будет для вас лучшим выбором. Это позволяет модели List беспокоиться о логике List, а модели Movie беспокоиться о логике Movie. Вы можете создать модель Nomination (имя не самое лучшее, но вы понимаете, что я имею в виду), чтобы управлять отношениями между фильмами и списками, а когда существует ограничение в 5, вы можете просто ограничить количество выдвигаемых вами номинаций. назад.

Есть несколько причин, по которым я считаю этот подход лучше.

Во-первых, предполагая, что вы хотите иметь возможность обходить отношения в обоих направлениях (movie.lists и list.movies), подход с пятью столбцами будет намного сложнее.

Хотя ActiveRecord было бы намного лучше поддерживать отношения has n, это не так, и вы будете бороться с этой платформой. Кроме того, отношения has n кажутся мне немного хрупкими в этой ситуации. Я не видел такой реализации в ActiveRecord, хотя мне бы очень хотелось, чтобы это произошло. :)

1 голос
/ 01 января 2009

Моим первым инстинктом было бы использовать объединяющую таблицу, но если это нежелательно, столбцы User.movie[1-5]_id подойдут. (Я думаю, что movie1_id лучше соответствует соглашению Rails, чем movie_id_1.)

Поскольку вы пометили эти Rails и ActiveRecord, я добавлю в свой ответ какой-то полностью непроверенный и, возможно, несколько неправильный код модели. :)

class User < ActiveRecord::Base
  TOP_N_MOVIES = 5
  (1..TOP_N_MOVIES).each { |n|  belongs_to "movie#{n}".to_sym, :class_name => Movie }
end

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

Возможно, вы также захотите добавить проверки, чтобы убедиться, что в списке пользователя нет повторяющихся фильмов.

Связывание вашего класса фильма с вашими пользователями аналогично.

class Movie < ActiveRecord::Base

  (1..User::TOP_N_MOVIES).each do |n| 
    has_many "users_list_as_top_#{n}".to_sym, :class_name => User, :foreign_key => "movie#{n}_id"
  end

  def users_list_as_top_anything
    ary = []
    (1..User::TOP_N_MOVIES).each {|n| ary += self.send("users_list_as_top_#{n}") }
    return ary
  end

end

(Конечно, users_list_as_top_anything, вероятно, лучше было бы записать как явный SQL. Сегодня я ленивый.)

1 голос
/ 31 декабря 2008

Я полагаю, вы имеете в виду «реализовать», а не «модель»? Скажем, моделирование довольно просто в UML, где у вас есть сущность Person, состоящая из 5 сущностей Movie.

Но трудности возникают, когда вы говорите, что has_one, переходя к has_5. Если это простое скалярное значение, has_one, возможно, является свойством родительского объекта. Has_5 - это, вероятно, 2 сущности, связанные друг с другом посредством отношения «состоит из» в UML.

Вероятно, основной вопрос, на который нужно ответить: «Можете ли вы гарантировать, что это всегда будет« Топ-5 »?» Если да, смоделируйте его с колонками, как вы упомянули. Если нет, смоделируйте его с другим объектом.

Возможно, еще один вопрос: "Насколько легко будет провести рефакторинг?" Если это просто, черт возьми, начните с 5 столбцов и сделайте рефакторинг для разделения сущностей, если они когда-либо изменятся.

Как обычно, «лучший» зависит от деловой и технической среды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...