所以,想象一下我有这个模型:
class Car
has_one :engine
end
和引擎型号:
class Engine
belongs_to :car
end
当我为用户呈现表单时,他可以创建一辆新车,我只想让他从一个可用的引擎中选择(可用的引擎将在select
中,填充由collection_select
)。问题是,如果我像这样构建字段:
<%= f.collection_select :engine,Engine.all,:id,:name %>
当我尝试保存它时,我会得到一个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_one
和belongs_to
关联是实现此目的的唯一方法吗?
我迷失了,我觉得我在这里缺少一些非常基本的东西。
答案 0 :(得分:8)
您应该使用engine_id
<%= f.collection_select :engine_id, Engine.all, :id, :name %>
<强> UPD 强>
至于Engine
不是belongs_to Car
所以你应该在这里使用嵌套属性。这个截屏视频对您非常有用:
Checkout api:http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for
简介:
class Car
has_one :engine
accepts_nested_attributes_for :engine
end
并以您的形式:
<%= form_for @car ... do |f| %>
...
<%= f.fields_for :engine do |b| %>
<%= b.collection_select :id, Engine.all, :id, :name %>
...
<% end %>
...
<% end %>
答案 1 :(得分:0)
回应Kyle之前的回答 - 我喜欢这种简单的方法,但是我必须按照以下方式更改它以适用于我的应用程序(我在Rails 3.2.13中)。主要的一点是地图需要返回一个数组 - 所以我认为这可能是一个拼写错误,将两个数组用逗号分隔。我还将id属性的字符串引用更改为符号,但我不确定这是否必不可少或只是另一种选择。从某种程度上说,这对我有用。
<%= f.select :class_location_id, ClassLocation.all.map {|e| [e.place, e.id]} %>
答案 2 :(得分:0)
我遇到了同样的问题,这是我的解决方案(基于 fl00r 答案的改进):
按 fl00r 说的那样做。
将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
<%= 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 %>
更多信息:Stop rails from generating hidden field for fields_for method
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 Nested Attributes Unpermitted Parameters
3.1。添加功能(私人)
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