Вопрос

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

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

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

Это было полезно?

Решение

Моим первым побуждением было бы использовать таблицу соединений, но если это нежелательно 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

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

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

Аналогично происходит привязка вашего класса movie обратно к вашим пользователям.

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.Я сегодня ленивый.)

Другие советы

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top