Saving nested objects with Rails, backbone.js, and

2019-01-16 12:45发布

I'm using Rails, backbone.js (learning this now). Let's say you have two models, Car and Engine.

var Car = Backbone.Model.extend({
  initialize: function() {
    if(this.get('engine') != undefined) this.engine = new Engine(this.get('engine'));
  }
}

var redCar = new Car({
      'color': 'red',
      // The controller nests the model
      'engine': {
         'horsepower': '350'
       }
    });


redCar.save()

What is the right way to send engine_attributes to the controller? (Car accepts_nested_attributes_for :engine, so it expects engine_attributes.) Do I override the Backbone sync()? Is there a better convention to follow for nested models?

Maybe I should not be returning nested models from the controller, or returning engine_attributes instead of engine?

On a side note, I am using the Rails respond_with(@car, :include => :engine) (same as @car.to_json(:include => :engine). The fact that this api nests the engine attributes under engine but the model expects engine_attributes seems contradictory - I've never been sure how to reconcile this.

4条回答
冷血范
3楼-- · 2019-01-16 13:29

Very helpful. I was working with a similar situation, and this example did not work for me at first. In my example I have a has_many / belongs_to relation. For example a car has_many :tires.

The problem I encountered was that the tires_attributes needed to be nested INSIDE of the car json, not adjacent to it. I ended up with something like this:

toJSON: function(){

  json = {car : this.attributes};
  json.car.tires_attributes = this.get('tires').toJSON();
  return json;

}

Hope this helps.

查看更多
ら.Afraid
4楼-- · 2019-01-16 13:44

I believe we've to do something with (or around) Backbone sync or with rails backend, because the problem in communication between two. Overriding toJSON() method might lead to unexpected results, because this is general purpose method and others parts of application might rely on, for example views.

Possibly quick solution:

redCar.save({}, {
    contentType: 'application/json',
    data: JSON.stringify({car: redCar.toJSON(), engines_attributes: redCar.get('engines').toJSON()})
});
查看更多
太酷不给撩
5楼-- · 2019-01-16 13:46

I would suggest to override toJSON on the backbone model.

toJSON: function(){

  json = {car : this.attributes};
  return _.extend(json, {engine_attributes: this.get("engine").toJSON());

}

toJSON is called within the sync method just before sending data to the backend.

查看更多
登录 后发表回答