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:
- Jedan na jedan
- Jedan na više
- Više na više
- 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.
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.
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.
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.
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.
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:
- Ne postoji model koji se tako zove.
- 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!