Rails Asocijacije

Rails Asocijacije

Asocijacija je veza između dva modela aktivnog zapisa. Puno olakšava izvođenje različitih operacija na zapisima u vašem kodu. Podelit ćemo udruženja u četiri kategorije:

  1. Jedan na jedan
  2. Jedan na više
  3. Više na više
  4. Polimorfni jedan na više

Ako ste novi u Rubi on Rails, obavezno pripremite svoj projekat i proverite kako da kreirate modele u Rails-u.

Jedan na jedan

Kada postavljate odnose jedan-na-jedan, kažete da zapis sadrži tačno jednu instancu drugog modela. Na primer, ako svaki korisnik u vašoj aplikaciji ima samo jedan profil, svoje modele možete opisati kao:

class User < ApplicationRecord       class Profile < ApplicationRecord
  has_one :profile                     belongs_to :user
end  

Jedan od modela u datoj relaciji imaće poziv metode has_one, a drugi će pripadati belong_to. Koristi se za opisivanje koji model sadrži referencu stranog ključa za drugi, u našem slučaju to je model profila.
alt
Pokrijte svoje asocijacije testovima RSpec kako biste bili sigurni da sve funkcioniše onako kako vi želite.

Jedan Na Više

Asocijacija jedan prema više je najčešće korišćena veza. Ova asocijacija ukazuje na to da svaka instanca modela A može imati nula ili više primeraka drugog modela B, a model B pripada samo jednom modelu A.

Proverimo to na primeru. Želimo da napravimo aplikaciju u koju korisnici mogu da pišu više priča, naši modeli bi trebali izgledati ovako:

class User < ApplicationRecord       class Story < ApplicationRecord
  has_many :stories                     belongs_to :user
end                                  end

Ovde je odlučivanje koji model će imati has_many, a koji belong_to važnije nego u relacijama jedan na jedan, jer menja logiku vaše aplikacije. U oba slučaja, drugi model sadrži jednu referencu na prvi model u obliku stranog ključa.

Drugi model ne zna za odnos prvog modela - nije svestan da li se prvi model odnosi na više njih ili samo na jednog.
alt
Testovi za asocijacije postaju složeniji da napišu više odnosa koje stvarate. Trebalo bi da proverite kako da napravite sopstvene fabrike asocijacija kako biste olakšali život testiranju.

Više Na Više

Asocijacije „više prema više“ su malo složenije i njima se može upravljati na dva načina, „has i belongs to many“ i „has many through“ veze.

Has I Belongs To Many

Asocijacija has_and_belongs_to_many stvara direktnu vezu više na više sa drugim modelom. Jednostavniji je od drugog, jer zahteva samo pozivanje has_and_belongs_to_many sa oba modela.

alt

Primer: Recimo, korisnik može imati mnogo različitih uloga i ista uloga može sadržati mnogo korisnika, naši modeli bi bili ovakvi:

class User < ApplicationRecord       class Role < ApplicationRecord
  has_and_belongs_to_many :roles       has_and_belongs_to_many :users
end                                  end

Morate da napravite tabelu pridruživanja da bi ovo udruženje funkcionisalo. To je tabela koja povezuje dva različita modela. Tabela spajanja kreira se pomoću rails funkcije create_join_table: user,: role u odvojenoj migraciji.

class CreateUserRoles < ActiveRecord::Migration
  def change
    create_table :user_roles, id: false do |t|
      t.references :user, index: true, foreign_key: true
      t.references :role, index: true, foreign_key: true
    end
  end
end

Ovo je vrlo jednostavan pristup, ali nemate direktan pristup povezanim objektima, možete držati samo reference na dva modela i ništa drugo.

Has Many Through

Drugi način da se definiše asocijacija više na više je korišćenje tipa asocijacije has many through. Ovde definišemo zaseban model, koji će upravljati tom vezom između dva različita.
alt

Umesto da idete na novi primer, trebalo bi da pogledate ovaj! Objašnjava sve što biste trebali znati o ovoj asocijaciji.

Na primeru asocijacije has_and_belongs_to_many, ovaj put bi tri modela trebalo napisati ovako:

class User < ApplicationRecord
  has_many :user_roles
  has_many :roles, through: :user_roles
end
 
class UserRoles < ApplicationRecord
  belongs_to :user
  belongs_to :role
end
 
class Role < ApplicationRecord
  has_many :user_roles
  has_many :users, through: :user_roles
end

Ova asocijacija će vam omogućiti da radite stvari poput user.role i da dobijete listu svih povezanih instanci drugog modela. Takođe će vam omogućiti pristup podacima specifičnim za vezu između prvog i drugog modela.

Polymorphic

Polimorfne asocijacije su najnaprednije asocijacije koja su nam dostupne. Možete ga koristiti kada imate model koji može pripadati mnogim različitim modelima na jednoj asocijaciji.
alt

Zamislimo da želite da možete da pišete komentare za korisnike i priče. Želite da oba modela budu komentarisana. Evo kako bi se ovo moglo deklarisati:

class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
end
 
class Employee < ApplicationRecord
  has_many :comment, as: :commentable
end
 
class Product < ApplicationRecord
  has_many :comment, as: :commentable
end

Možete smatrati polimorfnu deklaraciju belongs_to podešavanjem interfejsa koji bilo koji drugi model može koristiti. Da biste deklarisali polimorfni interfejs, u modelu morate deklarisati i kolonu stranog ključa i kolonu tipa. Trebali biste pokrenuti migraciju nakon što završite.

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.text :body
      t.integer :commentable_id
      t.string :commentable_type
      t.timestamps
    end
 
    add_index :comments, :commentable_id
  end
end

Ova migracija se može pojednostaviti korišćenjem referenci:

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.text :body
      t.references :commentable, polymorphic: true, index: true
      t.timestamps
    end
  end
end

Dodatne Opcije

Postoji nekoliko dodatnih opcija koje možete koristiti prilikom definisanja odnosa između modela, obradićemo dve najčešće korišćene.

class_name

Ako se ime drugog modela ne može izvesti iz imena asocijacije, možete koristiti opciju: class_name da navedete ime modela. Više o ovome možete pročitati na RailsGuides.

Primer: Želite da belongs_to veza pozove autora, ali postoje dva problema:

  1. Ne postoji model koji se tako zove.
  2. U tabeli priče nedostaje polje author_id.

Lako popraviti! Da bi ovo funkcionisalo i da bi zaustavili neuspeh testova, samo treba da navedete :foreign_key i stvarno ime klase:

class Story < ApplicationRecord
  belongs_to :author, class_name: 'User', foreign_key: 'user_id'
end

dependent

Ovu opciju možete da koristite kada se želite rešiti osirotelih zapisa jer oni mogu dovesti do različitih problema. Osiroteli zapisi se kreiraju kada izbrišemo ili uništimo model A koji je povezan sa modelom B, ali model B nije uklonjen u procesu.

class User < ApplicationRecord
  has_many :stories, dependent: :destroy
end

Primer: Pretpostavimo da je korisnik koji se zove Marija napisao puno priča. Zatim smo Mariju izbrisali iz baze podataka, ali u pričama je kolona user_id i dalje postavljena na Marijin ID. Te se priče nazivaju osirotelim zapisima.

Hvala vam za čitanje!

Obavezno se pretplatite ako želite da ostanete u više prema više vezi sa našim člancima!