模型(#...)预期,使用select标签时出现String(#...)错误

时间:2017-04-18 14:52:00

标签: ruby-on-rails ruby ruby-on-rails-5 has-one

我搭建了一个简单的例子来说明我遇到的问题。 在这个例子中,我有一个Starship和一个Pilot。我希望能够在创建时将现有的飞行员分配给星舰。

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

飞船/ _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

参数哈希

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

我收到此错误

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

我看到我的飞行员在哈希中被发送为一个字符串,但我似乎并没有找到我应该如何做到这一点。

3 个答案:

答案 0 :(得分:5)

使用集合选择并仅返回导频ID。

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

请注意,您需要更改starship_params

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

为:pilot_id

添加attr_accessor
class Starship < ApplicationRecord
  attr_accessor :pilot_id

修改您的创建如下...

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

答案 1 :(得分:1)

您有一对一的可选关系。只列出所有飞行员都可以覆盖它们。创建一个新的飞行员比从整个列表中分配一个更好。

如果您想使用,请尝试使用此代码。请记住,如果您想转移飞行员,也可以使用下面的Pilot.pluck(:id)

<div class="field">
  <%= f.label :pilot_id %>
  <%= f.select :pilot_id, Pilot.where('starship_id is NULL').pluck(:id) %>
</div>

现在使用starship_controller创建方法 写

def create
    @starship = Starship.new(starship_params)
    pilot = @starship.build_pilot
    pilot.id= params[:starship][:pilot_id]
    pilot.reload
    respond_to do |format|
      if @starship.save
        format.html { redirect_to root_path, notice: 'Starship successfully created.' }
       else
         format.html { redirect_to root_path, notice: 'Error occured.' }
       end
end

你的强大的参数应该是

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

希望这会有所帮助......

答案 2 :(得分:0)

  

只需将以下代码替换为您的代码,您就可以了。

<%= f.label :pilot %>
<%= f.select :pilot, Pilot.all.map{ |p| [p.name, p.id] } %>

这将在选择下拉列表中显示飞行员姓名,并在保存时保存特定飞行员的ID。