Partial Updates (aka PATCH) using a $resource based service?

后端 未结 3 712
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-29 11:38

We\'re building a web application using Django/TastyPie as the back-end REST service provider, and building an AngularJS based front end, using lots of $resource based servi

相关标签:
3条回答
  • 2020-12-29 12:13

    We implemented $patchusing ngResource, but it's a bit involved (we use Django Rest Framework on the server-side). For your diff component, I'll leave to your own implementation. We use a pristine cache to track changes of resources, so I can poll a given object and see what (if any) has changed.

    I leverage underscore's _.pick() method to pull the known fields to save off the existing instance, create a copy (along with the known primary key) and save that using $patch.

    We also use some utility classes to extend the built-in resources.

    app.factory 'PartUpdateMixin', ['$q', '_', ($q, _) ->
    
        PartUpdateMixin = (klass) ->
            partial_update: (keys...) ->
                deferred = $q.defer()
                params = _.pick(@, 'id', keys...)
                o = new klass(params)
                o.$patch(deferred.resolve, deferred.reject)
                return deferred.promise
    ]
    

    Here's the utility classes to enhance the Resources.

    app.factory 'extend', ->
        extend = (obj, mixins...) ->
            for mixin in mixins
                obj[name] = method for name, method of mixin
            obj
    
    app.factory 'include', ['extend', (extend) ->
        include = (klass, mixins...) ->
            extend klass.prototype, mixins...
    
        return include
    ]
    

    Finally, we can enhance our Resource

    include TheResource, PartUpdateMixin(TheResource)
    resourceInstance = TheResource.get(id: 1234)
    # Later...
    updatedFields = getChangedFields(resourceInstance)
    resourceInstance.partial_update(updatedFields...)
    
    0 讨论(0)
  • 2020-12-29 12:20

    I would suggest using

    update: {
        method: 'PATCH',
        transformRequest: dropUnchangedFields
    }
    

    where

    var dropUnchangedFields = function(data, headerGetter) {
    
        /* compute from data using your .diff method by  */
        var unchangedFields = [ 'name', 'street' ];
    
        /* delete unchanged fields from data using a for loop */ 
        delete data['name'] ;
        delete data['street'];
    
        return data;
    
    }
    

    PS: not sure from memory, whether data is a reference to your resource of a copy of it, so you may need to create a copy of data, before deleting fields

    Also, instead of return data, you may need return JSON.stringify(data).


    Source (search for "transformRequest" on the documentation page)

    0 讨论(0)
  • 2020-12-29 12:26

    I would suggest using Restangular over ngResource. The angular team keeps improving ngResource with every version, but Restangular still does a lot more, including allowing actions like PATCH that ngResource doesn't. Here'a a great SO question comparing the two What is the advantage of using Restangular over ngResource?

    0 讨论(0)
提交回复
热议问题