Backbone 和 Rails 关联:避免 JSON HashWithIndifferentAccess 错误
Posted
技术标签:
【中文标题】Backbone 和 Rails 关联:避免 JSON HashWithIndifferentAccess 错误【英文标题】:Backbone and Rails associations: Avoiding JSON HashWithIndifferentAccess errors 【发布时间】:2012-02-01 16:39:46 【问题描述】:我正在尝试让我的骨干关联在 rails 应用程序中工作,但在尝试更新现有模型时遇到了困难。具体来说,Rails 会抛出以下错误:
在 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"=>"第二次测试 post", "updated_at"=>"2012-01-03T10:51:09Z", "cmets"=>[], "id"=>"2" Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE “帖子”。“id”=? LIMIT 1 [["id", "2"]] 警告:不能批量分配 受保护的属性:id Completed 500 Internal Server Error in 15ms
ActiveRecord::AssociationTypeMismatch (评论(#70104367824560) 预期,得到 ActiveSupport::HashWithIndifferentAccess(#70104367278120)): app/controllers/posts_controller.rb:62:in
block in update' app/controllers/posts_controller.rb:61:in
update'
一些事情:
这是触发的(例如):
c = window.router.comments.models[0]
c.save(content: 'Changed content')
另外,是的,模型中存在“accepts_nested_attributes_for”。
下面的(有问题的)代码几乎一字不差地取自 thougtbot 的“backbone on rails”电子书,我还尝试遵循骨干关系 gem 的文档。两者都会引发此错误。任何想法表示赞赏,下面的代码
RAILS 'POST' 模型
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'
【问题讨论】:
【参考方案1】:我最近处理了同样的问题。这实际上不是 HashWithIndifferentAccess 错误:它与 accepts_nested_attributes_for
期望参数的方式有关。
当您声明 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
希望这会有所帮助。
【讨论】:
【参考方案2】:对于那些正在谷歌搜索的人......
虽然当前接受的答案确实有效,但以下是我解决问题的方法(非常相似,但略有不同):
我使用的是nested form,模型嵌套了 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 为我重命名了参数,因为我提前通知了它。
希望这会有所帮助!
【讨论】:
以上是关于Backbone 和 Rails 关联:避免 JSON HashWithIndifferentAccess 错误的主要内容,如果未能解决你的问题,请参考以下文章
Backbone.js 前端和 RESTful Rails 后端?
Rails、Backbone、PhoneGap、CORS(Access-Control-Allow-Origin 错误不允许)