Create a one-to-many association between two model classes

❮ Back Next ❯

In this step, you will learn how to add a class association to your model code and how to create association links between your seed objects.

We will specifically add the “departure” association between the Airport and Flight classes:

As per the diagram:

Add a foreign key column

First, we must add a departure_airport_id foreign key column to the flights database table to encode the relationship between each flight and the airport from which it departs.

Generate a partially complete migration script that adds the column by running this rails generate migration command in the terminal:

rails g migration AddAirportFkColToFlights departure_airport:references

Note that a migration script has been generated with a name similar to db/migrate/20240217224312_add_airport_fk_col_to_flights.rb (the timestamp will be different).

Specify that the departure_airport_id foreign keys refer to id attributes in the airports database table by updating line 3 in the generated migration as follows using VS Code (especially note the to_table bit):

    add_reference :flights, :departure_airport, null: false, foreign_key: { to_table: :airports }

Reset the database and run the latest migrations by running this command in the terminal:

rails db:migrate:reset

Confirm that the departure_airport_id column has been added to the flights table by running this command in the terminal:

psql --command="SELECT * FROM flights" practice_app_development

Note that the departure_airport_id column is now present in the flights table

Add has_many/belongs_to declarations to the model classes

Add a has_many declaration to the Airport class by editing app/models/airport.rb in VS Code as follows (comments not shown):

class Airport < ApplicationRecord

  has_many(
    :departure_flights,
    class_name: 'Flight',
    foreign_key: 'departure_airport_id',
    inverse_of: :departure_airport,
    dependent: :destroy
  )

end

Here is an explanation of each of the above arguments:

Add a belongs_to declaration to the Flight class by editing app/models/flight.rb in VS Code as follows (comments not shown):

class Flight < ApplicationRecord

  belongs_to(
    :departure_airport,
    class_name: 'Airport',
    foreign_key: 'departure_airport_id',
    inverse_of: :departure_flights
  )

end

Here is an explanation of each of the above arguments:

Update the seed data to use the association

The belongs_to declaration automatically adds a validation to the Flight class such that each Flight must belong to a corresponding Airport. If the departure_airport is set to nil, a validation error will result. This situation requires us to update our seeds.rb script, lest running rails db:seed would result in errors.

Assign each seed Flight object a departure Airport object by editing the calls to Flight.create! in the db/seeds.rb file as follows using VS Code (note the addition of departure_airport arguments):

# Flights

mem_atl = Flight.create!(
  departure_time: DateTime.strptime('03-02-2028 09:15:00 AM', '%m-%d-%Y %I:%M:%S %p'),
  arrival_time: DateTime.strptime('03-02-2028 11:05:00 AM', '%m-%d-%Y %I:%M:%S %p'),
  departure_airport: mem
)

mem_lax = Flight.create(
  departure_time: DateTime.strptime('01-18-2029 06:42:00 AM', '%m-%d-%Y %I:%M:%S %p'),
  arrival_time: DateTime.strptime('01-18-2029 01:16:00 PM', '%m-%d-%Y %I:%M:%S %p'),
  departure_airport: mem
)

atl_lax = Flight.create(
  departure_time: DateTime.strptime('04-04-2029 10:33:00 AM', '%m-%d-%Y %I:%M:%S %p'),
  arrival_time: DateTime.strptime('04-04-2029 05:00:00 PM', '%m-%d-%Y %I:%M:%S %p'),
  departure_airport: atl
)

Run the seeds.rb script by running this command in the terminal:

rails db:seed

As a result of running the seeds.rb script, the Flight and Airport objects should now be configured as follows:

Confirm that the changes made above work correctly by launching the Rails console in the terminal:

rails console

Check that Flight objects saved in the database have correct values saved in their departure_airport_id foreign key attributes:

Flight.all

For each Flight object outputted, note the object’s id attribute value and its departure_airport_id attribute value.

The correct values should be as follows:

Confirm that the has_many declaration works correctly by testing the generated Airport#departure_flights method. We perform the test on the MEM airport (id of 1):

Airport.find(1).departure_flights

Note that an array that consists of two Flight objects (id values of 1 and 2) is outputted.

Confirm that the belongs_to declaration works correctly by testing the generated Flight#departure_airport method. We perform the test on the flight with id of 1:

Flight.find(1).departure_airport

Note that the MEM Airport object is outputted.

Exit out of the Rails console to get back to the UNIX prompt:

exit

❮ Back Next ❯