如何为has_one关联创建视图?

所以,想象一下我有这个模型:

class Car has_one :engine end 

和发动机型号:

 class Engine belongs_to :car end 

当我为用户呈现表单时,他可以创建一辆新车,我只想让他从一个可用的引擎中选择(可用的引擎将在select ,由collection_select填充)。 问题是,如果我像这样构建字段:

  

当我尝试保存它时,我会得到一个AssociationTypeMismatch说它期望一个引擎,但它收到一个字符串。

这是这样做的吗?

 def create car = Car.new(params[:car]) engine = Engine.find(params[:engine]) car.engine = engine if car.save # redirect somewhere else # do something with the errors end end 

我总觉得Rails会自动完成将引擎与汽车相关联的东西,但我不知道如何让他这样做。

切换has_onebelongs_to关联是实现这一目的的唯一方法吗?

我迷路了,我觉得我在这里缺少一些非常基本的东西。

你应该使用engine_id

 <%= f.collection_select :engine_id, Engine.all, :id, :name %> 

UPD

至于Engine不是belongs_to Car所以你应该在这里使用嵌套属性。 这个截屏video对您非常有用:

Checkout api: http : //apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for

简介:

 class Car has_one :engine accepts_nested_attributes_for :engine end 

并以您的forms:

 <%= form_for @car ... do |f| %> ... <%= f.fields_for :engine do |b| %> <%= b.collection_select :id, Engine.all, :id, :name %> ... <% end %> ... <% end %> 

回答Kyle以前的回答 – 我喜欢这个简单的方法但是我必须按照以下方式更改它以适用于我的应用程序(我在Rails 3.2.13中)。 重点是地图需要返回一个数组 – 所以我认为这可能是一个拼写错误,将两个数组用逗号分隔。 我还将id属性的字符串引用更改为符号,但我不确定这是否必要或只是另一种选择。 从某种程度上说,这对我有用。

 <%= f.select :class_location_id, ClassLocation.all.map {|e| [e.place, e.id]} %> 

我遇到了同样的问题,这是我的解决方案(基于fl00r答案的改进):

  1. fl00r所说的那样

  2. 添加optional: true到类描述

class Engine belongs_to:car,optional:true end

更多信息请访问: http : //blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html

  1. 修改
 <%= f.fields_for :engine do |b| %> <%= b.collection_select :id, Engine.all, :id, :name %> ... <% end %> 

 <%= f.fields_for :engine, :include_id => false do |b| %> <%= b.collection_select :id, Engine.all, :id, :name %> ... <% end %> 

更多信息: 阻止rails为fields_for方法生成隐藏字段

  1. 修改EngineController

3.1。 修改

 def car_params params.require(:car).permit(:name) end 

 def car_params params.require(:car).permit(:name, engine_attributes: [:id, :name]) end 

更多信息在: Rails 4嵌套属性未允许的参数

3.1。 添加function(私人)

 def set_engine engine_id = car_params[:engine_attributes][:id] @engine = Engine.find(engine_id) @car.engine = @engine @car.save end 

3.2。 修改EngineController #update

  def update respond_to do |format| if @car.update(car_params) format.html { redirect_to @car, notice: 'Car was successfully updated.' } format.json { render :show, status: :ok, location: @car } else format.html { render :edit } format.json { render json: @car.errors, status: :unprocessable_entity } end end end 

  def update respond_to do |format| if set_engine && @car.update(car_params) format.html { redirect_to @car, notice: 'Car was successfully updated.' } format.json { render :show, status: :ok, location: @car } else format.html { render :edit } format.json { render json: @car.errors, status: :unprocessable_entity } end end end