data-modeling - ExtJS 4:Modelos con asociaciones y tiendas




store model-associations (5)

Konrad. Recientemente tuve que lidiar con Models+Associations+Stores . Esta no fue una experiencia muy agradable. Esto es lo que he aprendido:

Digamos que tenemos Store1, Store2, Model1, Model2, Grid1, Grid2. Grid1 usa Store1, Store1 usa Model1 y de manera similar Grid2 usa Store2, Store2 usa Model2.

Hasta ahora todo está funcionando, los datos se están cargando, etc.

Pero ahora queremos agregar hasMany asociación a Model1. Ok, estamos agregando a la configuración de Model1:

hasMany: {model: 'Model2', name: 'model2'}

Después de esto, piensas que puedes poblar Store2 con datos en el ítem clique de itemclick haciendo algo como lo siguiente:

Grid1.on('itemclick', function(view, item_which_uses_model1){
  //item_which_uses_model1.model2() supposed to return Model2's store
  item_which_uses_model1.model2().load();
}

Está esperando que Grid2 esté lleno de datos en el elemento de itemclick . Pero nada pasa. Actualmente se están publicando solicitudes, se obtienen respuestas. Pero Grid2 no está lleno de datos.
Y después de un tiempo te das cuenta de que item_which_uses_model1.model2() NO ES Store2 .

cuando Model2 "ve" que tiene asociación con Model1, crea la propia tienda de Model1 que no es Store2.

No es genial, porque Grid2 está usando Store2.

De hecho, puedes hackearlo, por ejemplo, agregando a la configuración de Grid2:

store: new Model1().model2(),

pero qué pasa si estás usando el patrón ExtJS mvc. Grid2 no tiene que saber nada sobre Model1.

No recomiendo usar associations en proyectos del mundo real. Al menos ahora. En su lugar, use el enfoque que se muestra en su ejemplo: Modelo + Tienda + Filtrado.

Introducción

Estoy frente a un problema de diseño de la aplicación con la clase Ext.data.Model en ExtJS. Trataré de desarrollar mis ideas en un escenario de tienda en línea muy común aquí, para que pueda seguirme. ¡Realmente agradecería cualquier comentario sobre mis pensamientos y conclusiones!

Modelos

Supongamos que desea asignar el hecho de que " Todos los clientes pueden solicitar varios productos " a ExtJS. A partir de las simples palabras, uno puede identificar estos tres modelos involucrados: Customer , Order y Product . El Order en este caso es lo que conecta los productos del Customer y del Product .

Asociaciones

Descubrí que ExtJS le permite especificar esta relación (Customer)1-n(Order)1-n(Product) usando las clases Ext.data.HasManyAssociation y Ext.data.BelongsToAssociation . Pero, ¿es esto lo que uno quiere? ¿Le gustaría que un Product siempre pertenezca a un Order ? ¿Qué sucede si desea tener una lista de Product sin ninguna conexión con Order s en absoluto?

Víveres

Aquí es donde obtiene más ExtJS específico. En ExtJS tiene Ext.data.Store para almacenar todos sus datos. Para mí, una forma natural de organizar mis datos es tener una Ext.data.Store para cada uno de mis modelos:

  1. CustomerStore
  2. OrderStore
  3. ProductStore

Considere tener tres Ext.grid.Panel s lado a lado; uno para cada tienda Al seleccionar un cliente en la cuadrícula, sus pedidos aparecen automáticamente en la segunda cuadrícula. Al seleccionar una orden en la segunda grilla, los productos asociados aparecen en la tercera grilla.

¿Esto te suena natural? Si no, ¡por favor comenta!

Juntando todo

Entonces ahora tenemos tres cosas que debemos unir:

  1. Modelos y sus
  2. Asociaciones ( hasMany , belongsTo ) y el
  3. Datos ( Store s)

¿Es posible definir una asociación solo desde un lado de una relación Modelo-Modelo? Por ejemplo, ¿puedo especificar que una Order hasMany Product pero excluye que un Product belongsTo una Order ? Porque un Product puede pertenecer a más de un Order . Por lo tanto, especifico que el modelo de Product hasMany Order a continuación.

Estos son los modelos en ExtJS:

Cliente

Ext.define('Customer', {
    extend   : 'Ext.data.Model',
    requires : [
        'Order',
    ],
    fields   : [
           {name : 'id',          type : 'int'},
           {name : 'lastname',    type : 'string'}
           {name : 'firstname',   type : 'string'}
    ],
    hasMany: 'Order' /* Generates a orders() method on every Customer instance */
});

Orden

Ext.define('Order', {
    extend   : 'Ext.data.Model',
    fields   : [
            {name : 'id',          type : 'int'},
            {name : 'customer_id', type : 'int'}, /* refers to the customer that this order belongs to*/
            {name : 'date',        type : 'date'}
    ],
    belongsTo: 'Customer', /* Generates a getCustomer method on every Order instance */
    hasMany: 'Product' /* Generates a products() method on every Order instance */
});

Producto

Ext.define('Product', {
    extend   : 'Ext.data.Model',
    fields   : [
            {name : 'id',          type : 'int'},
            {name : 'name',        type : 'string'},
            {name : 'description', type : 'string'},
            {name : 'price',       type : 'float'}
    ],
    /*
        I don't specify the relation to the "Order" model here
        because it simply doesn't belong here.

        Will it still work?
    */
    hasMany: 'Order'
});

Y aquí están las tiendas:

CustomerStore

Ext.define('CustomerStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'CustomerStore',
    model       : 'Customer',
    proxy   : {
        type   : 'ajax',
        url    : 'data/customers.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

OrderStore

Ext.define('OrderStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'OrderStore',
    model       : 'Order',
    proxy   : {
        type   : 'ajax',
        url    : 'data/orders.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

ProductStore

Ext.define('ProductStore', {
    extend      : 'Ext.data.Store',
    storeId     : 'ProductStore',
    model       : 'Product',
    proxy   : {
        type   : 'ajax',
        url    : 'data/products.json',
        reader : {
            type           : 'json',
            root           : 'items',
            totalProperty  : 'total'
        }
    }
});

Aquí hay un ejemplo (no yo) con las empresas y sus productos http://superdit.com/2011/05/23/extjs-load-grid-from-another-grid/ . Utiliza dos modelos y dos tiendas, pero no hay asociaciones definidas.

Gracias de antemano

-Konrad


Tenga en cuenta que su suposición:

(Cliente) 1-n (Pedido) 1-n (Producto)

Está Mal. Su modelo real debería ser:

(Cliente) 1-n (Pedido) n -n (Producto)

Es por eso que también encontró dificultades al modelarlo con hasMany-belongsTo


estoy totalmente de acuerdo con Molecular Man. Al leer la documentación de ExtJS apareció más como evidencia de que esta es una buena ruta cuando se utiliza una estructura de conjunto de árbol distribuida en diferentes tiendas. Francamente, todo esto podría ser cierto solo si dicha asociación tuviera de alguna manera una referencia de tiendas para realizar llamadas. Ese no es el caso de lo que he probado. Las asociaciones de modelos no tienen tal relación. Filtrar es la mejor manera de mantenerse al día con la actualización secuencial de otras grillas cuyos modelos dependen de otros.


Todo funciona bien en ExtJS 4, es difícil hacerlo bien la primera vez. Bueno, las primeras veces.

Sí, puede evitar especificar la asociación belongsTo del hijo y aún así utilizarla en una relación Has Many.

En mi proyecto, tenemos docenas de modelos, muchos con relaciones profundas, y funciona muy bien.

En cuanto a las relaciones Many-Many, deberías tener

Cliente - <CustomerOrder> - Pedido

Que es tres modelos,

O puede "falsificarlo" haciendo un montón de trabajo en el servidor para pretender que un cliente tiene muchas órdenes. Jenson anidado puede ayudar aquí.


Personalmente, en este caso, utilizaría la estructura que describió y usaría la base de datos como un mecanismo de almacenamiento tonto. Soy partidario de poner estas restricciones complejas y dependientes en la capa de aplicación.

Creo que la única forma de hacer cumplir estas restricciones sin crear nuevas tablas para cada pregunta con claves externas para otros, es usar el material de T-SQL u otros mecanismos específicos del vendedor para generar activadores de base de datos para hacer cumplir estas restricciones.

A nivel de aplicación, tienes muchas más posibilidades y es más fácil de portar, por lo que preferiría esa opción.

Espero que esto te ayude a encontrar una estrategia para tu aplicación.