backbone-relational-hal-rails 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTg0NWU1NDg4N2RiYTk1MTdmNDU0NjM4YTI2NmE3ODY0NTJiNjMwNA==
5
+ data.tar.gz: !binary |-
6
+ OTQ1Y2Q5MWI4ZTFjYzY1ZGFmNTQyNmYxZDExZGI0Yjc0ZWQzMDliYw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NzMxODExOTg2ZmNhM2VhNjU4NTIzMjU0Njc1ZTI4YWViMjIzMTM1YzgwOWY1
10
+ MTkwNjQxMjg4NWIyMGVmN2ExYTRhNjRjMGU4MWZiNGJlNzM4ZjY3NjI4Y2Iw
11
+ ODVjMTgxM2VjNzhmOTU3NmE4Mzc2Mzk4YjIzMzNmNWZiZGRhM2M=
12
+ data.tar.gz: !binary |-
13
+ ZDU5ZWE5N2ViOTQxZTMyY2U2NDhhZTM2NzEzMjhkYjhlNTdiM2NhZTIxOWRh
14
+ ZDBhNDkzZTYwMjI0MTMwMTMxZWE4NjA0MzI5ODlmZjcyZWM0YjIyNGNlZDg2
15
+ MjllN2M1YzYyYzg3MTUwNGY2MzJhNTQ2YjI0ZTY0ODkxODQyNzg=
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Simon Oulevay (Alpha Hydrae)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # backbone-relational-hal for Ruby on Rails
2
+
3
+ Javascript assets for the latest [backbone-relational-hal](https://github.com/AlphaHydrae/backbone-relational-hal) release.
4
+
5
+ ## Meta
6
+
7
+ * **Author:** Simon Oulevay a.k.a. Alpha Hydrae
8
+ * **License:** MIT (see [LICENSE.txt](https://github.com/AlphaHydrae/backbone-relational-hal-rails/blob/master/LICENSE.txt))
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,6 @@
1
+ module BackboneRelationalHal
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module BackboneRelationalHal
2
+ module Rails
3
+ VERSION = "0.1.1"
4
+ BACKBONE_RELATIONAL_HAL_VERSION = "0.1.1"
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module BackboneRelationalHal
2
+ module Rails
3
+ end
4
+ end
5
+
6
+ Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
@@ -0,0 +1,222 @@
1
+ /*!
2
+ * backbone-relational-hal v0.1.1
3
+ * Copyright (c) 2014 Simon Oulevay
4
+ * Distributed under MIT license
5
+ * https://github.com/AlphaHydrae/backbone-relational-hal
6
+ */
7
+ (function(Backbone, _, UriTemplate, $) {
8
+
9
+ var Collection = Backbone.Collection,
10
+ RelationalModel = Backbone.RelationalModel;
11
+
12
+ var HalLink = RelationalModel.extend({
13
+
14
+ href: function(options) {
15
+ options = _.extend({}, options);
16
+
17
+ var href = this.get('href');
18
+
19
+ if (this.get('templated')) {
20
+ href = new UriTemplate(href);
21
+ href = href.fillFromObject(options.template || {});
22
+ }
23
+
24
+ return href;
25
+ },
26
+
27
+ model: function(options) {
28
+ options = _.extend({}, options);
29
+
30
+ var model = options.model || (options.type ? new options.type() : new (Backbone.RelationalHalResource.extend({}))());
31
+
32
+ return model;
33
+ },
34
+
35
+ fetchResource: function(options) {
36
+ options = _.extend({}, options);
37
+
38
+ var fetchOptions = _.extend({}, options.fetch, { url: this.href(options.href) });
39
+
40
+ return this.model(options).fetch(fetchOptions);
41
+ }
42
+ });
43
+
44
+ var HalLinkCollection = Collection.extend({
45
+ model: HalLink
46
+ });
47
+
48
+ var HalResourceLinks = RelationalModel.extend({
49
+
50
+ parse: function(response) {
51
+ return _.reduce(response, function(memo, data, name) {
52
+ memo[name] = _.isArray(data) ? new HalLinkCollection(data) : new HalLink(data);
53
+ return memo;
54
+ }, {});
55
+ },
56
+
57
+ link: function(rel, options) {
58
+ options = _.extend({}, options);
59
+
60
+ var data = this.get(rel);
61
+ if (!data) {
62
+ return options.all ? new HalLinkCollection() : null;
63
+ } else if (data instanceof HalLinkCollection) {
64
+ return options.all ? data : data.at(0);
65
+ } else {
66
+ return options.all ? new HalLinkCollection([ data ]) : data;
67
+ }
68
+ }
69
+ });
70
+
71
+ var HalModelEmbedded = RelationalModel.extend({
72
+
73
+ embedded: function(rel) {
74
+ return this.get(rel);
75
+ }
76
+ });
77
+
78
+ var HalResource = Backbone.RelationalHalResource = RelationalModel.extend({
79
+
80
+ url: function() {
81
+
82
+ if (this.hasLink('self')) {
83
+ return this.link('self').href();
84
+ } else if (this._cachedHalUrl) {
85
+ return this._cachedHalUrl;
86
+ }
87
+
88
+ var halUrl = _.result(this, 'halUrl');
89
+ if (halUrl) {
90
+ $.when(halUrl).then(_.bind(function(url) {
91
+ this._cachedHalUrl = url;
92
+ }, this));
93
+ }
94
+
95
+ return halUrl || null;
96
+ },
97
+
98
+ link: function(rel) {
99
+ var links = this.get('_links');
100
+ return links ? links.link.apply(links, Array.prototype.slice.call(arguments)) : null;
101
+ },
102
+
103
+ hasLink: function(rel) {
104
+ return this.has('_links') && this.get('_links').has(rel);
105
+ },
106
+
107
+ fetchHalUrl: function(rels) {
108
+ return this._fetchResource(rels.slice(), $.Deferred(), 'url', this);
109
+ },
110
+
111
+ fetchResource: function(rels) {
112
+ return this._fetchResource(rels.slice(), $.Deferred(), 'resource', this);
113
+ },
114
+
115
+ _fetchResource: function(rels, deferred, fetchType, resource, response, options) {
116
+ if (!rels.length) {
117
+ return deferred.resolve(resource, response, options);
118
+ }
119
+
120
+ var relName = rels.shift(),
121
+ rel = _.isObject(relName) ? relName : { name: relName },
122
+ link = resource.link(rel.name);
123
+
124
+ if (fetchType == 'url' && !rels.length) {
125
+ return deferred.resolve(link.href(_.omit(rel, 'name')), resource, response, options);
126
+ }
127
+
128
+ link.fetchResource({
129
+ model: rel.model || (rel.name == 'self' ? this : null),
130
+ type: rel.type,
131
+ fetch: {
132
+ error: _.bind(deferred.reject, deferred),
133
+ success: _.bind(this._fetchResource, this, rels, deferred, fetchType)
134
+ }
135
+ });
136
+
137
+ return deferred;
138
+ },
139
+
140
+ embedded: function(rel) {
141
+ var embedded = this.get('_embedded');
142
+ return embedded ? embedded.embedded.apply(embedded, Array.prototype.slice.call(arguments)) : null;
143
+ },
144
+
145
+ hasEmbedded: function(rel) {
146
+ return this.has('_embedded') && this.get('_embedded').has(rel);
147
+ },
148
+
149
+ hasSameUri: function(other) {
150
+ if (!other) {
151
+ return false;
152
+ }
153
+
154
+ return this.link('self').href() == other.link('self').href();
155
+ },
156
+
157
+ isNew: function() {
158
+ return !this.hasLink('self');
159
+ }
160
+ });
161
+
162
+ var relationalHalResourceExtend = HalResource.extend;
163
+
164
+ HalResource.extend = function(options) {
165
+
166
+ options = _.defaults({}, options, {
167
+ relations: [],
168
+ halEmbedded: []
169
+ });
170
+
171
+ var embedded = HalModelEmbedded.extend({
172
+
173
+ relations: _.map(options.halEmbedded, function(halEmbedded) {
174
+ return _.clone(halEmbedded);
175
+ })
176
+ });
177
+
178
+ options.relations.push({
179
+ type: Backbone.HasOne,
180
+ key: '_links',
181
+ relatedModel: HalResourceLinks,
182
+ includeInJSON: false,
183
+ parse: true
184
+ });
185
+
186
+ options.relations.push({
187
+ type: Backbone.HasOne,
188
+ key: '_embedded',
189
+ relatedModel: embedded,
190
+ includeInJSON: false
191
+ });
192
+
193
+ return relationalHalResourceExtend.call(HalResource, options);
194
+ };
195
+
196
+ Backbone.originalSync = Backbone.sync;
197
+
198
+ Backbone.sync = function(method, model, options) {
199
+ options = _.clone(options) || {};
200
+
201
+ var deferred = $.Deferred(),
202
+ failureHandler = _.bind(deferred.reject, deferred);
203
+
204
+ // WTF: fix for weird backbone behavior.
205
+ // For some reason, when creating a model, backbone resets empty attributes
206
+ // right after starting to sync with the server. Since the actual sync happens
207
+ // later (after the HAL URL has been fetched), we need to make sure the
208
+ // attributes are passed in the options instead.
209
+ if (!options.attrs) {
210
+ options.attrs = model.toJSON(options);
211
+ }
212
+
213
+ var url = options.url || _.result(model, 'url');
214
+ $.when(url).fail(failureHandler).done(function(actualUrl) {
215
+ options.url = actualUrl;
216
+ Backbone.originalSync.call(Backbone, method, model, options).fail(failureHandler).done(_.bind(deferred.resolve, deferred));
217
+ });
218
+
219
+ return deferred;
220
+ };
221
+
222
+ })(Backbone, _, UriTemplate, $);