A great way to learn is by trying to explain, so as part of my rails association learning process, I’ll attempt to explain a slightly more complex bi-directional association between two models. This is part of the “Building advanced forms” exercise of The Odin Project.
Objective: I want to build a proof of concept flight-booking app, and the first requirement is to create associations between an Airport model and a Flight model.
- Each airport will have many flights, and each flight will belong to an airport. Airports have 3-letter international codes, e.g. LIS for the Lisbon international airport.
- Each flight, however, will need both origin and destination airports.
- Each airport will have departing and arriving flights.
So what does this mean for our model associations?
The airport model has a Code variable, which is a string field, such as “SFO” or “LIS”. This association creates the
Flight.find(1).airport methods which let you query Airport flights and flight airports, respectively.
Now we need to separate flight airports into origin airports and destination airports, since flights fly from A to B. We will call these
to_airport to make the relationships easier to understand. The Flight associations are changed to:
This means that each flight will have a from_airport and a to_airport, but that these are simply different instances of the Airport model. This means we have to create a
from_airport_id field and a
to_airport_id field in the Flight model in order to associate each Flight to two airports, the origin and destination ones.
The next step is to add departures and arrivals to the airport model. A departing flight of an airport is a flight whose from_airport field corresponds to the airport id of that airport. An arriving flight is a flight whose to_airport field corresponds to the airport’s id.
So what we want to do is to call these flights
arriving_flights, and associate them to a
from_airport_id field and a
to_airport_id field, in the Flight model. This association is done by setting a
In narrative form, this means that Airports have flights, and they are either departing or arriving depending on whether the
to_airport_id field corresponds to the airport ID.
Likewise, Flights have “from airports” (origins) and “to airports” (destinations), which is set by the ids in
We can now use methods such as
Airport.first.departing_flights to get the departing flights of the first airport, and
Flight.first.from_airport to get the origin of the first flight.
If we wanted to, we could change
destination but we’ll leave it as it is in the interest of simplicity. We could also add
inverse_of to make database querying more efficient, but we’ll also leave that out as it’s not a strict requirement.
And that’s it. Our app now has Airports with many departing and arriving flights, as well as Flights with origins and destinations.
— — —
Hope this was insightful. Feedback is always welcome.