1

So im working through the Odin Project's "Flight Booker" project. https://www.theodinproject.com/courses/ruby-on-rails/lessons/building-advanced-forms. Which essentially is what it sounds like and im running into a problem with passing nested attributes.

First and foremost the Relevant Models:

class Booking < ApplicationRecord
  belongs_to :passenger
  belongs_to :flight
  accepts_nested_attributes_for :passenger
end

class Flight < ApplicationRecord
  has_many :bookings, dependent: :destroy
  has_many :passengers, through: :bookings
  belongs_to :to_airport, class_name: 'Airport', foreign_key: 'origin_id'
  belongs_to :from_airport, class_name: 'Airport', foreign_key: 'destination_id'
end

class Passenger < ApplicationRecord
  has_many :bookings, dependent: :destroy
  has_many :flights, through: :bookings
end

The passenger schema just contains an email and name for right now. But the problem is when I pass the information to the "booking" controller. Here is my "New" form for booking.

<%= form_for @booking do |f| %>
  <%= f.hidden_field :flight_id, value: params[:booking][:flight_num] %>
  <%= f.hidden_field :passengers_num, value: params[:booking][:passengers_num] %>
  <% params[:booking][:passengers_num].to_i.times do |passenger| %>
    <%= fields_for :passenger  do |passenger| %>
      <%= passenger.label :name, 'Name', class: "Label" %>
      <%= passenger.text_field :name %>
      <%= passenger.label :email, 'email', class: "Label" %>
      <%= passenger.email_field :email %>
    <% end %>
  <% end %>
  <%= f.submit "Book Flight" %>
<% end %>

(Ignore the hidden fields for now, they are passed from the "Flights" search page and Im getting those just fine.)

So I am getting the multiple forms (name and email fields) but when I "Submit" I am only getting parameters for the last field sets. (So if there are 3 sets of name/email fields, I only get parameters for the last one).

It's possible im not understanding the fields_for however as I can't find a ton of good examples.

Thanks!

1 Answer 1

2

There could be many issues with your implementation...I'll layout a few...

Move <% params[:booking][:passengers_num].to_i.times do |passenger| %> logic into the new action of your bookings controller...ie

def new
  @booking = Booking.new
  3.times { @booking.passengers.new } # or whatever your logic is to display x amount of passenger fields
end

Make sure that in your bookings controller you are permitting the nested attributes like this...

params.require(:booking).permit(passengers_attributes: [:name, :email])

As far as the form, you'll need to treat it like a form within a form (makes sense...nested attributes created from a nested form!) and use the block variable...like this

<ul>
  <%= f.fields_for :passengers do |passenger_form| %>
    <li>
      <%= passenger_form.label :name
      <%= passenger_form.text_field :name %>
    </li>
    <!-- other permitted fields -->
  <% end %>
</ul>
Sign up to request clarification or add additional context in comments.

4 Comments

Im confused on the 3.times { @book.passengers.new} I don't see how that would work? Sidenote how would you pass multiple passenger_attributes into a new booking create in console?
The new action is intended to instantiate objects before they are created. So, if you have nested attributes, you need to instantiate them (all of them) before they are created from the form. In order to use the console to assign nested attributes, you need to use an array of hashes...ie....passengers_attributes: [ {name: "something", email: "[email protected]}, {name: "Something Else", email: "[email protected]"}]
I know the number ahead of time fortunately due to a previous form. Also I tried doing exactly that in the console and it wouldn't work for some reason.
did you add an ending " after the first hash in passengers_attributes (ie email: "[email protected]"...my bad)? I tested it and it is working. If that doesn't work, post the error message you are getting and we can go from there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.