1. #1
    Sencha User
    Join Date
    Jul 2008
    Posts
    53
    Vote Rating
    0
    jash is on a distinguished road

      0  

    Default Polymorphic model inheritance in 4.1?

    Polymorphic model inheritance in 4.1?


    Hi!

    When digging into ExtJS 4.1 B2 sources to see how I should get some stuff working I discovered a reference to polymorphic model inheritance. in some developer comments.

    Within my project I use PI a lot and It has been a lot of work to get this working in the front-end.

    I'm really curious about the functionality and if it will make it into 4.1F...

    The trouble I'm having should be fixed by something supporting data loaded from the server in the form:

    (take An Adresses table where in fact there are Address,PostalAddress an telephone number. tables)

    id, discriminator, fields....

    if Discriminator == 'PostalAddress' - //This record returned From an Addresses query will be loaded into a PostalAddress Model, with fields like street, zip, city

    if Discriminator == 'TelephoneNumber' //This record will be loaded into a a TelephoneNumber Model, with fields, country code, area and subscriber.

    Will this be what Polymorphic will do? I am not really sure where I found it, I think It was somewhere in validations but I'm not sure.

    At the moment to get this working I have a relatively complex way of loading data which is not in the ExtJs core and although I have been tried optimizing, it is relatively slow in the Address "Onload" where I fill several stores with the raw record data. It works somehow (after a lot of fiddling I got it working but I'm just not sure how it will hold up in the future with Ext updates).


    Any comments on the Polymorphic implementation, thoughts etc. would be very helpful.
    Another thing, how would Touch get around with this and how compatible will touch and Extjs be on the Data Package..... with a multi platform project we have been struggling on this since touch came out (Ext.Direct is our way of backend- communications, luckily Touch has Direct support now).

    Jash

  2. #2
    Ext JS Premium Member
    Join Date
    Feb 2012
    Location
    Oslo, Norway
    Posts
    5
    Vote Rating
    0
    einartg is on a distinguished road

      0  

    Default


    Very interesting, Jash. We've also been looking for this feature as we feel this is the missing part of the model relationship package that already comes with ExtJS 4.

    The kind of use cases that we are looking at are items in a tress structure and grids, where our nodes are of different types, and should display among other things different icons, as well as behave differently when moved (drag and drop), or other commands are applied to them.

    If you care to share your approach to achieve it would be much appreciated.

  3. #3
    Sencha User
    Join Date
    Jul 2008
    Posts
    53
    Vote Rating
    0
    jash is on a distinguished road

      0  

    Default


    I posted this in the hope that I would get some sort of response from Sencha.
    Looking at the fact that this post is viewed a lot of times and that polymorphic table inheritance is a solution for many modern day problems. I do expect Sencha to include this in 4.1 Final. I say 'Expect' for a reason and not to push it for my use only. It is just so essential in modern day database design and ORM that I just do not understand why this is 'overlooked' in the data package design since ExtJs is not really just for adding menu's to webpages it is to make applications to run in browsers for the most of it.

    I see one perfect example to make my point:
    Take 'Product' as an object for just what it is and think about a physical table 'Product' in the database. Product has properties which are reflected in the database (description, price, whatever).
    I would develop an application to work with 'Product' it would be static as hell. If the user of that application needs support for another type of Product which is just not compatible with the original product, either in needed functionality or storage of properties, then what? With Polymorphic Table Inheritance I would her set up Product in such a way that it supports PTI, without using it.
    Now with the new type of product say, we want to add a serial number. I would extend the original product with a property 'serialNumber' and none of my code needs to be rewritten, there where I create an other product type, my backend, will add a table but will include ALL records from both types if I query 'Products'. all fine UNTIL you use Extjs for displaying or editing data.

    I have posted enough about the lack of documentation on how the different components of extjs work together technically, makes it really difficult to make stuff work. the API docs are OK but Sencha does not seem to understand that examples do not cover the developers intended use of many of us and days are lost looking at cryptic error messages in ext-all-debug.... (I will talk about a self made solution later, this is the reason why I do not even bother to even bother with it)

    I was looking at something in the ExtJS sources when I tumbled upon some developer comments as said before. I do not have an out of the box solution people can use.

    Since I got away with javascript all together (I really hate it) and do everything in python, I can not give you any readable code (Since my python code is compiled into Javascript, minimized etc. it is jus not suited for the human brain)

    Let me explain what I did to get at least Forms working, I'll use addresses as an example.

    I use MVC/Application structure, where the 'C' bit in my system is not that interesting but that is due to the way my compiler outputs all the event routines inside the class definition (either in listeners of a direct property like launch : function(){...})


    I use SQLAlchemy which is a ORM (Object Relational Mapper) for Python and I Use Polymorphic table inheritance all over the place.


    On the details panel of a company, I get the company record (Into a extjs formpanel, which is placed on a MAIN panel). On Company I have a relation to "addresses":


    Company:
    field : id
    field : Name
    field : addresses = relation to all addresses with this Company's id


    address:
    field : id
    discriminator : "kind of address"


    email_address:
    id (is a foreign key to address.id)
    Value : String like "me@somewhere.com"


    twitter_address:
    id : (a foreign key to address.id)
    Value : "@tw_account"


    etc...


    So when I have loaded Company, I iterate over addresses:
    (Request to the server are nicely batched, but an extra set of querys are run so be carefull on large datasets)

    (Explanational code, not real)
    for ad in LoadedCompany.addresses.each():
    if ad.discriminator == 'email_address'
    var x = Ext.create('app.view.email_addressForm')
    MAIN.items.append(x)
    //(adds email_addressForm after CompanyForm)
    x.load(address.id)
    // get the data loaded into the form (no store needed)
    if ad.discriminator == 'twitter_address':
    var x = Ext.create('app.view.twitter_addressForm')
    MAIN.items.append(x)
    //(adds twitter_addressForm after CompanyForm)
    x.load(address.id)
    // get the data loaded into the form (no store needed)
    etc...


    After running I have a MAIN panel with a Company form, and as many "address" forms as there is data in the database where every address type is loaded into its "own" from type.


    to reduce overhead and double data I have multiple models for address (the main table)
    so address does only send "id"


    and "discriminator" where every individual address type has a model to include every field needed to create, remove, delete etc. my back-end handles the rest.


    With that I must say I'm lucky with my system since I only have to create python objects to reflect database storage, SQLAlchemy takes out database specific stuff (I can switch between MySQL, PostgreSQL, MSSQL etc. if needed without code changes). My 'Compiler' introspects the python Classes and automatically generates everything in the "models" and "stores" directories. it generates relationships, validations and Ext.Direct remoting api.


    In my stores and models I have over 1500 .js files I just do not need to build by hand.


    For Grid's this is more complex and I do not have a solution to put mixed content into a grid. For my use I got away with specific models and stores. When I need a grid I just define the "Fields" from different models and a new model is generated for each grid, again I have this automated (one extra reason for this 1500 files).


    Since I expect some day Sencha will wake up and actually add polymorphic table inheritance support to their models. I do not want to do their work and worked around it for now. In my situation that is not that bad. I just add support for it into my compiler and "recompile" after a very few code changes.


    But if you are developing in MVC by hand in an environment like Eclipse (like I did) it will run into an absolute nightmare, maintaining all those different files. I clearly got a solution for the "models, stores, controllers and views properties of ext.app.Application since it is all generated automatically.


    Sorry for not being able to help you any further but feel free to contact me. If you feel I can help you out.


    Extjs 4 promised to be capable of supporting large projects unfortunately there seems to be little research into what people really want to make use of it.
    I used Extjs 2.1 up to 4.1 (B3) and very, very slowly it is getting there. For me the only thing missing now is Polymorphic table inheritance support in Ext.data.Model.


    I have investigated to actually build it myself. I think that Sencha Devs would be capable of integrating this into 4.1 would take relatively little effort due to the nature of how Javascript works and how they coded the data package. Basically support for reading mixed record-types from the server response based on a discriminator field would be a nice first step. I actually think that would sort of work.


    If you really want more support I found out some things but have not really put any effort in it.


    Consider this:
    data returned on a app.store.address query:
    [
    {id : 1, discriminator : 'email_address', Value : 'someone@somewhere.com'},
    {id : 2, discriminator : 'twitter_address', Value : '@tw_address'}
    ]


    on the store.load event, you could look at record.get('discriminator')


    then try to load that record into the right model (just a single instance) and add that to an array you can work with (so your code works on an Array of mixed model instances) or just load the right form type and query the server again for that record.
    You might (as I did not test this) look at the rawvalue of the record (look at the record object from within Firebug or whatever you use, to find more) in the store's load event.
    as long as you are working with forms the above would do. I'm not sure what a grid would do and I'm not really sure how you would set up your gridcolums etc. that will be the next thing to address.


    I wonder I someone @ Sencha would dare to share thoughts on this, based on my 4 year experience with them they would not.






    Jash

  4. #4
    Sencha User
    Join Date
    Dec 2011
    Posts
    219
    Vote Rating
    9
    dedoz will become famous soon enough

      1  

    Default


    i think you guys trying to say "polymorphic association" what you are explaning has nothing to do with inheritance.
    and yes theres a comment in the source code bout polymorphic association
    Code:
    // TODO Add this back when it's fixed
    // case 'polymorphic':
    //      return Ext.create('Ext.data.PolymorphicAssociation', association);
    first from your post you cant have a field that holds many values, in a relational dabase
    each field is atomic, also in Extjs the "has many" records are holded in a associated store not in model field
    so doing
    for ad in LoadedCompany.addresses.each():
    in ExtJs, means adderess() is a associated store that was created after you declared a hasMany association, so this coulnd come from your declaration
    field : addresses = relation to all addresses with this Company's id
    then your post you said
    So when I have loaded Company, I iterate over addresses:
    (Request to the server are nicely batched, but an extra set of querys are run so be carefull on large datasets)
    why extra querys ? you can load a company and the response can come with all the address you are goin to use (you can load a record and all its associated data in 1 call to the server). then iterating over adresses doesnt trigger any server request.

    instead of posting what can u do in another lenguaje/orm post what u want to do in extjs.
    post the dabase model / schema and how are you setting polymorphic association in it
    polymorphic association is just a concept, and the implementation may differ
    usually the relational database behind it looks like
    Code:
    user
      id <--- its own id 
    
    company
      id <-- its own id
    
    email    (user emails and company emails)
      id <-- its own table id
      adress <-- twitter adderess
      poly_id <-- poly id              // instead of declarating  company_id and user_id  fields you set a poly id
      poly_type <-- some entity name
    
    twitter (user twitter and company twitters)
      id <-- its own table id
      address <-- twitter adress
      poly_id <-- poly id
      poly_type <-- some entity name
    
    (between  COMPANY and EMAIL/TWITTER theres no need for a ADDRESS intermediate table)
    dabase saved records
    Code:
    user
        id = 1
    
    company 
        id = 1
     
    email 
       id    dir                 poly_id   poly_type 
      1 , 'email1@server.com' ,   1,      'user'
      2,  'email2@server.com' ,   1,       'user' 
      3 , 'email3@server.com' ,  1,      'company'
    
    twitter
       id    dir                  poly_id   poly_type 
      1 , 'twitter1@twitter.com' ,   1,      'user'
      2,  'twitter2@twitter.com' ,   1,       'company' 
      3 , 'twitter3@twitter.com' ,   1,      'company'
    thats in the dabase, it doenst matter if you are using XXX server lenguaje and XXX server ORM because thats an option you took, the important is to check if extjs can work with this database that its implemeting polymorphic associations

    Exjs user model
    Code:
    Ext.define ('User') {
          ...... fields and stuff ....
       hasMany : [
        {name : 'emails',  model : 'email', foreignKey : 'poly_id', associationKey :  'emailrecords'}
        {name : 'twitters',  model : 'twitter', foreignKey : 'poly_id', associationKey :  'twotterrecords'}
    ]
    }
    now u can load an user
    Code:
    User.load(1 , {  // this is the only request to the server "load user 1"
        callback : function(user) {   
            user.emails().each (function(email){ // print all user emails
                console.log(  email.get('address')  ) 
            }
            user.twitters().each (function(twitter){  // print all user twitters
                console.log(  twitter.get('address')  ) 
                    }
           }
    });
    and the "load user 1" response is similar to
    Code:
    {  id : 1,
       name : 'peter', 
       emailsrecords : [
              {id : 1, address: 'email1@server.com',  poly_id: 1, poly_type : 'user'},
              {id : 2, address: 'email2@server.com',  poly_id: 1, poly_type : 'user'},
       ]
       twitterrecords : [
              {id : 1, address: 'twitter1@twitter.com',  poly_id: 1, poly_type : 'user'}
       ]   
    }
    adding a new record in Extjs
    Code:
    newEmail = Ext.create('Email', { 
         address : 'anotherEmail@servercom' , 
         poly_type : 'user'
    });
    
    peter.emails().add(newEmail)
    newEmail.get('poly_id') // it was set to 1 automatically 
                                        // by Extjs and its the declared foreign key
                                         // if doesnt you can always set manually
    (i didnt test any posted code but i used just regular model/association stuff, so it should work )

    so from this maybe you can change some things to work with your models / server code, but at the end is very simple and doesnt need that much work to be waiting for Extjs realease a polymophic association

    the only need of polymorphic association is when trying to access the user from the email, but as you were loading the company theres no need.

    hope this helps you and sorry for my bad english

  5. #5
    Sencha User
    Join Date
    Jul 2008
    Posts
    53
    Vote Rating
    0
    jash is on a distinguished road

      0  

    Default


    dedoz,

    I wrote a lengty reply yesterday but the forums (even though autosave sort of works) kicked me out.

    First of all I am not sure where you did get the info on PM associations. Even the docs of 4.1B3 do not speak about it.

    Next, my back-end does not include related data. If I do so on every query almost my entire database is dumped. so that is not an option.

    In fact you are reasoning the other way around, I'm not going Extjs to give the lead over how stuff is handled, extjs should support every data configuration in the back-end too.

    Polymorphic table inheritance is just so common these days and I have not been able the get it working with extjs in a way that it is configurable and can reflect my back-end data.

    you say:
    instead of posting what can u do in another lenguaje/orm post what u want to do in extjs.
    post the dabase model / schema and how are you setting polymorphic association in it
    polymorphic association is just a concept, and the implementation may differ
    usually the relational database behind it looks like

    that is totally wrong! and the other way around. I can do things in my back-end and that is my freedom and needed to bring innovative solutions. in fact Extjs has been way behind in what I need and has been the part in my system that holds stuff back over the last few years. the data package has been a huge improvement but it is far from functional in the sense of reflecting more complex databases (Polymorphic table inheritance, self referencing many to many relations and combinations of those two.

    In my case I use Extjs as some sort of data consuming dumb terminal and NOT to define the entire application, that is done in my back-end.

    for people interested about polymorphic table inheritance have a look at : http://docs.sqlalchemy.org/en/latest...heritance.html

    and again where did you get the info about PM associations? you can say it is just a concept, stuff like this have been a concept to me 15-20 years ago, is the wheel reinvented here?

    I have some thoughts about extending store to make Extjs read data but I still think it is dangerous since Sencha can suddenly move into something completely different and I have Touch to consider too extjs and touch are closing in on eachother but the catching up cycle seems to be one year. I am sort of done with hacking stuff over from extjs to touch (like we had to do with Ext.direct it makes upgrading a nightmare.

    Jash

  6. #6
    Sencha User
    Join Date
    Dec 2011
    Posts
    219
    Vote Rating
    9
    dedoz will become famous soon enough

      0  

    Default


    First of all I am not sure where you did get the info on PM associations. Even the docs of 4.1B3 do not speak about it.
    as my post says above the PM association comment, "theres a comment in the source code" (its just code comment in associations source code)

    Next, my back-end does not include related data. If I do so on every query almost my entire database is dumped. so that is not an option.
    not really, well if you like "always return every associated record" well of course thats not the way to go.. you can always pass extra params when loading stuff and you can tell to the server "send me person 1 , include its employee too plx" something like that. how ? just put an extra param that your server can interpret as "include employees" so he will append those requested records. for my app my server side expect a key like "include : ['phones','emails']" and stuff like that.

    extjs should support every data configuration in the back-end too.
    first thats not the reallity and we need to work with what extjs can do or wait a year to implement your app. i just posted an idea to help you doing what u wanted to do, second and most important no tecnology will give you all the features that "other tecnology" has, like expecting Extjs can do all data modeling that can be done in php, and in ruby too, and perl , and all the ORM like doctrine, propel, activeRecord, etc. could be insane. the base is the DBMS like mysql, postgres and sqlserver, should at least cover some common schema definition, as any ORM doesnt give full suport for every feature on every DBMS they can work agaisnt.

    that is totally wrong! and the other way around. I can do things in my back-end and that is my freedom and needed to bring innovative solutions.
    i agree and i didnt say anything diferent to that. i said "post what u wanna do instead of ... " thats all.

    and again where did you get the info about PM associations? you can say it is just a concept, stuff like this have been a concept to me 15-20 years ago, is the wheel reinvented here?
    its a concept because theres no direct implementation in most relational databases its an idea that gets implemented using common field like poly_id and poly_type is not like you goin to set PRIMARY KEY POLYMORPHIC(somestuff) dunno, is pretty much like many to many relationship is a concept and yes its been there for years too but still this only exists in a conceptual model and on the phisical model that targets a relational dabatabase (commons, didnt check sqlserver lasts versions) it cannot be implemented directly and you have to implement using other stuff like setting a middle table and two has many relationships, etc. u get the idea bout a concept and conceptual schemas?

    in fact Extjs has been way behind in what I need and has been the part in my system that holds stuff back over the last few years
    i agree. ext model package is missing some important stuff but its what its :d i have my own issues trying to implement some stuff using models/stores but at the end, thats whats this tool can offer to us at the moment, crying worth nothing :d

    my english fails :d

  7. #7
    Sencha User
    Join Date
    Jul 2008
    Posts
    53
    Vote Rating
    0
    jash is on a distinguished road

      0  

    Default


    What I want to do is something like I'll write up later on. It will not be usable code at all. I will use it to demonstrate what I would like to achieve, one way or another. After that I will share my thoughts on what is needed to get it working. My knowledge about ExtJs internals is not enough to make a proper decision on how I should start.



    the comments behind the fields inform about how it is stored in the database:
    PK = Primary KEy
    AUTO = auto increment
    FK = foreign key to ('model.field')
    PHP Code:
    ext.define('a.model.Address',{ 
     
    extend 'Ext.data.Model'
     
    fields  : [         {name 'id'type 'int'}  // PK, AUTO 
               
    {name 'discriminator'type 'string'} , // string column 
              


       

    ); 
     
    ext.define('a.model.emailaddress',{ 
       
    extend 'a.model.address',            // IMPORTANT 
       
    fields  : [ 
               {
    name 'id'type 'int'}  // PK, FK('address.id') 
               
    {name 'Value'type 'string'} , // string column 
              
    ], 

    ); 
     
    ext.define('a.model.twitteraddress',{ 
       
    extend 'a.model.address',            // IMPORTANT 
       
    fields  : [ 
               {
    name 'id'type 'int'}  // PK, FK('address.id') 
               
    {name 'Value'type 'string'} , // string column 
              
    ], 

    ); 
    on the //IMPORTAND on the extends:
    the subclass of address will add all the fields from address and add its own. this is NOT reflected in the above, I'm not sure on how to do so, within an init? there is no doc about init on Ext.data.model so that seems impossible. id is overwritten so in this case only

    The smart ones of you see no use for this since both twitter and email models have just a 'Value' field. just add 'Type' and 'Value' to address you would say. In fact replace 'Value' for any number of fields you like. i.e.. street, zip, city, country for a postal address etc. I stick with Value because that is the use cause but not the problem. To address things can be added like security or common associations can be set up which should be inherited too as do the validations

    all the support for maintaining the records and the id and discriminator fields is in the back-end. We need the 'discriminator' field to distinguish between model types on loading in the -modified- store

    now for the data in the database take this:

    address:
    id Discriminator
    1 twitteraddress
    2 emailaddress
    3 twitteraddressid


    emailaddress:
    id Value
    2 jash@jash.com


    twitteraddress:
    id Value
    1 @jash
    3 @jash2

    as you can see for every emailaddress and twitter address record, a record in address is also created.
    there is no real use in storing records of the 'Address' model but that will be very handy later on in querying:

    on query's I will give the SQL equivalent and the json data output for that

    SELECT * FROM address;
    [
    {id : 1, discriminator : 'twitteraddress', Value : '@jash'},
    {id : 2, discriminator : 'emailaddress', Value : 'jash@jash.com'},
    {id : 3, discriminator : 'twiteraddress', Value : '@jash2'}
    ]

    here you can see the problem, a store can handle [model1,model1,model1] as data but what if [model1, model2, model1] is fed into it......?

    PHP Code:
    ext.define('a.store.addresses',{ 
    extend 'Ext.data.Store'
    model 'a.model.address',   // so it query's address, good!! 
    models : {address 'a.model.address',emailaddress 'a.model.emailaddress',twitter address'a.model.'twitter address'}    // NEW these models can come in, translate discriminator to modelname 
     
    listeners : { 
             load : function(Record){ 
                 this.each(Record){ 
                   // do something based on Record.get('
    discriminator') 
                   // to load the store with mixed model reflecting the data 
                   // this.data (Store.data) is a MixedCollection type ..?..?..!..!! 
             } 
     


    I am not sure what next and if this is the right way. there is also writing (create/update) to take into account.
    Maybe the jsonReader and jsonWriter on the proxy need some work to.

    if I look at denoz first post the polymorphic could be opening possibilities

    that would translate to

    PHP Code:
    ext.define('a.model.Address',{ 
       
    extend 'Ext.data.Model'
       
    fields  : [ 
    /*poly_Id*/            {name 'id'type 'int'}  // PK, AUTO 
    /*poly_type*/          
    {name 'discriminator'type 'string'} , // string column 
                         
    {name 'SomethingCommon'
     
              ] 

       

    ); 
    @dedoz: Your english is fine to me!

    jash

Thread Participants: 2

Tags for this Thread