Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Backbone model sending duplicate attributes to server on save?

I'm writing a practice Backbone app, with Rails backend API, and I'm confused about the behavior of save on Backbone models.

Let's say a Team has many Players, and I want to save a team with numerous players in a single POST.

So in Rails I have:

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

class Player < ActiveRecod::Base
  belongs_to :team
end

and for backbone client, I have a Player model and a Players collection defined (not shown)

and then the containing Team model (NOTE: no Teams collection)

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;  
  }
}

When I examine my stringified JSON in the browser, everything looks good:

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

Checking the server logs, the lone top level attribute ('team size') is repeated, once at the top level, and then repeated under a root key.

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}
  }

I have a few questions:

  1. What's the best way to ensure the player_attributes are nested inside the root key? I (So that I can do a nested save inside TeamController, in the standard rails manner: (i.e. Team.create(params[:team]) ) I can accomplish this with some javascript hackery inside toJSON, but I'm guessing there's an easier, cleaner way.

  2. Is this standard, desirable behaviour? To send duplicates of attributes like this? I guess there's no harm, but it doesn't smell right.

  3. Am I not defining the url / urlRoot correctly or some such?

thanks

like image 880
doublea Avatar asked Jun 07 '12 17:06

doublea


People also ask

How do you save in backbone?

Backbone is wonderful because it does a lot of work for you. To save our donut and secondHelping, we simply do this: myDonut. save(); mySecondHelping.

What is Backbone used for?

It is designed for developing single-page web applications, and for keeping various parts of web applications (e.g. multiple clients and the server) synchronized. Backbone was created by Jeremy Ashkenas, who is also known for CoffeeScript and Underscore. js.

What is Backbone framework?

Backbone. js is a model view controller (MVC) Web application framework that provides structure to JavaScript-heavy applications. This is done by supplying models with custom events and key-value binding, views using declarative event handling and collections with a rich application programming interface (API).


1 Answers

1- You have to override the toJSON method in order to include the model name as the root of the JSON element sent to the server.

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

Since you are already messing and overriding this method I don't see any reasons not to go this way.

2- This is a very strange behavior you're describing. Try:

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

It will probably eliminate Rails duplicate params parsing. Another advantage you get from this is that Rails won't include the team as a root element of its generated JSON to the client.

3- Your definition of urlRoot is just fine.

like image 96
Erez Rabih Avatar answered Sep 18 '22 14:09

Erez Rabih