Backbone和Rails关联:避免JSON HashWithIndifferentAccess错误

我正试图让我的骨干协会在rails应用程序中工作,而我在尝试更新现有模型时遇到了困难。 特别是,Rails抛出以下错误:

在2012-01-04 02:36:14 +1000开始PUT“/ posts / 2”为127.0.0.1
由PostsController处理#update更新为JSON参数:{“post”=> {“content”=>“Seconderona”,“created_at”=>“2012-01-03T10:51:09Z”,“id”=> 2,“ title“=>”第二个测试post“,”updated_at“=>”2012-01-03T10:51:09Z“,”评论“=> [{}]},”id“=>”2“}后期加载( 0.2ms)SELECT“posts”。* FROM“posts”WHERE“posts”。“id”=? LIMIT 1 [[“id”,“2”]]警告:无法批量分配受保护的属性:id已完成500内部服务器错误15ms

ActiveRecord :: AssociationTypeMismatch(评论(#70104367824560)预期,获得ActiveSupport :: HashWithIndifferentAccess(#70104367278120)):
app / controllers / posts_controller.rb:62: block in update'
app/controllers/posts_controller.rb:61:in
中的block in update'
app/controllers/posts_controller.rb:61:in
block in update'
app/controllers/posts_controller.rb:61:in
block in update'
app/controllers/posts_controller.rb:61:in
更新中’

一些东西:

这是在(例如)触发的:

 c = window.router.comments.models[0] c.save({content: 'Changed content'}) 

此外,是的,’accepts_nested_attributes_for’出现在模型中。

下面的(违规)代码几乎是从thougtbot的“rails on rails”电子书中逐字记录的,我也尝试过关注骨干关系gem的文档。 都引发了这个错误。 任何想法赞赏,代码如下

铁路’后’模型

 class Post < ActiveRecord::Base has_many :comments accepts_nested_attributes_for :comments def as_json(options = nil) super((options || {}).merge(include: { comments: { only: [content] } } )) end end 

铁路’评论’模型

 class Comment < ActiveRecord::Base belongs_to :post accepts_nested_attributes_for :post def as_json(options = nil) super((options || {}).merge(include: { post: { only: [:title, :content]}})) end end 

BACKBONE POST控制器

 class Backbonerelationaldemo.Models.Post extends Backbone.Model paramRoot: 'post' initialize: () -> comments = new Backbonerelationaldemo.Collections.CommentsCollection comments.reset(@get('comments')) @setComments(comments) setComments: (comments) -> @comments = comments class Backbonerelationaldemo.Collections.PostsCollection extends Backbone.Collection model: Backbonerelationaldemo.Models.Post url: '/posts' 

BACKBONE评论控制器

 class Backbonerelationaldemo.Models.Comment extends Backbone.Model paramRoot: 'comment' initialize: () -> if (@has('post')) @setPost(new Backbonerelationaldemo.Models.Post(@get('post'))) setPost: (post) -> @post = post class Backbonerelationaldemo.Collections.CommentsCollection extends Backbone.Collection model: Backbonerelationaldemo.Models.Comment url: '/comments' 

我最近处理了同样的问题。 它实际上不是HashWithIndifferentAccess错误:它与accepts_nested_attributes_for如何期望params有关。

当您声明accepts_nested_attributes_for :comments ,Rails会在传入的参数上查找参数调用comments_attributes

问题是来自Backbone的JSON表示具有"comments"属性而不是"comments_attributes"属性。

您可以通过向Post模型添加toJSON函数来修复Backbone端:

 # in your Post model toJSON: -> attrs = _.clone(@attributes) attrs.comments_attributes = _.clone(@attributes.comments) delete attrs.comments attrs 

或者您可以在Rails控制器中处理它:

 # in your Posts controller def update params[:comments_attributes] = params.delete(:comments) if params.has_key? :comments # call to update_attributes and whatever else you need to do end 

希望这会有所帮助。

对于那些谷歌搜索…

虽然目前接受的答案肯定有效,但以下是我如何解决我的问题(非常相似,但略有不同):

我使用的是嵌套表单 ,模型嵌套了4层深。 在我的渲染表单的控制器中,我需要构建表单。

 def new @survey = Survey.new 3.times do question = @survey.questions.build 4.times { question.answers.build } end end 

这允许参数包括params[:survey][:questions_attributes] 。 Rails为我重命名了参数,因为我提前告知了它。

希望这可以帮助!