Flight - belongs_to :departure_airport
, Airport has_many :departing_flights
.
I am trying to create a drop down select form element within a Rails form_with
where the association's :city value for each option is an attribute on an association:
View form code - flight#index:
<%= form_with(url: flights_path, method: :get) do |form| %>
<div>
<%= form.label :departure_airport, 'Departure Airport' %>
<%= form.collection_select :departure_airport, @flights, :departure_airport_id, :departure_airport.city, prompt: 'Select Departure Airport' %>
</div>
<div>
<%= form.submit 'Search Flights' %>
</div>
<% end %>
Flight controller code:
class FlightsController < ApplicationController
def index
@flights = Flight.all
end
end
Flight.rb:
class Flight < ApplicationRecord
belongs_to :departure_airport, class_name: 'Airport'
validates_presence_of :departure_airport
end
Airport.rb:
class Airport < ApplicationRecord
has_many :departing_flights, class_name: 'Flight', foreign_key: 'departure_airport_id'
end
I can see that the association is working because the html displays the actual airport object reference string as the name/label for each dropdown option. But for the life of me I cannot get the each option to be named with an attribute on the association:
Html rendered form extract:
<form action="/flights" accept-charset="UTF-8" method="get">
<div>
<label for="departure_airport">Departure Airport</label>
<select name="departure_airport" id="departure_airport"><option value="">Select Departure Airport</option>
<option value="8">#<Airport:0x00000001126f0730></option>
<option value="60">#<Airport:0x0000000112728630></option>
<option value="47">#<Airport:0x0000000112713140></option>
<option value="33">#<Airport:0x00000001126fbdd8></option>
etc ...
<option value="42">#<Airport:0x0000000112c9b568></option></select>
</div>
<div>
<input type="submit" name="commit" value="Search Flights" data-disable-with="Search Flights">
</div>
</form>
I've tried any of the various attrs/columns of an airport object (e.g. :departure_airport.name
, :departure_airport.country
) and none will display as the label for an individual option.
Can anyone see what I'm doing wrong here?
The associations are definitely there are model level, as illustrated by this rails console object & association querying:
3.1.2 :012 > f = Flight.first
Flight Load (1.4ms) SELECT "flights".* FROM "flights" ORDER BY "flights"."id" ASC LIMIT $1 [["LIMIT", 1]]
=>
#<Flight:0x000000010280c9a8
...
3.1.2 :013 > f.departure_airport_id
=> 8
3.1.2 :014 > f.departure_airport.name
Airport Load (1.0ms) SELECT "airports".* FROM "airports" WHERE "airports"."id" = $1 LIMIT $2 [["id", 8], ["LIMIT", 1]]
=> "Bordeaux Airport"
3.1.2 :015 > f.departure_airport.city
=> "Bordeaux"
3.1.2 :016 > f.departure_airport.country
=> "France"
3.1.2 :017 >
:departure_airport.city
this calls city
method on a Symbol :departure_airport
, not the association.
You have to use attributes and methods that are in Flight
model:
<%= form.collection_select :departure_airport_id, @flights,
:departure_airport_id,
:departure_airport_city
%>
class Flight < ApplicationRecord
belongs_to :departure_airport, class_name: 'Airport'
# this validation is redundant, belongs_to association is required by default
# validates_presence_of :departure_airport
# this is the same as
#
# def departure_airport_city
# departure_airport.city
# end
#
delegate :city, to: :departure_airport, prefix: true
end