9

我正在使用 Rails 后端 API 编写一个练习 Backbone 应用程序,我对保存 Backbone 模型的行为感到困惑。

假设一个团队有很多玩家,我想在一个 POST 中保存一个有很多玩家的团队。

所以在 Rails 中我有:

class Team < ActiveRecord::Base
  has_many :players
  accepts_nested_attributes_for :players
end

class Player < ActiveRecod::Base
  belongs_to :team
end

对于骨干客户端,我定义了一个 Player 模型和一个 Players 集合(未显示)

然后是包含团队模型(注意:没有团队集合)

Demo.Models.Team = Backbone.Model.extend({
  urlRoot: '/teams',
  defaults: {
    'team_size': 12
  },
  initialize: function() {
    this.players = new Demo.Collections.Players());
  },
  toJSON: function() {
    var json = _.clone(this.attributes);
    json.players_attributes = this.players.map(function(player) {
      return player.toJSON();
    });
    return json;  
  }
}

当我在浏览器中检查我的字符串化 JSON 时,一切看起来都很好:

{"team_size":12, "players_attributes":[{"name":"Fred"},{"name":"Jim" },{"name":"Mark"}]}

检查服务器日志,重复唯一的顶级属性(“团队规模”),一次在顶级,然后在根键下重复。

Started POST "/teams" for 127.0.0.1 at 2012-06-07 13:39:40 -0400
Processing by TeamsController#create as JSON
  Parameters: {
    "team_size"=>12, "players_attributes":[{"name":"Fred"},{"name":"Jim" },{"name":"Mark"}]}, 
    "team"=>{"team_size"=>12}
  }

我有几个问题:

  1. 确保 player_attributes 嵌套在根键内的最佳方法是什么?我(这样我就可以在 TeamController 中以标准的 rails 方式进行嵌套保存:(即 Team.create(params[:team]))我可以使用 toJSON 中的一些 javascript 黑客来完成此操作,但我猜有一个更简单,更清洁的方式。

  2. 这是标准的、可取的行为吗?要发送这样的属性的副本?我想没有坏处,但它闻起来不对劲。

  3. 我没有正确定义 url / urlRoot 吗?

谢谢

4

3 回答 3

3

1- 您必须重写 toJSON 方法才能将模型名称作为发送到服务器的 JSON 元素的根。

 toJSON: function() {
    return { team: _.clone( this.attributes ) }
  },

由于您已经在弄乱并覆盖此方法,因此我看不出有任何理由不这样做。

2-这是您描述的一种非常奇怪的行为。尝试:

class Team < ActiveRecord::Base
  self.include_root_in_json = false
end

它可能会消除 Rails 重复参数解析。您从中获得的另一个优势是 Rails 不会将团队作为其生成的 JSON 的根元素包含在客户端中。

3-您对 urlRoot 的定义很好。

于 2012-09-22T07:00:23.480 回答
0

我在寻找同样的问题时来到这里。所以即使这是一个老问题,我认为值得给出答案。

我实际上找到了一个解释这些重复属性的 Rails 设置:wrap_parameters

http://apidock.com/rails/v3.2.13/ActionController/ParamsWrapper/ClassMethods/wrap_parameters

只需将其设置为一个空数组,rails 就不会尝试包装来自您的 JSON 请求的参数。

于 2013-09-27T22:27:09.413 回答
0

尽管您可以使用其他人提到的 toJSON hack,但这实际上并不是一个好主意。sync一方面,它会在和savewith之间产生不一致的结果{patch: true}(这种不一致是因为如果您不打补丁,同步方法会调用 toJSON,但如果您将补丁设置为 true,则不会调用 toJSON)

相反,更好的解决方案是使用补丁版本的 Backbone,它会重载同步方法本身。骨干轨 gem 会自动执行此操作,或者您可以将骨干轨_rails_sync.js 拉到您自己的应用程序中。可以在此处找到此问题的更完整答案:Backbone.js and Rails - How to handle params from Backbone models?

于 2016-05-19T16:39:12.833 回答