Domanda

Mi chiedevo quale sia il modo migliore per modellare una relazione in cui un oggetto è associato esattamente con n oggetti di un'altra classe. Voglio estendere la relazione has_one a un valore specifico di n.

Ad esempio, una TopFiveMoviesList appartiene all'utente e contiene esattamente cinque film. Immagino che la tabella sql sottostante avrebbe campi come movie_id_1, movie_id_2, ... movie_id_5.

So che potrei fare una relazione has_many e limitare il numero di figli a livello di modello, ma preferirei non avere una tabella intermedia.

È stato utile?

Soluzione

Il mio primo istinto sarebbe quello di utilizzare una tabella di join, ma se ciò non fosse auspicabile le colonne User.movie [1-5] _id si adatterebbero al conto. (Penso che movie1_id si adatti meglio alla convenzione Rails rispetto a movie_id_1 .)

Dato che hai taggato questo Rails e ActiveRecord, aggiungerò un codice modello completamente non testato e probabilmente un po 'sbagliato alla mia risposta. :)

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

Potresti avvolgere quella riga in un metodo in stile macro, ma a meno che non sia un modello comune per la tua applicazione, probabilmente questo renderà il tuo codice più difficile da leggere con un piccolo vantaggio DRY.

Potresti anche voler aggiungere convalide per assicurarti che non ci siano film duplicati nell'elenco di un utente.

Associare la tua classe di film ai tuoi utenti è simile.

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

(Certo che users_list_as_top_anything sarebbe probabilmente meglio scritto come SQL esplicito. Oggi sono pigro.)

Altri suggerimenti

Penso che implementare questo modello attraverso un modello di join sarà la soluzione migliore qui. Permette al modello List di preoccuparsi della logica di List e al modello Movie di preoccuparsi della logica di Movie. Puoi creare un modello Nomination (il nome non è il massimo, ma sai cosa intendo) per gestire la relazione tra film ed elenchi e quando c'è un limite di 5, puoi semplicemente limitare numero di nomination che ritiri.

Ci sono alcuni motivi per cui penso che questo approccio sia migliore.

Innanzitutto, supponendo che tu voglia essere in grado di attraversare le relazioni in entrambi i modi ( movie.lists e list.movies ), l'approccio a 5 colonne sarà molto Messier.

Anche se sarebbe molto meglio per ActiveRecord supportare ha n relazioni, non è così, e quindi combatterai il framework su quello. Inoltre, la relazione ha n mi sembra un po 'fragile in questa situazione. Non ho visto quel tipo di implementazione decollata in ActiveRecord, anche se sarei davvero interessato a vederlo accadere. :)

Suppongo che intendi " implementa " anziché "modello"? La modellazione è abbastanza semplice in UML, diciamo, dove hai un'entità Person che è composta da 5 entità Movie.

Ma la difficoltà arriva quando dici has_one, andando a has_5. Se è un semplice valore scalare, has_one è forse una proprietà sull'entità padre. Has_5 è probabilmente 2 entità correlate tra loro attraverso un "è costituito da" relazione in UML.

La domanda principale a cui rispondere è probabilmente, "Puoi garantire che sarà sempre la" Top 5 "? " Se sì, modellalo con le colonne, come hai detto. Se no, modellalo con un'altra entità.

Un'altra domanda è forse, "Quanto sarà facile riformattare?" Se è semplice, diamine, inizia con 5 colonne e refactoring per separare le entità se dovesse mai cambiare.

Come al solito, "migliore" dipende dall'ambiente aziendale e tecnico.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top