ruby-on-railsrubyruby-on-rails-5has-one

Model(#...) expected, got String(#...) error when using select tag


I scaffolded a simple example to illustrate a problem I'm having. In this example I have a Starship and a Pilot. I want to be able to assign an existing pilot to the starship at creation.

starship.rb

class Starship < ApplicationRecord
  has_one :pilot

  validates :name, presence: true
end

pilot.rb

class Pilot < ApplicationRecord
  belongs_to :starship, optional: true

  validates :name, presence: true
end

starships/_form.html.erb

<div class="field">
  <%= f.label :pilot %>
  <%= f.select :pilot, Pilot.all %>
</div>

starships_controller.rb

  def starship_params
    params.require(:starship).permit(:name, :pilot)
  end

params hash

{"name"=>"Nostromo", "pilot"=>"#<Pilot:0x007f85ff547f90>"}

And I get this error

Pilot(#70106745549840) expected, got String(#70106709663840)

I see that my pilot is sent as a string in the hash, but I don't seem to find how I am supposed to do it otherwise.


Solution

  • Use collection select and return just the pilot id.

    <%= f.collection_select(:pilot_id, Pilot.all, :id, :name) %>
    

    Note that you'll need to change your starship_params

      def starship_params
        params.require(:starship).permit(:name, :pilot_id)
      end
    

    Add an attr_accessor for :pilot_id

    class Starship < ApplicationRecord
      attr_accessor :pilot_id
    

    Modify your create as follows...

    def create
      @starship = Starship.new(starship_params)
      @starship.pilot = Pilot.find(@starship.pilot_id)
      respond_to do |format|
        ...