Pergunta

Eu queria saber qual a melhor maneira de modelar um relacionamento onde um objeto é associado com exatamente n objetos de outra classe. Eu quero estender a relação has_one para um valor específico de n.

Por exemplo, um TopFiveMoviesList pertenceria para o usuário e têm exatamente cinco filmes. Eu imagino que a tabela sql subjacente teria campos como movie_id_1, movie_id_2, ... movie_id_5.

Eu sei que eu poderia fazer um relacionamento has_many e limitar o número de crianças no nível do modelo, mas eu prefiro não ter uma tabela intermediário.

Foi útil?

Solução

Meu primeiro instinto seria usar uma tabela associativa, mas se isso não é colunas User.movie[1-5]_id desejáveis ??caberia a conta. (Eu acho que se encaixa movie1_id melhor com Rails convenção de movie_id_1.)

Uma vez que você marcou este Rails e ActiveRecord, vou acrescentar algum código modelo completamente testados e provavelmente um pouco errado para a minha resposta. :)

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

Você poderia envolver essa linha em um método macro-estilo, mas a menos que se isso é um padrão comum para a sua aplicação, fazendo isso provavelmente só irá fazer o seu código que mais difícil de ler com pouco benefício DRY.

Você também pode querer adicionar validações para garantir que não há filmes duplicados na lista do usuário.

Associando sua classe filme de volta para seus usuários é similar.

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

(Claro que users_list_as_top_anything provavelmente seria melhor escrito como SQL explícita. Eu sou preguiçoso hoje.)

Outras dicas

Eu acho que implementar este modelo através de um juntar modelo vai ser você está melhor aposta aqui. Ele permite que o modelo List se preocupar com a Lista lógica eo modelo Movie se preocupar com a lógica Filme. Você pode criar um Nomination (nome não é o maior, mas você sabe o que quero dizer) modelo para lidar com a relação entre filmes e listas, e quando há um limite de 5, você poderia simplesmente limitar o número de indicações que você puxar para trás.

Existem algumas razões pelas quais eu acho que esta abordagem é melhor.

Em primeiro lugar, supondo que você quer ser capaz de atravessar as relações em ambos os sentidos (movie.lists e list.movies), a abordagem coluna 5 vai ser muito mais confuso.

Enquanto que seria muito melhor para ActiveRecord para relacionamentos apoio has n, não faz, e assim você estará lutando contra o quadro em que um. Além disso, a relação has n parece um frágil bit para mim nesta situação. Eu não vi esse tipo de implementação tirou em ActiveRecord, embora eu estaria realmente interessado em ver isso acontecer. :)

Eu suponho que você quer dizer "implementar" em vez de "modelo"? A modelagem é muito fácil em UML, por exemplo, onde você tem uma entidade Pessoa que é composta de 5 entidades de cinema.

Mas a dificuldade vem quando você diz has_one, vai has_5. Se é um valor escalar simples, has_one é talvez uma propriedade sobre a entidade pai. Has_5 é provavelmente 2 entidades relacionadas umas às outras através de um "é composta de" relacionamento em UML.

A principal questão a resposta é, provavelmente, "você pode garantir que ele será sempre 'Top 5'?" Se sim, modelá-lo com colunas, como você mencionou. Se não, modelá-lo com outra entidade.

Outra questão é, talvez, "Quão fácil será para refatorar?" Se é simples, Parreira, comece com 5 colunas e refatorar para entidades separadas se ele nunca muda.

Como de costume, "melhor" é dependente do ambiente empresarial e técnica.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top