我正在渲染一个模型,它是JSON中的子书籍,如下所示:
{"id":2,"complete":false,"private":false, "books" [{ "id":2,"name":"Some Book"},.....
然后我通过将相同的JSON传递回我的控制器来更新此模型,我收到以下错误:
ActiveRecord :: AssociationTypeMismatch(Book(#2245089560)预期,得到ActionController ::参数(#2153445460))
在我的控制器中,我使用以下内容进行更新:
@project.update_attributes!(project_params)
private
def project_params
params.permit(:id, { books: [:id] } )
end
无论我在permit
中将哪些属性列入白名单,我似乎无法保存子模型。
我错过了一些明显的东西吗?
更新 - 另一个例子:
控制器:
def create
@model = Model.new(model_params)
end
def model_params
params.fetch(:model, {}).permit(:child_model => [:name, :other])
end
请求:
post 'api.address/model', :model => { :child_model => { :name => "some name" } }
型号:
accepts_nested_attributes_for :child_model
错误:
期望的ChildModel,得到了ActionController :: Parameters
尝试此方法无济于事:http://www.rubyexperiments.com/using-strong-parameters-with-nested-forms/
答案 0 :(得分:12)
您是否在项目模型上使用accepts_nested_attributes_for :books
?如果是,则密钥应为"books"
而不是"books_attributes"
。
def project_params
params.permit(:id, :complete, :false, :private, books_attributes: [:id, :name])
end
答案 1 :(得分:8)
我正在使用Angular.js& Rails& Rails序列化器,这对我有用:
<强>模型强>:
ModelSerializer :
<强>控制器强>:
<强> AngularJS 强>:
答案 2 :(得分:7)
我使用ember.js解决这个问题的方法是设置books_attributes mannualy。
在控制器中:
def project_params
params[:project][:books_attributes] = params[:project][:books_or_whatever_name_relationships_have] if params[:project][:books_or_whatever_name_relationships_have]
params.require(:project).permit(:attr1, :attr2,...., books_attributes: [:book_attr1, :book_attr2, ....])
end
因此rails会按预期的方式检查和过滤嵌套属性
答案 3 :(得分:0)
这对我有用。我的父模型是Artist
,子模型是Url
。
class ArtistsController < ApplicationController
def update
artist = Artist.find(params[:id].to_i)
artist.update_attributes(artist_params)
render json: artist
end
private
def artist_params
remap_urls(params.permit(:name, :description, urls: [:id, :url, :title, :_destroy]))
end
def remap_urls(hash)
urls = hash[:urls]
return hash unless urls
hash.reject{|k,v| k == 'urls' }.merge(:urls_attributes => urls)
end
end
class Artist < ActiveRecord::Base
has_many :urls, dependent: :destroy
accepts_nested_attributes_for :urls, allow_destroy: true
end
class Url < ActiveRecord::Base
belongs_to :artist
end
...和coffeescript(处理删除):
@ArtistCtrl = ($scope, $routeParams, $location, API) ->
$scope.destroyUrls = []
$scope.update = (artist) ->
artist.urls.push({id: id, _destroy: true}) for id in $scope.destroyUrls
artist.$update(redirectToShow, artistError)
$scope.deleteURL = (artist,url) ->
artist.urls.splice(artist.urls.indexOf(url),1)
$scope.destroyUrls.push(url.id)
答案 4 :(得分:0)
所有答案中都缺少某些内容,这是undefined
形式的输入。
如果执行此操作,表单将起作用:
fields_for
但是,表单以f.fields_for @model.submodel do ..
的形式发送,但这就是导致其他人在其答案中提到的错误的原因。如果尝试执行model[submodel]
,Rails会引发错误,提示您期望使用model.update(model_params)
类型。
要解决此问题,请确保遵循Submodel
格式:
:name, value
然后在控制器中,确保将f.fields_for :submodel, @model.submodel do ...
放在参数上:
_attributes
现在,保存,更新等将正常工作。
答案 5 :(得分:-3)
浪费了几天时间试图找出如何在Angular中使用accepts_nested_attributes,问题总是一样的:Rails白名单不会允许变量进入params哈希。我尝试了每个人在SO和其他博客上说的每个不同的白名单语法,尝试使用:反向,尝试使用habtm和mas_many_through,尝试手动滚动我自己的解决方案,但如果白名单不允许参与通过,那就不会工作,尝试做什么http://guides.rubyonrails.org说“在强参数范围之外”,尝试将所有这些列入白名单,这不是一个真正的选择,但无论如何都会导致其他问题。不确定为什么rails 4强参数白名单不会允许任意数据通过,这是一个巨大的问题,特别是如果accepts_nested_attributes也不起作用....我想我们只是在一个单独的页面/表单/控制器上创建/删除所有关联并且看起来像个白痴,让我的最终用户使用多个表单/页面做一些应该可以在1页上轻松完成的表格。我知道,通常我希望Angular能够搞砸我,但是这次Angular工作得非常好,实际上Rails 4在一个问题上让我两次搞砸了,这应该是非常简单的。