Sådan fungerer en has_many :through association i praksis
On januar 3, 2022 by adminNår du begynder at arbejde med Rails og ActiveRecord, kan det være svært at forstå begrebet has_many :through association, og endnu vigtigere, hvordan de kan bruges i din Rails-app.
“lad os sige, at jeg har group, member, memberships… hvordan bruger jeg så rent faktisk dette i mine modeller, controllere og views?”
“Jeg bruger en has_many :through relation, som ser ud til at virke. Jeg har nu brug for en formular, som jeg kan rendere for at få brugerne til at tilmelde sig eller forlade gruppen.”
Først og fremmest bør du være rimelig sikker på, at en has_many :through-forbindelse er et godt valg til dit app-design. Hvis du antager, at du er det, kan du her se, hvordan du kan omsætte den i praksis.
Sæt, at du bygger en app med Brugere og grupper, og du ønsker at bygge en formular, hvor en given bruger kan tilmelde sig eller forlade en hvilken som helst gruppe. Du har valgt at tilknytte dine brugere og grupper via tabellen Membership.
Dine modeller er struktureret således:
class User < ActiveRecord::Base has_many :memberships has_many :groups, through: :membershipsendclass Group < ActiveRecord::Base has_many :memberships has_many :users, through: :membershipsendclass Membership < ActiveRecord::Base belongs_to :user belongs_to :groupend
Jeg synes altid, at det er nyttigt, før jeg begynder at skrive mine controllere eller views, at tænke igennem, hvad jeg vil opnå, og bruge Rails-konsollen til at sikre, at jeg er på rette vej. Med andre ord, jeg forsøger at komme med et med et slutmål, og derefter arbejde baglæns ved hjælp af Rails-konsollen for at finde ud af min løsning.
Så, eftersom vi ønsker at gengive en formular, der giver en bruger mulighed for at tilmelde sig eller forlade en gruppe, bør vi spørge os selv, “hvad betyder det at få en bruger til at tilmelde sig en gruppe?”
For så vidt angår databasen betyder det i bund og grund, at tabellen Membership
vil have en række med kolonnerne user_id
og group_id
, der svarer til vores givne bruger og gruppe. Vores opgave er så at orkestrere tingene således, at når brugeren klikker “submit” på sin formular, så ender Membership
tabellen med en ny række (eller rækker) med de korrekte user_id
og group_id
værdier.
I den formular/view, som vi renderer for brugeren, har vi brug for en måde, hvorpå brugeren kan vælge hvilke grupper de ønsker at tilmelde sig. Og i controlleren ønsker vi at udtrække de valg, som brugeren har foretaget i formularen, og bruge disse valg til at oprette nye rækker i tabellen Membership
.
Først, forestil dig, at du havde et user_id
og et group_id
, hvordan ville du så oprette den nye række i tabellen Medlemskab? ActiveRecord gør det nemt. Det, vi ønsker at gøre, er for en given User
-post at tilføje et “medlemskab” til den, så når vi siger @user.groups
, får vi en liste over grupper tilbage, som omfatter den gruppe, vi lige har tilføjet. Hvis du gør dette:
#assuming @user is your User [email protected] << Group.find(group_id)#if you have a list of group_ids(something like ), you can also do:@user.group_ids << group_ids
Dette stykke kode vil automatisk oprette en ny række i tabellen “Membership” med de rigtige group_id
og user_id
. Og når du nu bruger @user.groups
, får du tilbage en liste over de grupper, som du har tilføjet. Prøv ovenstående i din Rails-konsol for at få ekstra sikkerhed.
Kig i Rails-guiden nedenfor for at få flere oplysninger om, hvilke metoder ActiveRecord giver dig, når du bruger has_many :through
.
Jeg går ud fra, at du har en eller anden form for godkendelse oprettet i din app, som giver dig adgang til metoden current_user
. Vi skal bruge denne metode til at få vores user_id
, via et simpelt current_user.id
-opkald. Når du har din bruger (med noget som @user = User.find(current_user.id)
), kan du bruge ovenstående kode til at tilføje grupper.
Det næste spørgsmål er, hvordan du skriver din visning, så den videregiver group_id
-værdierne til controlleren?
Hvordan du skriver din visning afhænger helt af det flow, du forventer, at dine brugere går igennem, og andre faktorer i din app. Lad os sige, at du beslutter dig for at give din bruger en liste over afkrydsningsfelter med en liste over de grupper, de kan tilmelde sig eller forlade. Her er en simpel måde at opnå det på:
<% Group.all.each do |group| %> <%= check_box_tag "user", group.id, @user.group_ids.include?(group.id) %> <%= group.name %> <br /><% end %>
Brugen af check_box_tag
kræver nok en forklaring.
Den første parameter "user"
fortæller Rails, at det skal gruppere alle afkrydsningsfelter med dette ID sammen og sende det til controlleren som et Array. Det betyder, at du i din controller kan lave params
og få en fin Ruby Array med alle de group_ids
, som brugeren har valgt.
Den sidste parameter sikrer bare, at enhver gruppe, som brugeren i øjeblikket tilhører, markeres, når formularen gengives.
Overstående skulle få dig i gang med at bruge has_many :through i din Rails-app, men afhængigt af, hvad din app gør, er jeg ret sikker på, at du vil løbe ind i problemer, som ikke er dækket i dette indlæg. Så hvis du stadig sidder fast, kan du tjekke følgende:
1) Tjek denne fantastiske Rails-cast, som tager dig gennem hele spektret af brugen af has_many :through. Hvis du ikke allerede har gjort det, vil jeg stærkt anbefale dig at få dig en konto på RailsCasts.
2) Rails ActiveRecord Guide on has_many :through
Skriv et svar