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

Pla*_*Ton 4 javascript json ruby-on-rails coffeescript backbone.js

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

在2012-01-04 02:36:14 +1000开始PUT"/ posts/2"for 127.0.0.1
由PostsController处理#news更新为JSON参数:{"post"=> {"content"=>"Seconderona", "created_at"=>"2012-01-03T10:51:09Z","id"=> 2,"title"=>"第二次测试帖子","updated_at"=>"2012-01-03T10:51:09Z ","comments"=> [{}]},"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:in update'block in update'
app/controllers/posts_controller.rb:61:in

一些东西:

这是在(例如)触发的:

c = window.router.comments.models[0]
c.save({content: 'Changed content'})
Run Code Online (Sandbox Code Playgroud)

此外,是的,'accepts_nested_attributes_for'出现在模型中.

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

铁路'后'模型

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
Run Code Online (Sandbox Code Playgroud)

铁路'评论'模型

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
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

sat*_*run 26

我最近处理了同样的问题.它实际上不是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
Run Code Online (Sandbox Code Playgroud)

或者您可以在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
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助.