Hur en has_many :through association fungerar i praktiken
On januari 3, 2022 by adminNär du börjar arbeta med Rails och ActiveRecord kan det vara svårt att förstå konceptet med has_many :through associationer, och framför allt hur de kan användas i din Rails-app.
”Låt oss säga att jag har group, member, memberships… hur använder jag sedan detta i mina modeller, kontrollanter och vyer?”
”Jag använder en has_many :through-relation som verkar fungera. Jag behöver nu ett formulär som jag kan rendera för att få användare att gå med i eller lämna gruppen.”
För det första bör du vara ganska säker på att en has_many :through-association är ett bra val för din appdesign. Om du antar att du är det, så kan du här se hur du kan omsätta det i praktiken.
Säg att du bygger en app med Users and Groups och att du vill skapa ett formulär där en viss användare kan gå med i eller lämna vilken grupp som helst. Du har valt att associera dina användare och grupper genom tabellen Membership.
Dina modeller är strukturerade så här:
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
Jag tycker alltid att det är bra att innan jag börjar skriva mina controllers eller vyer, att tänka igenom vad jag vill åstadkomma och använda Rails-konsolen för att se till att jag är på rätt väg. Med andra ord försöker jag komma fram till ett slutmål och sedan arbeta bakåt med hjälp av Rails-konsolen för att komma fram till min lösning.
Så, med tanke på att vi vill göra ett formulär som gör det möjligt för en användare att gå med i eller lämna en grupp, bör vi fråga oss själva: ”Vad innebär det att få en användare att gå med i en grupp?”
För databasen innebär det i huvudsak att tabellen Membership
kommer att ha en rad med kolumnerna user_id
och group_id
som motsvarar vår givna användare och grupp. Vår uppgift är sedan att organisera saker och ting så att när användaren klickar på ”submit” i sitt formulär, får Membership
-tabellen en ny rad (eller rader) med de korrekta user_id
– och group_id
-värdena.
I formuläret/visningen som vi visar för användaren behöver vi ett sätt som gör det möjligt för användaren att välja vilka grupper han/hon vill ansluta sig till. Och i kontrollern vill vi extrahera de val som användaren gjorde i formuläret och använda dessa val för att skapa nya rader i tabellen Membership
.
För det första, tänk dig att du hade ett user_id
och ett group_id
, hur skulle du gå till väga för att skapa den nya raden i tabellen Membership? ActiveRecord gör det enkelt. Vad vi vill göra är att för en given User
-post lägga till ett ”medlemskap” till den, så att när vi säger @user.groups
får vi tillbaka en lista över grupper som inkluderar den grupp vi just lagt till. Om du gör så här:
#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
Denna kod kommer automatiskt att skapa en ny rad i tabellen Membership med rätt group_id
och user_id
. När du nu använder @user.groups
får du tillbaka en lista över de grupper som du har lagt till. För ökad säkerhet kan du prova ovanstående i din Rails-konsol.
Kolla in Rails-guiden nedan för mer information om vilka metoder ActiveRecord ger dig när du använder has_many :through
.
Jag utgår från att du har någon typ av autentisering inställd i din app, vilket ger dig tillgång till current_user
-metoden. Vi kommer att behöva den här metoden för att få vår user_id
, via ett enkelt current_user.id
-anrop. När du har din användare (med något som @user = User.find(current_user.id)
) kan du använda koden ovan för att lägga till grupper.
Nästa fråga är hur du skriver din vy så att den skickar group_id
-värdena till controllern?
Hur du skriver din vy beror helt och hållet på det flöde som du förväntar dig att dina användare ska gå igenom och andra faktorer i din app. Låt oss säga att du bestämmer dig för att ge din användare en lista med kryssrutor som listar de grupper de kan gå med i eller lämna. Här är ett enkelt sätt att åstadkomma det:
<% Group.all.each do |group| %> <%= check_box_tag "user", group.id, @user.group_ids.include?(group.id) %> <%= group.name %> <br /><% end %>
Användningen av check_box_tag
behöver förmodligen förklaras.
Den första parametern "user"
talar om för Rails att gruppera alla kryssrutor med det här ID:t tillsammans och skicka in det till kontrollern som en Array. Detta innebär att du i din controller kan göra params
och få en fin Ruby Array med alla group_ids
som användaren valde.
Den sista parametern ser bara till att alla grupper som användaren för tillfället tillhör kontrolleras när formuläret visas.
Ovanstående bör få dig att komma igång med att använda has_many :through i din Rails-app, men beroende på vad din app gör så är jag ganska säker på att du kommer att stöta på problem som inte täcks i detta inlägg. Så om du fortfarande sitter fast kan du kolla in följande:
1) Kolla in denna fantastiska Rails-cast som tar dig genom hela skalan av att använda has_many :through. Om du inte redan har gjort det rekommenderar jag starkt att du skaffar dig ett konto på RailsCasts.
2) Rails ActiveRecord Guide on has_many :through
Lämna ett svar