Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / data / proxy / Rest.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @author Ed Spencer
17  *
18  * The Rest proxy is a specialization of the {@link Ext.data.proxy.Ajax AjaxProxy} which simply maps the four actions
19  * (create, read, update and destroy) to RESTful HTTP verbs. For example, let's set up a {@link Ext.data.Model Model}
20  * with an inline Rest proxy
21  *
22  *     Ext.define('User', {
23  *         extend: 'Ext.data.Model',
24  *         fields: ['id', 'name', 'email'],
25  *
26  *         proxy: {
27  *             type: 'rest',
28  *             url : '/users'
29  *         }
30  *     });
31  *
32  * Now we can create a new User instance and save it via the Rest proxy. Doing this will cause the Proxy to send a POST
33  * request to '/users':
34  *
35  *     var user = Ext.create('User', {name: 'Ed Spencer', email: 'ed@sencha.com'});
36  *
37  *     user.save(); //POST /users
38  *
39  * Let's expand this a little and provide a callback for the {@link Ext.data.Model#save} call to update the Model once
40  * it has been created. We'll assume the creation went successfully and that the server gave this user an ID of 123:
41  *
42  *     user.save({
43  *         success: function(user) {
44  *             user.set('name', 'Khan Noonien Singh');
45  *
46  *             user.save(); //PUT /users/123
47  *         }
48  *     });
49  *
50  * Now that we're no longer creating a new Model instance, the request method is changed to an HTTP PUT, targeting the
51  * relevant url for that user. Now let's delete this user, which will use the DELETE method:
52  *
53  *         user.destroy(); //DELETE /users/123
54  *
55  * Finally, when we perform a load of a Model or Store, Rest proxy will use the GET method:
56  *
57  *     //1. Load via Store
58  *
59  *     //the Store automatically picks up the Proxy from the User model
60  *     var store = Ext.create('Ext.data.Store', {
61  *         model: 'User'
62  *     });
63  *
64  *     store.load(); //GET /users
65  *
66  *     //2. Load directly from the Model
67  *
68  *     //GET /users/123
69  *     Ext.ModelManager.getModel('User').load(123, {
70  *         success: function(user) {
71  *             console.log(user.getId()); //outputs 123
72  *         }
73  *     });
74  *
75  * # Url generation
76  *
77  * The Rest proxy is able to automatically generate the urls above based on two configuration options - {@link #appendId} and
78  * {@link #format}. If appendId is true (it is by default) then Rest proxy will automatically append the ID of the Model
79  * instance in question to the configured url, resulting in the '/users/123' that we saw above.
80  *
81  * If the request is not for a specific Model instance (e.g. loading a Store), the url is not appended with an id.
82  * The Rest proxy will automatically insert a '/' before the ID if one is not already present.
83  *
84  *     new Ext.data.proxy.Rest({
85  *         url: '/users',
86  *         appendId: true //default
87  *     });
88  *
89  *     // Collection url: /users
90  *     // Instance url  : /users/123
91  *
92  * The Rest proxy can also optionally append a format string to the end of any generated url:
93  *
94  *     new Ext.data.proxy.Rest({
95  *         url: '/users',
96  *         format: 'json'
97  *     });
98  *
99  *     // Collection url: /users.json
100  *     // Instance url  : /users/123.json
101  *
102  * If further customization is needed, simply implement the {@link #buildUrl} method and add your custom generated url
103  * onto the {@link Ext.data.Request Request} object that is passed to buildUrl. See [Rest proxy's implementation][1] for
104  * an example of how to achieve this.
105  *
106  * Note that Rest proxy inherits from {@link Ext.data.proxy.Ajax AjaxProxy}, which already injects all of the sorter,
107  * filter, group and paging options into the generated url. See the {@link Ext.data.proxy.Ajax AjaxProxy docs} for more
108  * details.
109  *
110  * [1]: source/RestProxy.html#method-Ext.data.proxy.Rest-buildUrl
111  */
112 Ext.define('Ext.data.proxy.Rest', {
113     extend: 'Ext.data.proxy.Ajax',
114     alternateClassName: 'Ext.data.RestProxy',
115     alias : 'proxy.rest',
116     
117     /**
118      * @cfg {Boolean} appendId
119      * True to automatically append the ID of a Model instance when performing a request based on that single instance.
120      * See Rest proxy intro docs for more details. Defaults to true.
121      */
122     appendId: true,
123     
124     /**
125      * @cfg {String} format
126      * Optional data format to send to the server when making any request (e.g. 'json'). See the Rest proxy intro docs
127      * for full details. Defaults to undefined.
128      */
129     
130     /**
131      * @cfg {Boolean} batchActions
132      * True to batch actions of a particular type when synchronizing the store. Defaults to false.
133      */
134     batchActions: false,
135     
136     /**
137      * Specialized version of buildUrl that incorporates the {@link #appendId} and {@link #format} options into the
138      * generated url. Override this to provide further customizations, but remember to call the superclass buildUrl so
139      * that additional parameters like the cache buster string are appended.
140      * @param {Object} request
141      */
142     buildUrl: function(request) {
143         var me        = this,
144             operation = request.operation,
145             records   = operation.records || [],
146             record    = records[0],
147             format    = me.format,
148             url       = me.getUrl(request),
149             id        = record ? record.getId() : operation.id;
150         
151         if (me.appendId && id) {
152             if (!url.match(/\/$/)) {
153                 url += '/';
154             }
155             
156             url += id;
157         }
158         
159         if (format) {
160             if (!url.match(/\.$/)) {
161                 url += '.';
162             }
163             
164             url += format;
165         }
166         
167         request.url = url;
168         
169         return me.callParent(arguments);
170     }
171 }, function() {
172     Ext.apply(this.prototype, {
173         /**
174          * @property {Object} actionMethods
175          * Mapping of action name to HTTP request method. These default to RESTful conventions for the 'create', 'read',
176          * 'update' and 'destroy' actions (which map to 'POST', 'GET', 'PUT' and 'DELETE' respectively). This object
177          * should not be changed except globally via {@link Ext#override Ext.override} - the {@link #getMethod} function
178          * can be overridden instead.
179          */
180         actionMethods: {
181             create : 'POST',
182             read   : 'GET',
183             update : 'PUT',
184             destroy: 'DELETE'
185         }
186     });
187 });
188