一个控制器:
class ProductsController < ApplicationController
def create
flat = Flat.find(params[:flat_id])
@flat = FlatDecorator.new(flat)
@product = flat.products.new(product_params)
if @product.save
redirect_to flat
else
render 'flats/show'
end
end
private
def product_params
params.require(:product).permit([:name, :flatmate_id, :present, :flat_id])
end
end
另一位管制员:
class FlatmatesController < ApplicationController
def create
flat = Flat.find(params[:flat_id])
@flat = FlatDecorator.new(flat)
@flatmate = flat.flatmates.new(flatmate_params)
if @flatmate.save
redirect_to flat
else
render 'flats/show'
end
end
private
def flatmate_params
params.require(:flatmate).permit(:name)
end
end
观点:
<h2>Flat <%= @flat.name%></h2>
<div>
<h3>Products</h3>
<ol>
<% @flat.products.each do |product| %>
<% if product.persisted? %>
<li><%= product.name %> <%= product.present %></li>
<% end %>
<% end %>
</ol>
</div>
<div>
<%= form_for [@flat, @product] do |form|%>
<p>
<%= form.label :name %>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :flatmate_id, "Who buys next" %>
<%= collection_select :product, :flatmate_id, @flat.flatmates, :id, :name %>
</p>
<p>
<%= form.label :present %>
<%= form.check_box :present %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
</div>
<div>
<h3>Flatmates</h3>
<ol>
<% @flat.flatmates.each do |flatmate| %>
<% if flatmate.persisted? %>
<li><%= flatmate.name %></li>
<% end %>
<% end %>
</ol>
</div>
<div>
<%= form_for [@flat, @flatmate] do |form|%>
<p>
<%= form.label :name %>
<%= form.text_field :name %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
</div>
当尝试提交第一个表单(产品)并取消选中复选框时,我会
First argument in form cannot contain nil or be empty
在第二个表单的form_for
上。在进行调试时,@flatmate
即为nil
,@flat
就可以了。
选中该复选框后,一切正常。
我做错了什么?
答案 0 :(得分:0)
当你在Rails中调用render
时,它实际上并没有调用命名方法,只是渲染它的视图。这意味着它使用的实例变量(@ flat,@ flatmate,@ product等)没有被设置在任何地方,因此被解释为nil。
当您到达渲染调用时,您需要确保正在定义视图使用的所有实例变量。
注意:看起来您正在使用“flats / show”作为更改相关对象的表单。这在rails中很不寻常,我建议使用嵌套路线并将室友,产品等放在平板下。然后将其移动到特定于平面的编辑表单以收集这些内容
resources :flats do
resources :flatmates do
collection do
get :edit
post :update
end
end
end