Skip to content

Commit 5218d60

Browse files
committed
Merge branch 'master' of github.com:mgonto/restangular
2 parents 881b76b + cbe6d17 commit 5218d60

File tree

6 files changed

+1377
-1267
lines changed

6 files changed

+1377
-1267
lines changed

README.md

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Restangular
22

3-
[![Build Status](https://travis-ci.org/mgonto/restangular.png)](https://travis-ci.org/mgonto/restangular)
3+
[![Build Status](https://travis-ci.org/mgonto/restangular.svg?branch=master)](https://travis-ci.org/mgonto/restangular)
44
[![PayPayl donate button](http://img.shields.io/paypal/donate.png?color=yellow)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=martin%40gon%2eto&lc=US&item_name=Martin%20Gontovnikas&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted "Donate once-off to this project using Paypal")
55
[![Donate on Gittip](http://img.shields.io/gittip/mgonto.svg)](https://www.gittip.com/mgonto/)
66
<a href="https://twitter.com/intent/tweet?hashtags=&original_referer=http%3A%2F%2Fgithub.com%2F&text=Check+out+Restangular%2C+a+service+for+%23AngularJS+that+makes+it+easy+to+use+Rest+APIs&tw_p=tweetbutton&url=https%3A%2F%2Fgithub.com%2Fmgonto%2Frestangular" target="_blank">
@@ -80,19 +80,22 @@ You can also **check out [a video introduction of a talk I gave at Devoxx France
8080
- [How do I handle CRUD operations in a List returned by Restangular?](#how-do-i-handle-crud-operations-in-a-list-returned-by-restangular)
8181
- [When I set baseUrl with a port, it's stripped out.](#when-i-set-baseurl-with-a-port-its-stripped-out)
8282
- [How can I access the unrestangularized element as well as the restangularized one?](#how-can-i-access-the-unrestangularized-element-as-well-as-the-restangularized-one)
83+
- [Restangular fails with status code 0](#restangular-fails-with-status-code-0)
8384
- [Why does this depend on Lodash / Underscore?](#why-does-this-depend-on-lodash--underscore)
8485
- [Supported Angular versions](#supported-angular-versions)
8586
- [Server Frameworks](#server-frameworks)
8687
- [Releases Notes](#releases-notes)
8788
- [License](#license)
8889

90+
**[Back to top](#table-of-contents)**
91+
8992
## Differences with $resource
9093

9194
Restangular has several features that distinguish it from $resource:
9295

9396
* **It uses [promises](http://docs.angularjs.org/api/ng.$q)**. Instead of doing the "magic" filling of objects like $resource, it uses promises.
9497
* **You can use this in $routeProvider.resolve**. As Restangular returns promises, you can return any of the methods in the `$routeProvider.resolve` and you'll get the real object injected into your controller if you want.
95-
* **It doesn't have all those `$resource` bugs**. Restangular doesn't have problem with trailling slashes, additional `:` in the URL, escaping information, expecting only arrays for getting lists, etc.
98+
* **It doesn't have all those `$resource` bugs**. Restangular doesn't have problem with trailing slashes, additional `:` in the URL, escaping information, expecting only arrays for getting lists, etc.
9699
* **It supports all HTTP methods**.
97100
* **It supports ETag out of the box**. You don't have to do anything. ETags and If-None-Match will be used in all of your requests
98101
* **It supports self linking elements** If you receive from the server some item that has a link to itself, you can use that to query the server instead of writing the URL manually.
@@ -127,6 +130,8 @@ $scope.user.one('messages', 123).one('from', 123).getList('unread');
127130

128131
````
129132

133+
**[Back to top](#table-of-contents)**
134+
130135
#How do I add this to my project?
131136

132137
You can download this by:
@@ -142,17 +147,23 @@ You can download this by:
142147
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/restangular/1.3.1/restangular.min.js"></script>
143148
````
144149

150+
**[Back to top](#table-of-contents)**
145151

146152
#Dependencies
147153

148154
Restangular depends on Angular and Lodash (or Underscore).
149155

156+
**[Back to top](#table-of-contents)**
157+
150158
# Production apps using Restangular
151159

152160
Each time, there're more Production WebApps using `Restangular`. If your webapp uses it and it's not in the list, please create an issue or submit a PR:
153161

154162
* **Life360** is using Restangular to build the WebApp version of their platform
155163
* **Thomson Reuters** is using Restangular for the new Webapp they've built
164+
* **Quran.com** is using Restangular for their alpha/beta app and soon to be main site
165+
166+
**[Back to top](#table-of-contents)**
156167

157168
#Starter Guide
158169

@@ -173,6 +184,8 @@ The Restangular service may be injected into any Controller or Directive :)
173184
Note: When adding Restangular as a dependency it is not capitalized 'restangular'
174185
But when injected into your controller it is 'Restangular'
175186

187+
**[Back to top](#table-of-contents)**
188+
176189
## Using Restangular
177190

178191
### Creating Main Restangular object
@@ -192,6 +205,8 @@ Restangular.one('accounts', 1234)
192205
Restangular.several('accounts', 1234, 123, 12345);
193206
````
194207

208+
**[Back to top](#table-of-contents)**
209+
195210
### Let's code!
196211

197212
Now that we have our main Object let's start playing with it.
@@ -308,6 +323,8 @@ account.customPOST({name: "My Message"}, "messages", {param: "myParam"}, {})
308323

309324
````
310325

326+
**[Back to top](#table-of-contents)**
327+
311328
## Configuring Restangular
312329

313330
### Properties
@@ -536,6 +553,8 @@ You can set this to either `true` or `false`. By default it's false. If set to t
536553

537554
You can set here if you want to URL Encode IDs or not. By default, it's true.
538555

556+
**[Back to top](#table-of-contents)**
557+
539558
### Accessing configuration
540559

541560
You can also access the configuration via `RestangularProvider` and `Restangular` via the `configuration` property if you don't want to use the setters. Check it out:
@@ -544,6 +563,8 @@ You can also access the configuration via `RestangularProvider` and `Restangular
544563
Restangular.configuration.requestSuffix = '/';
545564
````
546565

566+
**[Back to top](#table-of-contents)**
567+
547568
### How to configure them globally
548569

549570
You can configure this in either the `config` or the `run` method. If your configurations don't need any other services, then I'd recommend you do them in the `config`. If your configurations depend on other services, you can configure them in the `run` using `Restangular` instead of `RestangularProvider`
@@ -606,6 +627,8 @@ app.run(function(Restangular, BaseUrlCalculator) {
606627
});
607628
````
608629

630+
**[Back to top](#table-of-contents)**
631+
609632
### How to create a Restangular service with a different configuration from the global one
610633
Let's assume that for most requests you need some configuration (The global one), and for just a bunch of methods you need another configuration. In that case, you'll need to create another Restangular service with this particular configuration. This scoped configuration will inherit all defaults from the global one. Let's see how.
611634

@@ -636,6 +659,8 @@ app.controller('MainCtrl', function(Restangular, BingRestangular) {
636659
});
637660
````
638661

662+
**[Back to top](#table-of-contents)**
663+
639664
### Decoupled Restangular Service
640665

641666
There're some times where you want to use Restangular but you don't want to expose Restangular object anywhere. For those cases, you can actually use the `service` feature of Restangular.
@@ -669,6 +694,8 @@ var Cars = Restangular.service('cars', Restangular.one('users', 1));
669694
Cars.getList() // GET to /users/1/cars
670695
````
671696

697+
**[Back to top](#table-of-contents)**
698+
672699
## Methods description
673700

674701
There are 3 sets of methods. Collections have some methods and elements have others. There are are also some common methods for all of them
@@ -683,6 +710,7 @@ These are the methods that can be called on the Restangular object.
683710
* **restangularizeElement(parent, element, route, queryParams)**: Restangularizes a new element
684711
* **restangularizeCollection(parent, element, route, queryParams)**: Restangularizes a new collection
685712

713+
**[Back to top](#table-of-contents)**
686714

687715
### Element methods
688716
* **get([queryParams, headers])**: Gets the element. Query params and headers are optionals
@@ -702,11 +730,13 @@ These are the methods that can be called on the Restangular object.
702730
* **getRestangularUrl()**: Gets the URL of the current object.
703731
* **getRequestedUrl()**: Gets the real URL the current object was requested with (incl. GET parameters). Will equal getRestangularUrl() when no parameters were used, before calling `get()`, or when using on a nested child.
704732
* **getParentList()**: Gets the parent list to which it belongs (if any)
705-
* **clone()**: Copies the element
733+
* **clone()**: Copies the element. It's an alias to calling `Restangular.copy(elem)`.
706734
* **plain()**: Returns the plain element received from the server without any of the enhanced methods from Restangular. It's an alias to calling `Restangular.stripRestangular(elem)`
707735
* **withHttpConfig(httpConfig)**: It lets you set a configuration for $http only for the next call. Check the Local Config HTTP section for an example.
708736
* **save**: Calling save will determine whether to do PUT or POST accordingly
709737

738+
**[Back to top](#table-of-contents)**
739+
710740
### Collection methods
711741
* **getList([queryParams, headers]): Gets itself again (Remember this is a collection)**.
712742
* **get([id]): Gets one item from the collection by id**.
@@ -724,9 +754,11 @@ These are the methods that can be called on the Restangular object.
724754
* **several(route, ids*)**: Used for RequestLess connections and URL Building. See section below.
725755
* **oneUrl(route, url)**: This will create a new Restangular object that is just a pointer to one element with the specified URL.
726756
* **allUrl(route, url)**: This creates a Restangular object that is just a pointer to a list at the specified URL.
727-
* **clone()**: Copies the collection
757+
* **clone()**: Copies the collection. It's an alias to calling `Restangular.copy(collection)`.
728758
* **withHttpConfig(httpConfig)**: It lets you set a configuration for $http only for the next call. Check the Local Config HTTP section for an example.
729759

760+
**[Back to top](#table-of-contents)**
761+
730762
### Custom methods
731763
* **customGET(path, [params, headers])**: Does a GET to the specific path. Optionally you can set params and headers.
732764
* **customGETLIST(path, [params, headers])**: Does a GET to the specific path. **In this case, you expect to get an array, not a single element**. Optionally you can set params and headers.
@@ -748,9 +780,13 @@ Restangular.all("accounts").customGET("messages", {param: "param2"})
748780

749781
All custom methods have an alias where you replace `custom` by `do`. For example, `customGET` is equal to `doGET`. Just pick whatever syntax you prefer.
750782

783+
**[Back to top](#table-of-contents)**
784+
751785
## Copying elements
752786
Before modifying an object, we sometimes want to copy it and then modify the copied object. We can't use `angular.copy` for this because it'll not change the `this` binded in the functions we add to the object. In this cases, you must use `Restangular.copy(fromElement)`.
753787

788+
**[Back to top](#table-of-contents)**
789+
754790
## Enhanced promises
755791

756792
Restangular uses enhanced promises when returning. What does this mean? All promises returned now have 2 additional methods and collection promises have 3. These are the methods:
@@ -780,6 +816,8 @@ lengthPromise.then(function(length) {
780816
});
781817
````
782818

819+
**[Back to top](#table-of-contents)**
820+
783821
## Using values directly in templates
784822

785823
Since Angular 1.2, Promise unwrapping in templates has been disabled by default and will be deprecated soon.
@@ -810,6 +848,8 @@ $scope.accounts = Restangular.all('accounts').getList().$object;
810848

811849
The `$object` property is a new property I've added to promises. By default, it'll be an empty array or object. Once the sever has responded with the real value, that object or array is filled with the correct response, therefore making the ng-repeat work :). Pretty neat :D
812850

851+
**[Back to top](#table-of-contents)**
852+
813853
## Using Self reference resources
814854

815855
A lot of REST APIs return the URL to self of the element that you're querying. You can use that with Restangular so that you don't have to create the URLs yourself, but use the ones provided by the server.
@@ -862,6 +902,8 @@ Restangular.all('people').getList().then(function(people) {
862902
})
863903
````
864904

905+
**[Back to top](#table-of-contents)**
906+
865907
## URL Building
866908
Sometimes, we have a lot of nested entities (and their IDs), but we just want the last child. In those cases, doing a request for everything to get the last child is overkill. For those cases, I've added the possibility to create URLs using the same API as creating a new Restangular object. This connections are created without making any requests. Let's see how to do this:
867909

@@ -882,6 +924,8 @@ Restangular.one("accounts", 123).one("buildings", 456).all("spaces").post({name:
882924
Restangular.one("accounts", 123).one("buildings", 456).remove();
883925
````
884926

927+
**[Back to top](#table-of-contents)**
928+
885929
## Using local $http configuration
886930

887931
There're sometimes when you want to set a specific configuration $http configuration just for one Restangular's call. For that, you can use `withHttpConfig`. You must call that method just before doing the HTTP request. Let's learn how to use it with the following example:
@@ -892,6 +936,8 @@ Restangular.one('accounts', 123).withHttpConfig({timeout: 100}).getList('buildin
892936
$scope.account.withHttpConfig({timeout: 100}).put();
893937
````
894938

939+
**[Back to top](#table-of-contents)**
940+
895941
## Creating new Restangular Methods
896942

897943
Let's assume that your API needs some custom methods to work. If that's the case, always calling customGET or customPOST for that method with all parameters is a pain in the ass. That's why every element has a `addRestangularMethod` method.
@@ -930,17 +976,19 @@ RestangularProvider.addElementTransformer('users', true, function(user) {
930976

931977
// If something is set to any of this variables, the default set in the method creation will be overridden
932978
// If nothing is set, then the defaults are sent
933-
Restangular.one('building', 123).evaluate({myParam: 'param'});
979+
Restangular.one('buildings', 123).evaluate({myParam: 'param'});
934980

935981
// GET to /buildings/123/evaluate?myParam=param with headers myHeader: specialHeaderCase
936982

937-
Restangular.one('building', 123).evaluate({myParam: 'param'}, {'myHeader': 'specialHeaderCase'});
983+
Restangular.one('buildings', 123).evaluate({myParam: 'param'}, {'myHeader': 'specialHeaderCase'});
938984

939985
// Here the body of the POST is going to be {key: value} as POST is an unsafe operation
940986
Restangular.all('users').login({key: value});
941987

942988
````
943989

990+
**[Back to top](#table-of-contents)**
991+
944992
## Adding Custom Methods to Collections
945993

946994
Create custom methods for your collection using Restangular.extendCollection(). This is an alias for:
@@ -967,6 +1015,8 @@ Create custom methods for your collection using Restangular.extendCollection().
9671015
});
9681016
```
9691017

1018+
**[Back to top](#table-of-contents)**
1019+
9701020
## Adding Custom Methods to Models
9711021

9721022
Create custom methods for your models using Restangular.extendModel(). This is an alias for:
@@ -975,6 +1025,8 @@ Create custom methods for your models using Restangular.extendModel(). This is a
9751025
Restangular.addElementTransformer(route, false, fn);
9761026
```
9771027

1028+
**[Back to top](#table-of-contents)**
1029+
9781030
### Example:
9791031
```js
9801032
Restangular.extendModel('accounts', function(model) {
@@ -989,6 +1041,8 @@ Create custom methods for your models using Restangular.extendModel(). This is a
9891041
});
9901042
```
9911043

1044+
**[Back to top](#table-of-contents)**
1045+
9921046
# FAQ
9931047

9941048
#### **How can I handle errors?**
@@ -1176,6 +1230,16 @@ RestangularProvider.setResponseExtractor(function(response) {
11761230
return newResponse;
11771231
});
11781232
````
1233+
Alternatively, if you just want the stripped out response on any given call, you can use the .plain() method, doing something like this:
1234+
1235+
````javascript
1236+
1237+
$scope.showData = function () {
1238+
baseUrl.post(someData).then(function(response) {
1239+
console.log(response.plain());
1240+
});
1241+
};
1242+
````
11791243

11801244
**Addendum :** If you want originalElement to be the original response object instead of having an original value for each key in your newResponse array, replace
11811245

@@ -1192,19 +1256,25 @@ By
11921256
newResponse.originalElement[key] = angular.copy(value);
11931257
````
11941258

1259+
#### Restangular fails with status code 0
1260+
1261+
This is typically caused by Cross Origin Request policy. In order to enable cross domain communication and get correct response with appropriate status codes, you must have the CORS headers attached, even in error responses. If the server does not attach the CORS headers to the response then the XHR object won't parse it, thus the XHR object won't have any response body, status or any other response data inside which typically will cause your request to fail with status code 0.
1262+
11951263
#### Why does this depend on Lodash / Underscore?
11961264

11971265
This is a very good question. I could've done the code so that I don't depend on Underscore nor Lodash, but I think both libraries make your life SO much easier. They have all of the "functional" stuff like map, reduce, filter, find, etc.
11981266
With these libraries, you always work with immutable stuff, you get compatibility for browsers which don't implement ECMA5 nor some of these cool methods, and they're actually quicker.
11991267
So, why not use it? If you've never heard of them, by using Restangular, you could start using them. Trust me, you're never going to give them up after this!
12001268

1269+
**[Back to top](#table-of-contents)**
12011270

12021271
# Supported Angular versions
12031272

12041273
Restangular supports all angular versions including 1.0.X, 1.1.X and 1.2.X (1.2.4 being the current at the time)
12051274

12061275
Also, when using Restangular with version >= 1.1.4, in case you're using Restangular inside a callback not handled by Angular, you have to wrap the whole request with `$scope.apply` to make it work or you need to run one extra `$digest` manually. Check out https://github.com/mgonto/restangular/issues/71
12071276

1277+
**[Back to top](#table-of-contents)**
12081278

12091279
# Server Frameworks
12101280

@@ -1213,22 +1283,30 @@ Users reported that this server frameworks play real nice with Restangular, as t
12131283
* Ruby on Rails
12141284
* CakePHP, Laravel and FatFREE, Symfony2 with RestBundle, Silex for PHP
12151285
* Play1 & 2 for Java & scala
1286+
* Dropwizard for Java
12161287
* Restify and Express for NodeJS
12171288
* Tastypie and Django Rest Framework for Django
12181289
* Slim Framework
1290+
* Symfony2 with FOSRestBundle (PHP)
12191291
* Microsoft ASP.NET Web API 2
12201292

1293+
**[Back to top](#table-of-contents)**
1294+
12211295
# Releases Notes
12221296

12231297
New releases notes are together with releases in GitHub at: https://github.com/mgonto/restangular/releases
12241298

12251299
To see old releases notes, [you can click here](https://github.com/mgonto/restangular/blob/master/CHANGELOG.md)
12261300

1301+
**[Back to top](#table-of-contents)**
1302+
12271303
# Contributors
12281304

12291305
* Martin Gontovnikas ([@mgonto](https://twitter.com/mgonto))
12301306
* Paul Dijou ([@paul_dijou](https://twitter.com/paul_dijou))
12311307

1308+
**[Back to top](#table-of-contents)**
1309+
12321310
# License
12331311

12341312
The MIT License
@@ -1244,3 +1322,5 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
12441322

12451323

12461324
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/mgonto/restangular/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
1325+
1326+
**[Back to top](#table-of-contents)**

0 commit comments

Comments
 (0)