Per completare la panoramica delle relazioni fra i modelli introduciamo la relazione molti a molti. Supponiamo di voler associare ad ogni bookmark non una sola categoria, ma molte: il bookmark con url="http://ruby.html.it"
potrebbe essere associato tanto alla categoria "Ruby" quanto alla categoria "Programmazione".
Creiamo modello e file di migrazione per le categorie con
ruby script/generate model Category
e definiamo i campi che dovranno apparire nella tabella nel file di migrazione:
create_table :categories do |t| t.string :title t.text :description t.timestamps end
Aggiungiamo le validazioni relative al modello Category
nel file app/models/category.rb
e generiamo un nuovo modello con:
ruby script/generate model Categorization
La tabella del nuovo modello includerà due referenze esterne verso le tabelle bookmarks
e categories
con le colonne bookmark_id
e category_id
:
create_table :categorization do |t| t.integer :bookmark_id t.integer :category_id t.timestamps end
Modifichiamo quindi i modelli come segue:
class Bookmark < ActiveRecord::Base has_many :categories, :through => :categorizations # validazioni # ... end class Category < ActiveRecord::Base has_many :categories, :through => :categorizations # validazioni #... end Class Categorization < ActiveRecord::Base belongs_to :bookmark belongs_to :category end
Ora è possibile accedere alle categorie abbinate a un bookmark con @bookmark.categories
, e ai bookmark relativi ad una categoria con @category.bookmarks
. La manipolazione degli oggetti associati all'oggetto originale secondo la relazione molti a molti avviene in modo analogo alla manipolazione degli oggetti associati nella relazione uno a molti:
Operazione | Descrizione |
---|---|
@category.bookmarks << @my_bookmark |
aggiunge il bookmark alla lista dei boomark in relazione con la categoria |
@category.bookmarks.empty? |
restituisce true se non esistono bookmark in relazione con la categoria @category e false altrimenti |
@category.bookmarks.size |
resitituisce un intero pari al numero di bookmark collegati a quella categoria |
@category.bookmarks.delete |
elimina tutti bookmark dall'associazione |
È possibile specificare alcuni attributi relativi alla relazione molti a molti; supponiamo di voler specificare per ogni relazione fra bookmark e categoria un commento aggiuntivo. La migrazione per la creazione della tabella categorizations
si presenterà in questo modo:
create_table :categorization do |t| t.integer :bookmark_id t.integer :category_id t.string :comment t.timestamps end
Rendiamo esplicita la relazione con il modello Categorization
per i modelli Bookmark
e Category
:
class Bookmark < ActiveRecord::Base has_many :categories, :through => :categorizations has_many :categorizations # validazioni # ... end class Category < ActiveRecord::Base has_many :categories, :through => :categorizations has_many :categorizations # validazioni #... end Class Categorization < ActiveRecord::Base belongs_to :bookmark belongs_to :category end
Ora è possibile accedere al modello Categorization
sia dal modello Bookmark
che dal modello Category
; ad esempio con @bookmark.categorizations.first.comment
si accede all'attributo comment
della prima categorizzazione del bookmark.