Backbone 和 Rails 关联:避免 JSON HashWithIndifferentAccess 错误
我正在尝试让我的骨干关联在 rails 应用程序中工作,但在尝试更新现有模型时遇到了困难.具体来说,Rails 会抛出以下错误:
I'm trying to get my backbone associations working inside a rails app , and I'm having difficulty when trying to update existing models. Specifically, Rails throws the following error:
在 2012-01-04 02:36:14 +1000 开始为 127.0.0.1 放置/posts/2"
PostsController#update 处理为 JSON 参数:{"post"=>{"content"=>"Seconderona","created_at"=>"2012-01-03T10:51:09Z", "id"=>2, "title"=>"第二次测试发布",updated_at"=>2012-01-03T10:51:09Z",评论"=>[{}]},"id"=>"2"} Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE帖子".id"=?LIMIT 1 [["id", "2"]] 警告:不能批量分配受保护的属性:id Completed 500 Internal Server Error in 15ms
Started PUT "/posts/2" for 127.0.0.1 at 2012-01-04 02:36:14 +1000
Processing by PostsController#update as JSON Parameters: {"post"=>{"content"=>"Seconderona", "created_at"=>"2012-01-03T10:51:09Z", "id"=>2, "title"=>"Second test post", "updated_at"=>"2012-01-03T10:51:09Z", "comments"=>[{}]}, "id"=>"2"} Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", "2"]] WARNING: Can't mass-assign protected attributes: id Completed 500 Internal Server Error in 15ms
ActiveRecord::AssociationTypeMismatch (评论(#70104367824560)预期,得到ActiveSupport::HashWithIndifferentAccess(#70104367278120)):
app/controllers/posts_controller.rb:62:in block in update'
update'
app/controllers/posts_controller.rb:61:in
ActiveRecord::AssociationTypeMismatch (Comment(#70104367824560)
expected, got
ActiveSupport::HashWithIndifferentAccess(#70104367278120)):
app/controllers/posts_controller.rb:62:in block in update'
update'
app/controllers/posts_controller.rb:61:in
一些事情:
这是触发的(例如):
c = window.router.comments.models[0]
c.save({content: 'Changed content'})
另外,是的,模型中存在accepts_nested_attributes_for".
Also, yes, 'accepts_nested_attributes_for' is present in the model.
下面的(有问题的)代码几乎一字不差地取自 thougtbot 的backbone on rails"电子书,我还尝试遵循骨干关系 gem 的文档.两者都会引发此错误.任何想法表示赞赏,下面的代码
The (offending) code below is taken pretty much verbatim from thougtbot's "backbone on rails" ebook, and I've also tried following the documentation for the backbone-relational gem. Both raise this error. Any ideas appreciated, code below
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
骨干后控制器
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'
主干评论控制器
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
期望参数的方式有关.
I dealt with the same issue recently. It's actually not a HashWithIndifferentAccess error: it has to do with how accepts_nested_attributes_for
expects params.
当您声明 accepts_nested_attributes_for :comments
时,Rails 会在传入参数上查找参数调用 comments_attributes
.
When you declare accepts_nested_attributes_for :comments
, Rails looks for a parameter call comments_attributes
on the incoming params.
问题是来自 Backbone 的 JSON 表示具有 "comments"
属性而不是 "comments_attributes"
属性.
The problem is that your JSON representation coming from Backbone has a "comments"
property instead of a "comments_attributes"
property.
您可以通过向 Post 模型添加 toJSON 函数来在 Backbone 端修复它:
You could fix it on the Backbone side by adding a toJSON function to your Post model:
# in your Post model
toJSON: ->
attrs = _.clone(@attributes)
attrs.comments_attributes = _.clone(@attributes.comments)
delete attrs.comments
attrs
或者您可以在 Rails 控制器中处理它:
Or you could handle it in your Rails controller:
# 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
希望这会有所帮助.
相关文章