Backbone and Rails Associations: 避免 JSON HashWithIndifferent

Backbone and Rails associations: Avoiding JSON HashWithIndifferentAccess errors

本文关键字:避免 JSON HashWithIndifferent Associations and Rails Backbone      更新时间:2023-09-26

我正在尝试让我的主干关联在 rails 应用程序中工作,并且在尝试更新现有模型时遇到困难。具体来说,Rails 会抛出以下错误:

在 2012-01-04 02:36:14 +1000
为 127.0.0.1 启动 PUT "/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", "comments"=>[{}]}, "id"=>"2"} 后加载(0.2 毫秒( 选择"帖子"。 从"帖子"中 "帖子"。id" = ?限制 1 [["id", "2"]] 警告:无法批量分配 受保护的属性:id 在 15ms 内完成 500 个内部服务器错误

ActiveRecord::AssociationTypeMismatch (Comment(#70104367824560( 意料之中,得到了 ActiveSupport::HashWithIndifferentAccess(#70104367278120((:
app/controllers/posts_controller.rb:62: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 的"Backbone 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

骨干后控制器

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期望参数的方式有关。

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

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

您可以通过向 Post 模型添加 toJSON 函数来在主干端修复它:

# 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 为我重命名了参数,因为我提前通知了它。

希望这有帮助!