Tutorial
Step 7: Many to Many
Let’s add a Team
relationship: a Team
can have many Employee
s, an
Employee
can have many Team
s. Let’s also say a Team
belongs to a
Department
.
id | department_id | name |
---|---|---|
1 | 1 | The A Team |
2 | 1 | The B Team |
3 | 2 | The C Team |
To satisfy this many-to-many use case, we’ll need a join model,
TeamMembership
:
id | team_id | employee_id |
---|---|---|
1 | 1 | 1 |
2 | 2 | 1 |
3 | 3 | 2 |
The Rails Stuff 🚂
Graphiti supports has_many :through
:
Finally, we’ll need a new seed file to handle these new associations:
The Graphiti Stuff 🎨
Let’s flesh out our TeamResource
:
The trick here is the many_to_many
relationship. Let’s add the reverse
as well:
And for good measure:
We can now get all the usual functionality: fetch Employees and their Teams in a single request (or vice versa).
Digging Deeper 🧐
The many_to_many
relationship is the only one where Graphiti modifies
a separate Resource “under the hood”. When we said many_to_many
:employees
, the EmployeeResource
got a team_id
filter, and
many_to_many :teams
created an employee_id
filter on TeamResource
.
This is because the logic is more complex than the default use case. We
don’t have a simple WHERE
clause; we need to join tables and look at
the appropriate primary/foreign keys. If the name of your API
association doesn’t match the name of your ActiveRecord association, try
has_many :things, as: :my_activerecord_relationship
to make the
introspection work correctly - or, write your own filter.
Sometimes you’ll have multiple levels of has_many :through
. In this
case, a simple many_to_many
isn’t enough - check out our Hopping
Relationships Cookbook.
Think hard before reaching for many_to_many
. Imagine one Team is the
“primary” Team for an Employee. We’d add a primary
boolean column to
the team_memberships
table…but that table isn’t exposed to the API!
Consider if there’s a hidden domain concept there.