我正在尝试创建一个可以编辑然后保存的嵌套表单。每当我去保存表单时,我都会收到错误:
对于ID =
的Collection,找不到ID为11的ClassInstance
11是表单中第一个ClassInstance的ClassInstance id,看起来Collection ID被设置为NULL。
我尝试在控制器form_for
中手动设置隐藏ID,并在_class_instance_fields.html.erb中为:collection_id设置隐藏字段。
ActiveRecord尝试做什么,为什么会混淆?我是否会使用嵌套表格做一些你不应该做的事情?
我已经将我的一些代码包含在去除绒毛中,因此无需查看。
collections_controller.rb
def update
@collection = Collection.new(params[:collection])
if @collection.save
flash[:notice] = "IT WORKED"
else
flash[:notice] = "No Cigar...."
end
redirect_to collection_path
end
def read
@collection = Collection.find_by_user_id(current_user.id)
@classes = Classification.all
end
read.html.erb
<%= form_for @collection, url: {:action => "update", collection_id: @collection.id} do |f| %>
<%= f.hidden_field :id #I had hoped this would fix it%>
<table class="instance_table">
<%= f.fields_for :class_instances do |builder| %>
<%= render 'shared/class_instance_fields', :f => builder, :status => '0' %>
<% end %>
<tr><td>
<%= link_to_add_fields "Add an Instance", f, :class_instances %>
</td></tr>
</table>
<%= f.submit "Save"%>
<% end %>
_class_instance_fields.html.erb
<tr class="record_row">
<td>
<%= f.label( :name) %></p>
</td>
<%= f.hidden_field :status, :value => status %>
<%= f.hidden_field :collection_id %>
<td>
<% if status == '1' %>
<%= f.text_field :name %>
<% else %>
<%= link_to f.object.name, instance_edit_path(f.object.id) %>
<% end %>
</td>
<td>
<% if status == '1' %>
<%= f.select :classification, options_for_select(@classes.collect{|c| [c.name, c.id]},selected: f.object.class_id)%>
<% else %>
<%= f.label :classification, displayClassInstanceName(@classes.select{|a| a[:id] == f.object.class_id }[0]) %>
<% end %>
</td>
<td>
<% user = nil%>
<% id = nil %>
<% if status == '1' %>
<%collection = current_user.id %>
<% else %>
<%collection = f.object.collection_id %>
<% end %>
<%= f.label :username, displayUserName( user ) %>
</td>
<td>
<%= removeRecordLink(f) %>
</td>
</tr>
在保存之前,我一直在使用Rails.logger.debug
检查参数。使用`update
Rails.logger.debug "TG: " << params.to_yaml
我得到以下输出
TG: --- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
utf8: ✓
_method: put
authenticity_token: efvqGsLKJfdCsadfjsad9fsD97dfgYaOUjsg+uvAQi2+k4=
collection: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
name: mikee's Collection
class_instances_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
'0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
status: '0'
collection_id: '8'
_destroy: '0'
instance_attributes_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
'0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
id: '1'
_destroy: '0'
id: '11'
commit: Save
controller: collections
action: update
id: '8'
也许这可以帮助理解事物,因为我对params不太熟悉,而且我不确定我应该在那里看到嵌套表格。
答案 0 :(得分:1)
我想对您的帖子发表评论但尚未获得50个声望......所以我只想发布此处。希望你会发现它有用。
您是否在表单前尝试<%= @collection.inspect %>
以查看Rails正在将哪些数据放入表单中?您不必在任何地方指定id
或collection_id
,因为form_for
会照顾您。
我会在表单中注释掉其余字段,然后在render text: params.inspect and return
操作中执行update
,以确切了解通过PATCH向其发送的数据(假设您正在运行) Rails 4)。
如果id
(或collection_id
取决于您的路线)显示正确,那么您可以开始取消注释表单的某些部分...冲洗并重复,直到找到有问题的代码。
编辑:我同意Philip7899。这似乎是一个很强的参数问题。
答案 1 :(得分:1)
与其他人相反,我不相信这是一个强大的参数问题。当您说params.require(:collection)
之类的内容时,强参数才会启动。
我很难理解你在这里要做什么。您的方法称为更新,它表示它更新现有记录,而是创建一个新记录(Collection.new
)。我假设您正在尝试更新现有记录。
这里有一些问题。首先是控制器。替换这个:
@collection = Collection.new(params[:collection])
用这个:
@collection = Collection.find(params[:id])
@collection.assign_attributes(params[:collection])
然后是视图......
当表单更新Rails中的资源时,标准过程是在表单操作URL中包含对象ID。当您使用form_for @collection
时会自动发生这种情况。由于您使用url: {:action => "update", collection_id: @collection.id}
覆盖了表单的URL,因此它无法正确生成路径。将您的form_for
行更改为:
<%= form_for @collection do |f| %>
并删除f.hidden_field :id
要使其正常工作,您必须在routes.rb
中设置相应的路线。我假设你在那里有一行,如resources :collections
。
我无法告诉您要对class_instances做什么,但是如果您希望在保存集合时创建其他对象,则可能需要在Collection模型上设置accepts_nested_attributes_for
。在这里阅读:
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
一旦这样做,您可能希望将params[:collection]
替换为collection_params
,然后您应该向控制器添加方法
protected
def collection_params
params.require(:collection).permit(:param_1, :param_2, :param_3)
end
其中:param_1,:param_2,:param_3是您希望允许用户更新的参数。
请参阅https://github.com/rails/strong_parameters和Rails 4 - Strong Parameters - Nested Objects
答案 2 :(得分:0)
如果您使用的是rails 4,请将class:id添加到class_instances的强参数中。如果您使用的是rails 3,请对模型进行更改,以便用户可以对其进行设置。