Success! Looks like we've fixed this one. According to our records the fix was applied for EXTJS-6981 in 4.2.0.489.
  1. #1
    Sencha User mono blaine's Avatar
    Join Date
    Jul 2008
    Location
    Turkey
    Posts
    123
    Vote Rating
    8
    mono blaine will become famous soon enough

      1  

    Default hasOne & belongsTo createSetter Bug

    hasOne & belongsTo createSetter Bug


    REQUIRED INFORMATION


    Ext version tested:
    • Ext 4.1.1
    Browser versions tested against:
    • Chrome 21
    Description:
    • The createSetter method implementations of both the hasOne and belongsTo association classes do not set the associated record argument to this[association.instanceName].
    Steps to reproduce the problem:
    • Create two model classes, Model1 and Model2, one linked to the other with a "hasOne" association
    • Use the setter method of the main record (of type Model1) to set an associated record of type Model2
    The result that was expected:
    • Besides the foreignKey value, the instance property should have also been set with a reference to the associated record.
    The result that occurs instead:
    • The value of the foreignKey in Model1 is updated, however the instance property does not.
    Test Case:

    Code:
    Ext.define('Address', {
        extend: 'Ext.data.Model',
        fields: [{
            name: 'id',
            type: 'int'
        }, {
            name: 'number',
            type: 'string'
        }, {
            name: 'street',
            type: 'string'
        }, {
            name: 'city',
            type: 'string'
        }, {
            name: 'zip',
            type: 'string'
        }, ]
    });
    
    Ext.define('Person', {
        extend: 'Ext.data.Model',
        fields: [{
            name: 'id',
            type: 'int'
        }, {
            name: 'name',
            type: 'string'
        }, {
            name: 'address_id',
            type: 'int'
        }],
        associations: [{
            type: 'hasOne',
            model: 'Address'
        }]
    });
    
    var addressRecord = Address.create({
        id: 1,
        street: "bla bla"
    }),
        personRecord = Person.create({
            id: 47,
            name: "mono blaine"
        });
    
    personRecord.setAddress(addressRecord);
    
    personRecord.getAddress(); // --> nothing?


    HELPFUL INFORMATION


    Possible fix:

    The createSetter implementation should be as follows:

    Code:
    /**
     * @private
     * Returns a setter function to be placed on the owner model's prototype
     * @return {Function} The setter function
     */
    createSetter: function () {
        var me = this,
            foreignKey = me.foreignKey,
            instanceName = me.instanceName;
    
        //'this' refers to the Model instance inside this function
        return function (value, options, scope) {
            var shouldSetInstance = value && value.isModel;
    
            if (shouldSetInstance) {
                this[instanceName] = value;
            }
    
            this.set(foreignKey, shouldSetInstance ? value.getId() : value);
    
            if (Ext.isFunction(options)) {
                options = {
                    callback: options,
                    scope: scope || this
                };
            }
    
            if (Ext.isObject(options)) {
                return this.save(options);
            }
        };
    }

  2. #2
    Sencha User mono blaine's Avatar
    Join Date
    Jul 2008
    Location
    Turkey
    Posts
    123
    Vote Rating
    8
    mono blaine will become famous soon enough

      1  

    Default


    The solution I proposed misses an important point (invalid associated record instance references), so here is an updated fix:

    Code:
    createSetter: function () {
        var me = this,
            foreignKey = me.foreignKey,
            instanceName = me.instanceName;
    
        //'this' refers to the Model instance inside this function
        return function (value, options, scope) {
            var setByRecord = value && value.isModel,
                valueToSet = setByRecord ? value.getId() : value;
    
            if (setByRecord) {
                this[instanceName] = value;
            }
            else if (this[instanceName] instanceof Ext.data.Model && this.get(foreignKey) !== valueToSet) {
                /*
                 * It means we are updating only the value of the field, 
                 * thus we have to delete the previous associated record instance reference.
                 */
                delete this[instanceName];
            }
    
            this.set(foreignKey, valueToSet);
    
            if (Ext.isFunction(options)) {
                options = {
                    callback: options,
                    scope: scope || this
                };
            }
    
            if (Ext.isObject(options)) {
                return this.save(options);
            }
        };
    }

  3. #3
    Sencha User
    Join Date
    Jun 2011
    Location
    Ukraine, Kherson
    Posts
    30
    Vote Rating
    0
    lufton is on a distinguished road

      0  

    Default


    This issue is present in ExtJs 4.2b, fixed with code above. Please apply this patch in next release .

  4. #4
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,502
    Vote Rating
    48
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Good analysis, and thanks for the pointers to the solution. I have pushed a proposed fix for this, and it should be in the 4.2 final.

  5. #5
    Sencha User
    Join Date
    Jun 2011
    Location
    Ukraine, Kherson
    Posts
    30
    Vote Rating
    0
    lufton is on a distinguished road

      0  

    Default


    Quote Originally Posted by Animal View Post
    Good analysis, and thanks for the pointers to the solution. I have pushed a proposed fix for this, and it should be in the 4.2 final.
    You are welcome!

Thread Participants: 2