9

Estoy escribiendo una práctica de la aplicación Backbone, con la API de back-end de Rails, y estoy confundido acerca del comportamiento de guardar en modelos Backbone.¿Por qué el modelo Backbone está enviando atributos duplicados al servidor al guardar?

Digamos que un equipo tiene muchos jugadores, y quiero guardar un equipo con numerosos jugadores en un solo POST.

Así que en los carriles tengo:

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

class Player < ActiveRecod::Base 
    belongs_to :team 
end 

y para el cliente de la columna vertebral, tengo un modelo de jugador y una colección de jugadores definido (no se muestra)

y luego el modelo de equipo que contiene (NOTA: no colección de equipos)

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

Cuando examino mi stringified JSON en el navegador, todo se ve bien:

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

Al verificar los registros del servidor, se repite el atributo de nivel superior solitario ('tamaño del equipo'), una vez en el nivel superior y luego se repite bajo una clave raíz.

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

Tengo algunas preguntas:

  1. ¿Cuál es la mejor manera de asegurar los player_attributes están anidadas dentro de la clave raíz? I (Para que pueda hacer un guardado anidado dentro de TeamController, en la forma estándar de rieles: (es decir Team.create (params [: team])) Puedo lograr esto con algunos hackes de javascript dentro de JSON, pero supongo que hay una . manera más fácil, más limpio

  2. ¿es esta norma, el comportamiento deseable? Para enviar los duplicados de los atributos de este tipo? Creo que no hay ningún daño, pero no huele bien.

  3. no soy yo definición de la URL/UrlRoot correctamente o algunas de estas?

gracias

+2

Backbone envía exactamente el resultado de toJSON(): 'params.data = JSON.stringify (model.toJSON());', por lo que su modelo contiene tales atributos o algo extraño en el servidor (hay un parche de cierre de desperdicios en el registro). Verifique el contenido de la solicitud http en firebug para averiguar a quién culpar. – Yaroslav

+0

He tenido este mismo problema con Backbone and Rails por un tiempo ... ahora necesito optimizar y esto se está volviendo desagradable ... ¿Alguna idea de dónde viene? – wulftone

+0

Creo que vale la pena señalar que en mi caso (y probablemente también en el suyo), la red troncal parece estar enviando información no duplicada. Firebug me dice que la solicitud POST enviada a mi servidor contenía la información correcta y no duplicada. Sin embargo, en algún lugar antes de que se convierta en el rubí "params", se duplican algunas cosas ... ¿por qué? – wulftone

Respuesta

3

1- Debe sobrescribir el método toJSON para incluir el nombre del modelo como la raíz del elemento JSON enviado al servidor.

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

Dado que ya está jugando y anulando este método, no veo ninguna razón para no seguir por este camino.

2- Este es un comportamiento muy extraño que estás describiendo. Pruebe:

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

Probablemente elimine el análisis de parámetros duplicados de Rails. Otra ventaja que obtienes de esto es que Rails no incluirá al equipo como un elemento raíz de su JSON generado para el cliente.

3- Tu definición de urlRoot está bien.

+0

Esto parece funcionar siempre que no aplique parches. Si está utilizando '' 'save''' con' '' {patch: true} '' ', entonces el método de sincronización Backbone prefiere los attrs que se cambiaron en lugar de llamar al método toJSON. –

0

Llegué aquí mientras buscaba el mismo problema. Así que incluso es una vieja pregunta, creo que vale la pena dar la respuesta.

realidad me encontré con un ajuste de rieles que explican estos atributos duplicados: wrap_parameters

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

sólo puede configurarse como un conjunto vacío, y los carriles no tratará de envolver parámetros procedentes de sus peticiones JSON.

0

Aunque puede utilizar el hack toJSON mencionado por otros, esta no es una buena idea. Por un lado, se produce un resultado incoherente entre sync y save con {patch: true} (esta inconsistencia se debe a que el método de sincronización llama toJSON si no parche, pero no llamar toJSON si tiene cierto conjunto de parches a)

lugar , una mejor solución es usar una versión parcheada de Backbone que sobrecargue el método de sincronización. La gema backbone-rails lo hace automáticamente, o puedes llevar a backbone_rails_sync.js a tu propia aplicación. Puede encontrar una respuesta más completa a esta pregunta aquí: Backbone.js and Rails - How to handle params from Backbone models?

Cuestiones relacionadas