rightnow_oms 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5 -0
- data/README.md +19 -1
- data/app/assets/javascripts/rightnow_oms/app/app.js.coffee +9 -0
- data/app/assets/javascripts/rightnow_oms/app/controllers/cart.js.coffee +39 -17
- data/app/assets/javascripts/rightnow_oms/app/models/cart.js.coffee +1 -1
- data/app/assets/javascripts/rightnow_oms/app/models/cart_item.js.coffee +3 -0
- data/app/assets/javascripts/rightnow_oms/vendor/{ember.js → ember-0.9.5.js} +83 -26
- data/app/assets/javascripts/rightnow_oms/vendor/ember-data.js +239 -643
- data/app/assets/javascripts/rightnow_oms/vendor/ember-data.min.js +1 -1
- data/app/assets/javascripts/rightnow_oms/vendor/ember.min.js +5 -5
- data/app/assets/stylesheets/rightnow_oms/carts.css.scss +1 -0
- data/app/models/rightnow_oms/cart.rb +1 -0
- data/lib/rightnow_oms/version.rb +1 -1
- metadata +21 -21
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -51,7 +51,7 @@ Create the migrations with:
|
|
51
51
|
Run `bundle install` and require ember and ember-data in your `app/assets/javascripts/application.js`:
|
52
52
|
|
53
53
|
```
|
54
|
-
= require rightnow_oms/vendor/ember
|
54
|
+
= require rightnow_oms/vendor/ember-0.9.5
|
55
55
|
= require rightnow_oms/vendor/ember-data
|
56
56
|
```
|
57
57
|
|
@@ -150,6 +150,24 @@ You can add cartables to the cart by:
|
|
150
150
|
})
|
151
151
|
```
|
152
152
|
|
153
|
+
### Strategy to sync data with remote
|
154
|
+
|
155
|
+
By default, RightnowOms sync the data immediately when you change the
|
156
|
+
data objects in the store. But by setting `autoCommit` to `false`, you
|
157
|
+
can change the default behavior.
|
158
|
+
|
159
|
+
```javascript
|
160
|
+
RightnowOms.config.set('autoCommit', false)
|
161
|
+
```
|
162
|
+
|
163
|
+
If you turn off auto-commit, you need to sync the data explicitly. When
|
164
|
+
you have created, updated and deleted any data object in the client
|
165
|
+
side, you ought to commit these changes by yourself.
|
166
|
+
|
167
|
+
```javascript
|
168
|
+
RightnowOms.commit(true)
|
169
|
+
```
|
170
|
+
|
153
171
|
Now you have all things done. Wish you have a good day.
|
154
172
|
|
155
173
|
## Development
|
@@ -1,5 +1,13 @@
|
|
1
1
|
window.RightnowOms = Ember.Application.create
|
2
2
|
rootElement: '#rightnow-oms'
|
3
|
+
commit: (force = false)->
|
4
|
+
clearTimeout(@_commitTimer) if @_commitTimer
|
5
|
+
|
6
|
+
@_commitTimer = setTimeout((->
|
7
|
+
window.RightnowOms.store.commit() if window.RightnowOms.config.get('autoCommit') || force
|
8
|
+
), 500)
|
9
|
+
|
10
|
+
_commitTimer: null
|
3
11
|
|
4
12
|
window.RightnowOms.store = DS.Store.create
|
5
13
|
adapter:
|
@@ -8,3 +16,4 @@ window.RightnowOms.store = DS.Store.create
|
|
8
16
|
namespace: 'rightnow_oms'
|
9
17
|
|
10
18
|
window.RightnowOms.config = Em.Object.create()
|
19
|
+
window.RightnowOms.config.set('autoCommit', true)
|
@@ -9,19 +9,29 @@ RightnowOms.cartController = Ember.Object.create
|
|
9
9
|
@set('content', RightnowOms.store.find(RightnowOms.Cart, @get('content').get('id')))
|
10
10
|
|
11
11
|
# item: a hash
|
12
|
-
addCartItem: (item
|
12
|
+
addCartItem: (item) ->
|
13
13
|
cartItem = @get('content').addCartItem(item)
|
14
|
-
|
14
|
+
RightnowOms.commit()
|
15
15
|
|
16
|
-
return
|
17
|
-
|
18
|
-
return callback.call(@, cartItem) if cartItem.get('id')
|
16
|
+
return if !(item.children && item.children.length > 0)
|
19
17
|
|
20
18
|
self = @
|
21
|
-
|
19
|
+
|
20
|
+
addChildren = (parent, children) ->
|
21
|
+
children.forEach((c) ->
|
22
|
+
c.parent_id = parent.get('id')
|
23
|
+
self.addCartItem(c)
|
24
|
+
)
|
25
|
+
|
26
|
+
return addChildren(cartItem, item.children) if cartItem.get('id')?
|
27
|
+
|
28
|
+
afterCartItemCreated = ->
|
22
29
|
if (!cartItem.get('isDirty')) && (!cartItem.get('isDeleted'))
|
23
|
-
|
24
|
-
|
30
|
+
addChildren(cartItem, item.children)
|
31
|
+
cartItem.removeObserver('isDirty', afterCartItemCreated)
|
32
|
+
RightnowOms.commit(true) unless RightnowOms.config.get('autoCommit')
|
33
|
+
|
34
|
+
cartItem.addObserver('isDirty', afterCartItemCreated)
|
25
35
|
|
26
36
|
# @id: id of the cart item to be updated
|
27
37
|
# @properties: a hash which is the new properties of the cart item.
|
@@ -33,19 +43,31 @@ RightnowOms.cartController = Ember.Object.create
|
|
33
43
|
# 'quantity': 2
|
34
44
|
# })
|
35
45
|
updateCartItem: (id, properties) ->
|
46
|
+
if RightnowOms.CartItem.findById(id).isProcessing()
|
47
|
+
alert('正在保存购物车,请稍后。。。')
|
48
|
+
return
|
49
|
+
|
36
50
|
@get('content').updateCartItem(id, properties)
|
37
|
-
|
51
|
+
RightnowOms.commit()
|
38
52
|
|
39
53
|
increaseCartItem: (id) ->
|
40
|
-
|
41
|
-
|
54
|
+
if RightnowOms.CartItem.findById(id).isProcessing()
|
55
|
+
alert('正在保存购物车,请稍后。。。')
|
56
|
+
return
|
57
|
+
|
58
|
+
cartItem = @get('content').increaseCartItem(id)
|
59
|
+
RightnowOms.commit(true)
|
42
60
|
|
43
61
|
decreaseCartItem: (id) ->
|
44
62
|
cartItem = RightnowOms.CartItem.findById(id)
|
45
63
|
|
64
|
+
if cartItem.isProcessing()
|
65
|
+
alert('正在保存购物车,请稍后。。。')
|
66
|
+
return
|
67
|
+
|
46
68
|
if cartItem.get('isDecreasable')
|
47
69
|
@get('content').decreaseCartItem(id)
|
48
|
-
|
70
|
+
RightnowOms.commit(true)
|
49
71
|
else
|
50
72
|
@removeCartItem(id)
|
51
73
|
|
@@ -55,12 +77,12 @@ RightnowOms.cartController = Ember.Object.create
|
|
55
77
|
|
56
78
|
if remove
|
57
79
|
@get('content').removeCartItem(id)
|
58
|
-
|
80
|
+
RightnowOms.commit(true)
|
59
81
|
|
60
82
|
cleanUp: ->
|
61
83
|
if confirm('您确定要清空您的购物车吗?')
|
62
84
|
@get('content').cleanUp()
|
63
|
-
|
85
|
+
RightnowOms.commit(true)
|
64
86
|
|
65
87
|
# return: an array of cart items.
|
66
88
|
#
|
@@ -70,15 +92,15 @@ RightnowOms.cartController = Ember.Object.create
|
|
70
92
|
#
|
71
93
|
# =>
|
72
94
|
# [{
|
73
|
-
# 'id': 1, 'cartable_id': 2, 'cartable_type': 'Product', 'name': 'product-1', 'original_price', 10.0, 'price': 10.0, 'group': 'booking', 'parent_id': null
|
95
|
+
# 'id': 1, 'cartable_id': 2, 'cartable_type': 'Product', 'name': 'product-1', 'original_price', 10.0, 'base_quantity': 1, 'price': 10.0, 'group': 'booking', 'parent_id': null
|
74
96
|
# }, {
|
75
|
-
# 'id': 2, 'cartable_id': 3, 'cartable_type': 'Product', 'name': 'product-2', 'original_price', 20.0, 'price': 20.0, 'group': 'booking', 'parent_id': 2
|
97
|
+
# 'id': 2, 'cartable_id': 3, 'cartable_type': 'Product', 'name': 'product-2', 'original_price', 20.0, 'base_quantity': 1, 'price': 20.0, 'group': 'booking', 'parent_id': 2
|
76
98
|
# }]
|
77
99
|
findCartItemsByGroup: (group) ->
|
78
100
|
found = []
|
79
101
|
cartItems = @get('content').findCartItemsByGroup(group)
|
80
102
|
|
81
103
|
cartItems.forEach (item) ->
|
82
|
-
found.push(item.getProperties('id', 'cartable_id', 'cartable_type', 'name', 'original_price', 'price', 'quantity', 'group', 'parent_id'))
|
104
|
+
found.push(item.getProperties('id', 'cartable_id', 'cartable_type', 'name', 'original_price', 'base_quantity', 'price', 'quantity', 'group', 'parent_id'))
|
83
105
|
|
84
106
|
found
|
@@ -17,7 +17,7 @@ RightnowOms.Cart = DS.Model.extend
|
|
17
17
|
total += item.get('price') * item.get('quantity') unless item.get('hasParent')
|
18
18
|
|
19
19
|
round(total, 2)
|
20
|
-
).property("cartItems.@each.quantity")
|
20
|
+
).property("cartItems.@each.quantity", "cartItems.@each.price")
|
21
21
|
|
22
22
|
addCartItem: (item) ->
|
23
23
|
return @createCartItem(item) if item.mergable == false
|
@@ -1735,7 +1735,7 @@ if ('undefined' === typeof Ember) {
|
|
1735
1735
|
/**
|
1736
1736
|
@namespace
|
1737
1737
|
@name Ember
|
1738
|
-
@version 0.9.
|
1738
|
+
@version 0.9.5
|
1739
1739
|
|
1740
1740
|
All Ember methods and functions are defined inside of this namespace.
|
1741
1741
|
You generally should not add new properties to this namespace as it may be
|
@@ -1767,10 +1767,10 @@ if ('undefined' !== typeof window) {
|
|
1767
1767
|
/**
|
1768
1768
|
@static
|
1769
1769
|
@type String
|
1770
|
-
@default '0.9.
|
1770
|
+
@default '0.9.5'
|
1771
1771
|
@constant
|
1772
1772
|
*/
|
1773
|
-
Ember.VERSION = '0.9.
|
1773
|
+
Ember.VERSION = '0.9.5';
|
1774
1774
|
|
1775
1775
|
/**
|
1776
1776
|
@static
|
@@ -6299,6 +6299,8 @@ function findNamespaces() {
|
|
6299
6299
|
// get(window.globalStorage, 'isNamespace') would try to read the storage for domain isNamespace and cause exception in Firefox.
|
6300
6300
|
// globalStorage is a storage obsoleted by the WhatWG storage specification. See https://developer.mozilla.org/en/DOM/Storage#globalStorage
|
6301
6301
|
if (prop === "globalStorage" && window.StorageList && window.globalStorage instanceof window.StorageList) { continue; }
|
6302
|
+
// Don't access properties on parent window, which will throw "Access/Permission Denied" in IE/Firefox for windows on different domains
|
6303
|
+
if (prop === "parent" || prop === "top" || prop === "frameElement" || prop === "content") { continue; }
|
6302
6304
|
// Unfortunately, some versions of IE don't support window.hasOwnProperty
|
6303
6305
|
if (window.hasOwnProperty && !window.hasOwnProperty(prop)) { continue; }
|
6304
6306
|
|
@@ -11295,6 +11297,18 @@ Ember.View = Ember.Object.extend(
|
|
11295
11297
|
*/
|
11296
11298
|
templateName: null,
|
11297
11299
|
|
11300
|
+
/**
|
11301
|
+
The name of the layout to lookup if no layout is provided.
|
11302
|
+
|
11303
|
+
Ember.View will look for a template with this name in this view's
|
11304
|
+
`templates` object. By default, this will be a global object
|
11305
|
+
shared in `Ember.TEMPLATES`.
|
11306
|
+
|
11307
|
+
@type String
|
11308
|
+
@default null
|
11309
|
+
*/
|
11310
|
+
layoutName: null,
|
11311
|
+
|
11298
11312
|
/**
|
11299
11313
|
The hash in which to look for `templateName`.
|
11300
11314
|
|
@@ -11317,25 +11331,46 @@ Ember.View = Ember.Object.extend(
|
|
11317
11331
|
template: Ember.computed(function(key, value) {
|
11318
11332
|
if (value !== undefined) { return value; }
|
11319
11333
|
|
11320
|
-
var templateName = get(this, 'templateName'),
|
11334
|
+
var templateName = get(this, 'templateName'),
|
11335
|
+
template = this.templateForName(templateName, 'template');
|
11321
11336
|
|
11322
|
-
|
11337
|
+
return template || get(this, 'defaultTemplate');
|
11338
|
+
}).property('templateName').cacheable(),
|
11323
11339
|
|
11324
|
-
|
11325
|
-
|
11326
|
-
|
11327
|
-
|
11328
|
-
|
11329
|
-
}
|
11340
|
+
/**
|
11341
|
+
A view may contain a layout. A layout is a regular template but
|
11342
|
+
supercedes the `template` property during rendering. It is the
|
11343
|
+
responsibility of the layout template to retrieve the `template`
|
11344
|
+
property from the view and render it in the correct location.
|
11330
11345
|
|
11331
|
-
|
11332
|
-
|
11333
|
-
|
11346
|
+
This is useful for a view that has a shared wrapper, but which delegates
|
11347
|
+
the rendering of the contents of the wrapper to the `template` property
|
11348
|
+
on a subclass.
|
11349
|
+
|
11350
|
+
@field
|
11351
|
+
@type Function
|
11352
|
+
*/
|
11353
|
+
layout: Ember.computed(function(key, value) {
|
11354
|
+
if (arguments.length === 2) { return value; }
|
11355
|
+
|
11356
|
+
var layoutName = get(this, 'layoutName'),
|
11357
|
+
layout = this.templateForName(layoutName, 'layout');
|
11358
|
+
|
11359
|
+
return layout || get(this, 'defaultLayout');
|
11360
|
+
}).property('layoutName').cacheable(),
|
11361
|
+
|
11362
|
+
templateForName: function(name, type) {
|
11363
|
+
if (!name) { return; }
|
11364
|
+
|
11365
|
+
var templates = get(this, 'templates'),
|
11366
|
+
template = get(templates, name);
|
11367
|
+
|
11368
|
+
if (!template) {
|
11369
|
+
throw new Ember.Error(fmt('%@ - Unable to find %@ "%@".', [this, type, name]));
|
11334
11370
|
}
|
11335
11371
|
|
11336
|
-
|
11337
|
-
|
11338
|
-
}).property('templateName').cacheable(),
|
11372
|
+
return template;
|
11373
|
+
},
|
11339
11374
|
|
11340
11375
|
/**
|
11341
11376
|
The object from which templates should access properties.
|
@@ -11499,7 +11534,10 @@ Ember.View = Ember.Object.extend(
|
|
11499
11534
|
@param {Ember.RenderBuffer} buffer The render buffer
|
11500
11535
|
*/
|
11501
11536
|
render: function(buffer) {
|
11502
|
-
|
11537
|
+
// If this view has a layout, it is the responsibility of the
|
11538
|
+
// the layout to render the view's template. Otherwise, render the template
|
11539
|
+
// directly.
|
11540
|
+
var template = get(this, 'layout') || get(this, 'template');
|
11503
11541
|
|
11504
11542
|
if (template) {
|
11505
11543
|
var context = get(this, 'templateContext'),
|
@@ -13412,8 +13450,6 @@ Ember.State = Ember.Object.extend({
|
|
13412
13450
|
|
13413
13451
|
(function(exports) {
|
13414
13452
|
var get = Ember.get, set = Ember.set, getPath = Ember.getPath, fmt = Ember.String.fmt;
|
13415
|
-
Ember.LOG_STATE_TRANSITIONS = false;
|
13416
|
-
|
13417
13453
|
/**
|
13418
13454
|
@class
|
13419
13455
|
*/
|
@@ -13478,19 +13514,19 @@ Ember.StateManager = Ember.State.extend(
|
|
13478
13514
|
},
|
13479
13515
|
|
13480
13516
|
sendRecursively: function(event, currentState, context) {
|
13481
|
-
var log =
|
13517
|
+
var log = this.enableLogging;
|
13482
13518
|
|
13483
13519
|
var action = currentState[event];
|
13484
13520
|
|
13485
13521
|
if (action) {
|
13486
|
-
if (log) { console.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, currentState
|
13522
|
+
if (log) { console.log(fmt("STATEMANAGER: Sending event '%@' to state %@.", [event, get(currentState, 'path')])); }
|
13487
13523
|
action.call(currentState, this, context);
|
13488
13524
|
} else {
|
13489
13525
|
var parentState = get(currentState, 'parentState');
|
13490
13526
|
if (parentState) {
|
13491
13527
|
this.sendRecursively(event, parentState, context);
|
13492
13528
|
} else if (get(this, 'errorOnUnhandledEvent')) {
|
13493
|
-
throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + getPath(this, 'currentState.
|
13529
|
+
throw new Ember.Error(this.toString() + " could not respond to event " + event + " in state " + getPath(this, 'currentState.path') + ".");
|
13494
13530
|
}
|
13495
13531
|
}
|
13496
13532
|
},
|
@@ -13598,7 +13634,7 @@ Ember.StateManager = Ember.State.extend(
|
|
13598
13634
|
},
|
13599
13635
|
|
13600
13636
|
enterState: function(exitStates, enterStates, state) {
|
13601
|
-
var log =
|
13637
|
+
var log = this.enableLogging;
|
13602
13638
|
|
13603
13639
|
var stateManager = this;
|
13604
13640
|
|
@@ -13607,7 +13643,7 @@ Ember.StateManager = Ember.State.extend(
|
|
13607
13643
|
state.exit(stateManager, transition);
|
13608
13644
|
}, function() {
|
13609
13645
|
this.asyncEach(enterStates, function(state, transition) {
|
13610
|
-
if (log) { console.log("STATEMANAGER: Entering " + state
|
13646
|
+
if (log) { console.log("STATEMANAGER: Entering " + get(state, 'path')); }
|
13611
13647
|
state.enter(stateManager, transition);
|
13612
13648
|
}, function() {
|
13613
13649
|
var startState = state, enteredState, initialState;
|
@@ -13622,7 +13658,7 @@ Ember.StateManager = Ember.State.extend(
|
|
13622
13658
|
while (startState = get(get(startState, 'states'), initialState)) {
|
13623
13659
|
enteredState = startState;
|
13624
13660
|
|
13625
|
-
if (log) { console.log("STATEMANAGER: Entering " + startState
|
13661
|
+
if (log) { console.log("STATEMANAGER: Entering " + get(startState, 'path')); }
|
13626
13662
|
startState.enter(stateManager);
|
13627
13663
|
|
13628
13664
|
initialState = get(startState, 'initialState');
|
@@ -15739,6 +15775,27 @@ EmberHandlebars.registerHelper('action', function(actionName, options) {
|
|
15739
15775
|
})({});
|
15740
15776
|
|
15741
15777
|
|
15778
|
+
(function(exports) {
|
15779
|
+
var get = Ember.get, set = Ember.set;
|
15780
|
+
|
15781
|
+
Ember.Handlebars.registerHelper('yield', function(options) {
|
15782
|
+
var view = options.data.view, template;
|
15783
|
+
|
15784
|
+
while (view && !get(view, 'layout')) {
|
15785
|
+
view = get(view, 'parentView');
|
15786
|
+
}
|
15787
|
+
|
15788
|
+
ember_assert("You called yield in a template that was not a layout", !!view);
|
15789
|
+
|
15790
|
+
template = get(view, 'template');
|
15791
|
+
|
15792
|
+
ember_assert("You called yield on " + view.toString() + " without supplying a template", !!template);
|
15793
|
+
template(this, options);
|
15794
|
+
});
|
15795
|
+
|
15796
|
+
})({});
|
15797
|
+
|
15798
|
+
|
15742
15799
|
(function(exports) {
|
15743
15800
|
// ==========================================================================
|
15744
15801
|
// Project: Ember Handlebar Views
|
@@ -71,7 +71,7 @@ DS.fixtureAdapter = DS.Adapter.create({
|
|
71
71
|
|
72
72
|
ember_assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
|
73
73
|
|
74
|
-
var ids = fixtures.map(function(item, index, self){ return item.id
|
74
|
+
var ids = fixtures.map(function(item, index, self){ return item.id });
|
75
75
|
store.loadMany(type, ids, fixtures);
|
76
76
|
}
|
77
77
|
|
@@ -81,7 +81,6 @@ DS.fixtureAdapter = DS.Adapter.create({
|
|
81
81
|
|
82
82
|
|
83
83
|
(function(exports) {
|
84
|
-
/*global jQuery*/
|
85
84
|
var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
|
86
85
|
|
87
86
|
DS.RESTAdapter = DS.Adapter.extend({
|
@@ -121,7 +120,8 @@ DS.RESTAdapter = DS.Adapter.extend({
|
|
121
120
|
},
|
122
121
|
|
123
122
|
updateRecord: function(store, type, model) {
|
124
|
-
var
|
123
|
+
var primaryKey = getPath(type, 'proto.primaryKey'),
|
124
|
+
id = get(model, primaryKey);
|
125
125
|
var root = this.rootForType(type);
|
126
126
|
|
127
127
|
var data = {};
|
@@ -159,7 +159,8 @@ DS.RESTAdapter = DS.Adapter.extend({
|
|
159
159
|
},
|
160
160
|
|
161
161
|
deleteRecord: function(store, type, model) {
|
162
|
-
var
|
162
|
+
var primaryKey = getPath(type, 'proto.primaryKey'),
|
163
|
+
id = get(model, primaryKey);
|
163
164
|
var root = this.rootForType(type);
|
164
165
|
|
165
166
|
var url = ["", this.pluralize(root), id].join("/");
|
@@ -177,11 +178,12 @@ DS.RESTAdapter = DS.Adapter.extend({
|
|
177
178
|
}
|
178
179
|
|
179
180
|
var root = this.rootForType(type),
|
180
|
-
plural = this.pluralize(root)
|
181
|
+
plural = this.pluralize(root),
|
182
|
+
primaryKey = getPath(type, 'proto.primaryKey');
|
181
183
|
|
182
184
|
var data = {};
|
183
185
|
data[plural] = models.map(function(model) {
|
184
|
-
return get(model,
|
186
|
+
return get(model, primaryKey);
|
185
187
|
});
|
186
188
|
|
187
189
|
this.ajax("/" + this.pluralize(root) + "/delete", "POST", {
|
@@ -213,6 +215,7 @@ DS.RESTAdapter = DS.Adapter.extend({
|
|
213
215
|
store.loadMany(type, ids, json[plural]);
|
214
216
|
}
|
215
217
|
});
|
218
|
+
var url = "/" + plural;
|
216
219
|
},
|
217
220
|
|
218
221
|
findAll: function(store, type) {
|
@@ -271,58 +274,19 @@ DS.RESTAdapter = DS.Adapter.extend({
|
|
271
274
|
(function(exports) {
|
272
275
|
var get = Ember.get, set = Ember.set;
|
273
276
|
|
274
|
-
/**
|
275
|
-
A model array is an array that contains records of a certain type. The model
|
276
|
-
array materializes records as needed when they are retrieved for the first
|
277
|
-
time. You should not create model arrays yourself. Instead, an instance of
|
278
|
-
DS.ModelArray or its subclasses will be returned by your application's store
|
279
|
-
in response to queries.
|
280
|
-
*/
|
281
|
-
|
282
277
|
DS.ModelArray = Ember.ArrayProxy.extend({
|
283
|
-
|
284
|
-
/**
|
285
|
-
The model type contained by this model array.
|
286
|
-
|
287
|
-
@type DS.Model
|
288
|
-
*/
|
289
278
|
type: null,
|
290
|
-
|
291
|
-
// The array of client ids backing the model array. When a
|
292
|
-
// record is requested from the model array, the record
|
293
|
-
// for the client id at the same index is materialized, if
|
294
|
-
// necessary, by the store.
|
295
279
|
content: null,
|
296
|
-
|
297
|
-
// The store that created this model array.
|
298
280
|
store: null,
|
299
281
|
|
300
|
-
// for associations, the model that this association belongs to.
|
301
|
-
parentModel: null,
|
302
|
-
|
303
282
|
init: function() {
|
304
283
|
set(this, 'modelCache', Ember.A([]));
|
305
284
|
this._super();
|
306
285
|
},
|
307
286
|
|
308
|
-
// Overrides Ember.Array's replace method to implement
|
309
|
-
replace: function(index, removed, added) {
|
310
|
-
var parentRecord = get(this, 'parentRecord');
|
311
|
-
var pendingParent = parentRecord && !get(parentRecord, 'id');
|
312
|
-
|
313
|
-
added = added.map(function(item) {
|
314
|
-
ember_assert("You can only add items of " + (get(this, 'type') && get(this, 'type').toString()) + " to this association.", !get(this, 'type') || (get(this, 'type') === item.constructor));
|
315
|
-
|
316
|
-
if (pendingParent) { item.send('waitingOn', parentRecord); }
|
317
|
-
return item.get('clientId');
|
318
|
-
});
|
319
|
-
|
320
|
-
this._super(index, removed, added);
|
321
|
-
},
|
322
|
-
|
323
287
|
arrayDidChange: function(array, index, removed, added) {
|
324
288
|
var modelCache = get(this, 'modelCache');
|
325
|
-
modelCache.replace(index, 0,
|
289
|
+
modelCache.replace(index, 0, Array(added));
|
326
290
|
|
327
291
|
this._super(array, index, removed, added);
|
328
292
|
},
|
@@ -354,12 +318,6 @@ DS.ModelArray = Ember.ArrayProxy.extend({
|
|
354
318
|
}
|
355
319
|
});
|
356
320
|
|
357
|
-
})({});
|
358
|
-
|
359
|
-
|
360
|
-
(function(exports) {
|
361
|
-
var get = Ember.get;
|
362
|
-
|
363
321
|
DS.FilteredModelArray = DS.ModelArray.extend({
|
364
322
|
filterFunction: null,
|
365
323
|
|
@@ -369,12 +327,6 @@ DS.FilteredModelArray = DS.ModelArray.extend({
|
|
369
327
|
}, 'filterFunction')
|
370
328
|
});
|
371
329
|
|
372
|
-
})({});
|
373
|
-
|
374
|
-
|
375
|
-
(function(exports) {
|
376
|
-
var get = Ember.get, set = Ember.set;
|
377
|
-
|
378
330
|
DS.AdapterPopulatedModelArray = DS.ModelArray.extend({
|
379
331
|
query: null,
|
380
332
|
isLoaded: false,
|
@@ -391,11 +343,6 @@ DS.AdapterPopulatedModelArray = DS.ModelArray.extend({
|
|
391
343
|
}
|
392
344
|
});
|
393
345
|
|
394
|
-
|
395
|
-
})({});
|
396
|
-
|
397
|
-
|
398
|
-
(function(exports) {
|
399
346
|
})({});
|
400
347
|
|
401
348
|
|
@@ -437,8 +384,7 @@ var OrderedSet = Ember.Object.extend({
|
|
437
384
|
},
|
438
385
|
|
439
386
|
forEach: function(fn, self) {
|
440
|
-
|
441
|
-
get(this, 'list').slice().forEach(function(item) {
|
387
|
+
get(this, 'list').forEach(function(item) {
|
442
388
|
fn.call(self, item);
|
443
389
|
});
|
444
390
|
},
|
@@ -501,8 +447,7 @@ var Hash = Ember.Object.extend({
|
|
501
447
|
},
|
502
448
|
|
503
449
|
forEach: function(fn, binding) {
|
504
|
-
var keys = get(this, 'keys'),
|
505
|
-
values = get(this, 'values');
|
450
|
+
var keys = get(this, 'keys'), values = get(this, 'values');
|
506
451
|
|
507
452
|
keys.forEach(function(key) {
|
508
453
|
var guid = Ember.guidFor(key);
|
@@ -562,17 +507,8 @@ DS.Transaction = Ember.Object.extend({
|
|
562
507
|
dirty.forEach(function(type, models) {
|
563
508
|
if (models.isEmpty()) { return; }
|
564
509
|
|
565
|
-
|
566
|
-
|
567
|
-
models.forEach(function(model) {
|
568
|
-
model.send('willCommit');
|
569
|
-
|
570
|
-
if (get(model, 'isPending') === false) {
|
571
|
-
array.push(model);
|
572
|
-
}
|
573
|
-
});
|
574
|
-
|
575
|
-
fn.call(binding, type, array);
|
510
|
+
models.forEach(function(model) { model.willCommit(); });
|
511
|
+
fn.call(binding, type, models.toArray());
|
576
512
|
});
|
577
513
|
};
|
578
514
|
|
@@ -744,27 +680,28 @@ DS.Store = Ember.Object.extend({
|
|
744
680
|
// . CREATE NEW MODEL .
|
745
681
|
// ....................
|
746
682
|
|
747
|
-
createRecord: function(type,
|
748
|
-
|
683
|
+
createRecord: function(type, hash, transaction) {
|
684
|
+
hash = hash || {};
|
749
685
|
|
750
|
-
var id =
|
686
|
+
var id = hash[getPath(type, 'proto.primaryKey')] || null;
|
751
687
|
|
752
|
-
var model = type.
|
688
|
+
var model = type.create({
|
689
|
+
data: hash || {},
|
753
690
|
store: this,
|
754
691
|
transaction: transaction
|
755
692
|
});
|
756
693
|
|
757
|
-
|
758
|
-
|
759
|
-
clientId = this.pushHash(hash, id, type);
|
760
|
-
model.send('setData', hash);
|
694
|
+
model.adapterDidCreate();
|
761
695
|
|
696
|
+
var data = this.clientIdToHashMap(type);
|
762
697
|
var models = get(this, 'models');
|
763
698
|
|
699
|
+
var clientId = this.pushHash(hash, id, type);
|
700
|
+
|
764
701
|
set(model, 'clientId', clientId);
|
702
|
+
|
765
703
|
models[clientId] = model;
|
766
704
|
|
767
|
-
model.setProperties(properties);
|
768
705
|
this.updateModelArrays(type, clientId, hash);
|
769
706
|
|
770
707
|
return model;
|
@@ -775,7 +712,7 @@ DS.Store = Ember.Object.extend({
|
|
775
712
|
// ................
|
776
713
|
|
777
714
|
deleteRecord: function(model) {
|
778
|
-
model.
|
715
|
+
model.deleteRecord();
|
779
716
|
},
|
780
717
|
|
781
718
|
// ...............
|
@@ -802,7 +739,7 @@ DS.Store = Ember.Object.extend({
|
|
802
739
|
*/
|
803
740
|
find: function(type, id, query) {
|
804
741
|
if (id === undefined) {
|
805
|
-
return this.
|
742
|
+
return this.findMany(type, null, null);
|
806
743
|
}
|
807
744
|
|
808
745
|
if (query !== undefined) {
|
@@ -837,22 +774,22 @@ DS.Store = Ember.Object.extend({
|
|
837
774
|
if (!model) {
|
838
775
|
// create a new instance of the model in the
|
839
776
|
// 'isLoading' state
|
840
|
-
model = this.
|
777
|
+
model = this.createModel(type, clientId);
|
841
778
|
|
842
779
|
// immediately set its data
|
843
|
-
model.
|
780
|
+
model.setData(data[clientId] || null);
|
844
781
|
}
|
845
782
|
} else {
|
846
783
|
clientId = this.pushHash(null, id, type);
|
847
784
|
|
848
785
|
// create a new instance of the model in the
|
849
786
|
// 'isLoading' state
|
850
|
-
model = this.
|
787
|
+
model = this.createModel(type, clientId);
|
851
788
|
|
852
789
|
// let the adapter set the data, possibly async
|
853
790
|
var adapter = get(this, '_adapter');
|
854
791
|
if (adapter && adapter.find) { adapter.find(this, type, id); }
|
855
|
-
else { throw fmt("Adapter is either null or
|
792
|
+
else { throw fmt("Adapter is either null or do not implement `find` method", this); }
|
856
793
|
}
|
857
794
|
|
858
795
|
return model;
|
@@ -885,7 +822,7 @@ DS.Store = Ember.Object.extend({
|
|
885
822
|
if ((needed && get(needed, 'length') > 0) || query) {
|
886
823
|
var adapter = get(this, '_adapter');
|
887
824
|
if (adapter && adapter.findMany) { adapter.findMany(this, type, needed, query); }
|
888
|
-
else { throw fmt("Adapter is either null or
|
825
|
+
else { throw fmt("Adapter is either null or do not implement `findMany` method", this); }
|
889
826
|
}
|
890
827
|
|
891
828
|
return this.createModelArray(type, clientIds);
|
@@ -895,7 +832,7 @@ DS.Store = Ember.Object.extend({
|
|
895
832
|
var array = DS.AdapterPopulatedModelArray.create({ type: type, content: Ember.A([]), store: this });
|
896
833
|
var adapter = get(this, '_adapter');
|
897
834
|
if (adapter && adapter.findQuery) { adapter.findQuery(this, type, query, array); }
|
898
|
-
else { throw fmt("Adapter is either null or
|
835
|
+
else { throw fmt("Adapter is either null or do not implement `findQuery` method", this); }
|
899
836
|
return array;
|
900
837
|
},
|
901
838
|
|
@@ -961,20 +898,20 @@ DS.Store = Ember.Object.extend({
|
|
961
898
|
var data = this.clientIdToHashMap(model.constructor);
|
962
899
|
|
963
900
|
data[clientId] = hash;
|
964
|
-
model.
|
901
|
+
model.set('data', hash);
|
965
902
|
}
|
966
903
|
|
967
|
-
model.
|
904
|
+
model.adapterDidUpdate();
|
968
905
|
},
|
969
906
|
|
970
907
|
didDeleteRecords: function(array) {
|
971
908
|
array.forEach(function(model) {
|
972
|
-
model.
|
909
|
+
model.adapterDidDelete();
|
973
910
|
});
|
974
911
|
},
|
975
912
|
|
976
913
|
didDeleteRecord: function(model) {
|
977
|
-
model.
|
914
|
+
model.adapterDidDelete();
|
978
915
|
},
|
979
916
|
|
980
917
|
didCreateRecords: function(type, array, hashes) {
|
@@ -990,55 +927,38 @@ DS.Store = Ember.Object.extend({
|
|
990
927
|
clientId = get(model, 'clientId');
|
991
928
|
|
992
929
|
data[clientId] = hash;
|
993
|
-
model
|
930
|
+
set(model, 'data', hash);
|
994
931
|
|
995
932
|
idToClientIdMap[id] = clientId;
|
996
933
|
idList.push(id);
|
997
934
|
|
998
|
-
model.
|
935
|
+
model.adapterDidUpdate();
|
999
936
|
}
|
1000
937
|
},
|
1001
938
|
|
1002
939
|
didCreateRecord: function(model, hash) {
|
1003
940
|
var type = model.constructor;
|
1004
941
|
|
1005
|
-
var id, clientId, primaryKey;
|
942
|
+
var id, clientId, primaryKey = getPath(type, 'proto.primaryKey');
|
1006
943
|
|
1007
944
|
var idToClientIdMap = this.idToClientIdMap(type);
|
1008
945
|
var data = this.clientIdToHashMap(type);
|
1009
946
|
var idList = this.idList(type);
|
1010
947
|
|
1011
|
-
|
1012
|
-
// provided a primary key.
|
1013
|
-
|
1014
|
-
primaryKey = getPath(type, 'proto.primaryKey');
|
1015
|
-
|
1016
|
-
// TODO: Make ember_assert more flexible and convert this into an ember_assert
|
1017
|
-
if (hash) {
|
1018
|
-
ember_assert("The server must provide a primary key: " + primaryKey, get(hash, primaryKey));
|
1019
|
-
} else {
|
1020
|
-
ember_assert("The server did not return data, and you did not create a primary key (" + primaryKey + ") on the client", get(get(model, 'data'), primaryKey));
|
1021
|
-
}
|
1022
|
-
|
1023
|
-
// If a hash was provided, index it under the model's client ID
|
1024
|
-
// and update the model.
|
1025
|
-
if (arguments.length === 2) {
|
1026
|
-
id = hash[primaryKey];
|
1027
|
-
|
1028
|
-
data[clientId] = hash;
|
1029
|
-
set(model, 'data', hash);
|
1030
|
-
}
|
948
|
+
id = hash[primaryKey];
|
1031
949
|
|
1032
950
|
clientId = get(model, 'clientId');
|
951
|
+
data[clientId] = hash;
|
952
|
+
set(model, 'data', hash);
|
1033
953
|
|
1034
954
|
idToClientIdMap[id] = clientId;
|
1035
955
|
idList.push(id);
|
1036
956
|
|
1037
|
-
model.
|
957
|
+
model.adapterDidUpdate();
|
1038
958
|
},
|
1039
959
|
|
1040
960
|
recordWasInvalid: function(record, errors) {
|
1041
|
-
record.
|
961
|
+
record.wasInvalid(errors);
|
1042
962
|
},
|
1043
963
|
|
1044
964
|
// ................
|
@@ -1047,6 +967,7 @@ DS.Store = Ember.Object.extend({
|
|
1047
967
|
|
1048
968
|
registerModelArray: function(array, type, filter) {
|
1049
969
|
var modelArrays = get(this, 'modelArrays');
|
970
|
+
var idToClientIdMap = this.idToClientIdMap(type);
|
1050
971
|
|
1051
972
|
modelArrays.push(array);
|
1052
973
|
|
@@ -1066,7 +987,7 @@ DS.Store = Ember.Object.extend({
|
|
1066
987
|
|
1067
988
|
updateModelArrayFilter: function(array, type, filter) {
|
1068
989
|
var data = this.clientIdToHashMap(type);
|
1069
|
-
var allClientIds = this.clientIdList(type)
|
990
|
+
var allClientIds = this.clientIdList(type);
|
1070
991
|
|
1071
992
|
for (var i=0, l=allClientIds.length; i<l; i++) {
|
1072
993
|
clientId = allClientIds[i];
|
@@ -1080,12 +1001,11 @@ DS.Store = Ember.Object.extend({
|
|
1080
1001
|
},
|
1081
1002
|
|
1082
1003
|
updateModelArrays: function(type, clientId, hash) {
|
1083
|
-
var modelArrays = get(this, 'modelArrays')
|
1084
|
-
modelArrayType, filter;
|
1004
|
+
var modelArrays = get(this, 'modelArrays');
|
1085
1005
|
|
1086
1006
|
modelArrays.forEach(function(array) {
|
1087
|
-
|
1088
|
-
|
1007
|
+
modelArrayType = get(array, 'type');
|
1008
|
+
filter = get(array, 'filterFunction');
|
1089
1009
|
|
1090
1010
|
if (type !== modelArrayType) { return; }
|
1091
1011
|
|
@@ -1218,7 +1138,8 @@ DS.Store = Ember.Object.extend({
|
|
1218
1138
|
|
1219
1139
|
var model = models[clientId];
|
1220
1140
|
if (model) {
|
1221
|
-
model.
|
1141
|
+
model.willLoadData();
|
1142
|
+
model.setData(hash);
|
1222
1143
|
}
|
1223
1144
|
} else {
|
1224
1145
|
clientId = this.pushHash(hash, id, type);
|
@@ -1287,21 +1208,13 @@ DS.Store = Ember.Object.extend({
|
|
1287
1208
|
// . MODEL MATERIALIZATION .
|
1288
1209
|
// .........................
|
1289
1210
|
|
1290
|
-
|
1211
|
+
createModel: function(type, clientId) {
|
1291
1212
|
var model;
|
1292
1213
|
|
1293
|
-
get(this, 'models')[clientId] = model = type.
|
1214
|
+
get(this, 'models')[clientId] = model = type.create({ store: this, clientId: clientId });
|
1294
1215
|
set(model, 'clientId', clientId);
|
1295
|
-
model.
|
1216
|
+
model.loadingData();
|
1296
1217
|
return model;
|
1297
|
-
},
|
1298
|
-
|
1299
|
-
destroy: function() {
|
1300
|
-
if (get(DS, 'defaultStore') === this) {
|
1301
|
-
set(DS, 'defaultStore', null);
|
1302
|
-
}
|
1303
|
-
|
1304
|
-
return this._super();
|
1305
1218
|
}
|
1306
1219
|
});
|
1307
1220
|
|
@@ -1310,7 +1223,7 @@ DS.Store = Ember.Object.extend({
|
|
1310
1223
|
|
1311
1224
|
|
1312
1225
|
(function(exports) {
|
1313
|
-
var get = Ember.get, set = Ember.set, getPath = Ember.getPath
|
1226
|
+
var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
|
1314
1227
|
|
1315
1228
|
var stateProperty = Ember.computed(function(key) {
|
1316
1229
|
var parent = get(this, 'parentState');
|
@@ -1319,14 +1232,6 @@ var stateProperty = Ember.computed(function(key) {
|
|
1319
1232
|
}
|
1320
1233
|
}).property();
|
1321
1234
|
|
1322
|
-
var isEmptyObject = function(object) {
|
1323
|
-
for (var name in object) {
|
1324
|
-
if (object.hasOwnProperty(name)) { return false; }
|
1325
|
-
}
|
1326
|
-
|
1327
|
-
return true;
|
1328
|
-
};
|
1329
|
-
|
1330
1235
|
DS.State = Ember.State.extend({
|
1331
1236
|
isLoaded: stateProperty,
|
1332
1237
|
isDirty: stateProperty,
|
@@ -1334,16 +1239,14 @@ DS.State = Ember.State.extend({
|
|
1334
1239
|
isDeleted: stateProperty,
|
1335
1240
|
isError: stateProperty,
|
1336
1241
|
isNew: stateProperty,
|
1337
|
-
isValid: stateProperty
|
1338
|
-
isPending: stateProperty,
|
1339
|
-
|
1340
|
-
// For states that are substates of a
|
1341
|
-
// DirtyState (updated or created), it is
|
1342
|
-
// useful to be able to determine which
|
1343
|
-
// type of dirty state it is.
|
1344
|
-
dirtyType: stateProperty
|
1242
|
+
isValid: stateProperty
|
1345
1243
|
});
|
1346
1244
|
|
1245
|
+
var cantLoadData = function() {
|
1246
|
+
// TODO: get the current state name
|
1247
|
+
throw "You cannot load data into the store when its associated model is in its current state";
|
1248
|
+
};
|
1249
|
+
|
1347
1250
|
var isEmptyObject = function(obj) {
|
1348
1251
|
for (var prop in obj) {
|
1349
1252
|
if (!obj.hasOwnProperty(prop)) { continue; }
|
@@ -1356,287 +1259,89 @@ var isEmptyObject = function(obj) {
|
|
1356
1259
|
var setProperty = function(manager, context) {
|
1357
1260
|
var key = context.key, value = context.value;
|
1358
1261
|
|
1359
|
-
var model = get(manager, 'model'),
|
1360
|
-
|
1262
|
+
var model = get(manager, 'model'), type = model.constructor;
|
1263
|
+
var store = get(model, 'store');
|
1264
|
+
var data = get(model, 'data');
|
1361
1265
|
|
1362
1266
|
data[key] = value;
|
1363
1267
|
|
1364
|
-
|
1365
|
-
// this record has changed so they can re-evaluate its contents
|
1366
|
-
// to determine membership.
|
1367
|
-
Ember.run.once(model, model.notifyHashWasUpdated);
|
1268
|
+
if (store) { store.hashWasUpdated(type, get(model, 'clientId')); }
|
1368
1269
|
};
|
1369
1270
|
|
1370
|
-
//
|
1371
|
-
//
|
1372
|
-
// treated slightly differently. This method is exposed
|
1373
|
-
// so that each implementation can invoke the common
|
1374
|
-
// behavior, and then implement the behavior specific
|
1375
|
-
// to the state.
|
1376
|
-
var waitingOn = function(manager, object) {
|
1377
|
-
var model = get(manager, 'model'),
|
1378
|
-
pendingQueue = get(model, 'pendingQueue'),
|
1379
|
-
objectGuid = guidFor(object);
|
1380
|
-
|
1381
|
-
var observer = function() {
|
1382
|
-
if (get(object, 'id')) {
|
1383
|
-
manager.send('doneWaitingOn', object);
|
1384
|
-
Ember.removeObserver(object, 'id', observer);
|
1385
|
-
}
|
1386
|
-
};
|
1387
|
-
|
1388
|
-
pendingQueue[objectGuid] = [object, observer];
|
1389
|
-
Ember.addObserver(object, 'id', observer);
|
1390
|
-
};
|
1391
|
-
|
1392
|
-
// Implementation notes:
|
1393
|
-
//
|
1394
|
-
// Each state has a boolean value for all of the following flags:
|
1395
|
-
//
|
1396
|
-
// * isLoaded: The record has a populated `data` property. When a
|
1397
|
-
// record is loaded via `store.find`, `isLoaded` is false
|
1398
|
-
// until the adapter sets it. When a record is created locally,
|
1399
|
-
// its `isLoaded` property is always true.
|
1400
|
-
// * isDirty: The record has local changes that have not yet been
|
1401
|
-
// saved by the adapter. This includes records that have been
|
1402
|
-
// created (but not yet saved) or deleted.
|
1403
|
-
// * isSaving: The record's transaction has been committed, but
|
1404
|
-
// the adapter has not yet acknowledged that the changes have
|
1405
|
-
// been persisted to the backend.
|
1406
|
-
// * isDeleted: The record was marked for deletion. When `isDeleted`
|
1407
|
-
// is true and `isDirty` is true, the record is deleted locally
|
1408
|
-
// but the deletion was not yet persisted. When `isSaving` is
|
1409
|
-
// true, the change is in-flight. When both `isDirty` and
|
1410
|
-
// `isSaving` are false, the change has persisted.
|
1411
|
-
// * isError: The adapter reported that it was unable to save
|
1412
|
-
// local changes to the backend. This may also result in the
|
1413
|
-
// record having its `isValid` property become false if the
|
1414
|
-
// adapter reported that server-side validations failed.
|
1415
|
-
// * isNew: The record was created on the client and the adapter
|
1416
|
-
// did not yet report that it was successfully saved.
|
1417
|
-
// * isValid: No client-side validations have failed and the
|
1418
|
-
// adapter did not report any server-side validation failures.
|
1419
|
-
// * isPending: A record `isPending` when it belongs to an
|
1420
|
-
// association on another record and that record has not been
|
1421
|
-
// saved. A record in this state cannot be saved because it
|
1422
|
-
// lacks a "foreign key" that will be supplied by its parent
|
1423
|
-
// association when the parent record has been created. When
|
1424
|
-
// the adapter reports that the parent has saved, the
|
1425
|
-
// `isPending` property on all children will become `false`
|
1426
|
-
// and the transaction will try to commit the records.
|
1427
|
-
|
1428
|
-
|
1429
|
-
// The dirty state is a abstract state whose functionality is
|
1430
|
-
// shared between the `created` and `updated` states.
|
1431
|
-
//
|
1432
|
-
// The deleted state shares the `isDirty` flag with the
|
1433
|
-
// subclasses of `DirtyState`, but with a very different
|
1434
|
-
// implementation.
|
1271
|
+
// several states share extremely common functionality, so we are factoring
|
1272
|
+
// them out into a common class.
|
1435
1273
|
var DirtyState = DS.State.extend({
|
1436
|
-
|
1437
|
-
|
1438
|
-
//
|
1274
|
+
// these states are virtually identical except that
|
1275
|
+
// they (thrice) use their states name explicitly.
|
1276
|
+
//
|
1277
|
+
// child classes implement stateName.
|
1278
|
+
stateName: null,
|
1439
1279
|
isDirty: true,
|
1280
|
+
willLoadData: cantLoadData,
|
1440
1281
|
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
// This means that there are local pending changes,
|
1445
|
-
// but they have not yet begun to be saved.
|
1446
|
-
uncommitted: DS.State.extend({
|
1447
|
-
// TRANSITIONS
|
1448
|
-
enter: function(manager) {
|
1449
|
-
var dirtyType = get(this, 'dirtyType'),
|
1450
|
-
model = get(manager, 'model');
|
1282
|
+
enter: function(manager) {
|
1283
|
+
var stateName = get(this, 'stateName'),
|
1284
|
+
model = get(manager, 'model');
|
1451
1285
|
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1286
|
+
model.withTransaction(function (t) {
|
1287
|
+
t.modelBecameDirty(stateName, model);
|
1288
|
+
});
|
1289
|
+
},
|
1456
1290
|
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
},
|
1291
|
+
exit: function(manager) {
|
1292
|
+
var stateName = get(this, 'stateName'),
|
1293
|
+
model = get(manager, 'model');
|
1461
1294
|
|
1462
|
-
|
1463
|
-
setProperty: setProperty,
|
1295
|
+
this.notifyModel(model);
|
1464
1296
|
|
1465
|
-
|
1466
|
-
|
1467
|
-
}
|
1297
|
+
model.withTransaction(function (t) {
|
1298
|
+
t.modelBecameClean(stateName, model);
|
1299
|
+
});
|
1300
|
+
},
|
1468
1301
|
|
1469
|
-
|
1470
|
-
waitingOn(manager, object);
|
1471
|
-
manager.goToState('pending');
|
1472
|
-
},
|
1302
|
+
setProperty: setProperty,
|
1473
1303
|
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
}),
|
1304
|
+
willCommit: function(manager) {
|
1305
|
+
manager.goToState('saving');
|
1306
|
+
},
|
1478
1307
|
|
1479
|
-
|
1480
|
-
// saved, it is in the 'in flight' state. Changes to the
|
1481
|
-
// record cannot be made during this window.
|
1482
|
-
inFlight: DS.State.extend({
|
1483
|
-
// FLAGS
|
1308
|
+
saving: DS.State.extend({
|
1484
1309
|
isSaving: true,
|
1485
1310
|
|
1486
|
-
|
1487
|
-
enter: function(manager) {
|
1488
|
-
var dirtyType = get(this, 'dirtyType'),
|
1489
|
-
model = get(manager, 'model');
|
1490
|
-
|
1491
|
-
model.withTransaction(function (t) {
|
1492
|
-
t.modelBecameClean(dirtyType, model);
|
1493
|
-
});
|
1494
|
-
},
|
1495
|
-
|
1496
|
-
// EVENTS
|
1497
|
-
didCommit: function(manager) {
|
1311
|
+
didUpdate: function(manager) {
|
1498
1312
|
manager.goToState('loaded');
|
1499
1313
|
},
|
1500
1314
|
|
1501
|
-
|
1315
|
+
wasInvalid: function(manager, errors) {
|
1502
1316
|
var model = get(manager, 'model');
|
1503
1317
|
|
1504
1318
|
set(model, 'errors', errors);
|
1505
1319
|
manager.goToState('invalid');
|
1506
|
-
},
|
1507
|
-
|
1508
|
-
setData: function(manager, hash) {
|
1509
|
-
var model = get(manager, 'model');
|
1510
|
-
set(model, 'data', hash);
|
1511
1320
|
}
|
1512
1321
|
}),
|
1513
1322
|
|
1514
|
-
// If a record becomes associated with a newly created
|
1515
|
-
// parent record, it will be `pending` until the parent
|
1516
|
-
// record has successfully persisted. Once this happens,
|
1517
|
-
// this record can use the parent's primary key as its
|
1518
|
-
// foreign key.
|
1519
|
-
//
|
1520
|
-
// If the record's transaction had already started to
|
1521
|
-
// commit, the record will transition to the `inFlight`
|
1522
|
-
// state. If it had not, the record will transition to
|
1523
|
-
// the `uncommitted` state.
|
1524
|
-
pending: DS.State.extend({
|
1525
|
-
initialState: 'uncommitted',
|
1526
|
-
|
1527
|
-
// FLAGS
|
1528
|
-
isPending: true,
|
1529
|
-
|
1530
|
-
// SUBSTATES
|
1531
|
-
|
1532
|
-
// A pending record whose transaction has not yet
|
1533
|
-
// started to commit is in this state.
|
1534
|
-
uncommitted: DS.State.extend({
|
1535
|
-
// EVENTS
|
1536
|
-
setProperty: setProperty,
|
1537
|
-
|
1538
|
-
deleteRecord: function(manager) {
|
1539
|
-
var model = get(manager, 'model'),
|
1540
|
-
pendingQueue = get(model, 'pendingQueue'),
|
1541
|
-
tuple;
|
1542
|
-
|
1543
|
-
// since we are leaving the pending state, remove any
|
1544
|
-
// observers we have registered on other records.
|
1545
|
-
for (var prop in pendingQueue) {
|
1546
|
-
if (!pendingQueue.hasOwnProperty(prop)) { continue; }
|
1547
|
-
|
1548
|
-
tuple = pendingQueue[prop];
|
1549
|
-
Ember.removeObserver(tuple[0], 'id', tuple[1]);
|
1550
|
-
}
|
1551
|
-
|
1552
|
-
manager.goToState('deleted');
|
1553
|
-
},
|
1554
|
-
|
1555
|
-
willCommit: function(manager) {
|
1556
|
-
manager.goToState('committing');
|
1557
|
-
},
|
1558
|
-
|
1559
|
-
doneWaitingOn: function(manager, object) {
|
1560
|
-
var model = get(manager, 'model'),
|
1561
|
-
pendingQueue = get(model, 'pendingQueue'),
|
1562
|
-
objectGuid = guidFor(object);
|
1563
|
-
|
1564
|
-
delete pendingQueue[objectGuid];
|
1565
|
-
|
1566
|
-
if (isEmptyObject(pendingQueue)) {
|
1567
|
-
manager.send('doneWaiting');
|
1568
|
-
}
|
1569
|
-
},
|
1570
|
-
|
1571
|
-
doneWaiting: function(manager) {
|
1572
|
-
var dirtyType = get(this, 'dirtyType');
|
1573
|
-
manager.goToState(dirtyType + '.uncommitted');
|
1574
|
-
}
|
1575
|
-
}),
|
1576
|
-
|
1577
|
-
// A pending record whose transaction has started
|
1578
|
-
// to commit is in this state. Since it has not yet
|
1579
|
-
// been sent to the adapter, it is not `inFlight`
|
1580
|
-
// until all of its dependencies have been committed.
|
1581
|
-
committing: DS.State.extend({
|
1582
|
-
// FLAGS
|
1583
|
-
isSaving: true,
|
1584
|
-
|
1585
|
-
// EVENTS
|
1586
|
-
doneWaitingOn: function(manager, object) {
|
1587
|
-
var model = get(manager, 'model'),
|
1588
|
-
pendingQueue = get(model, 'pendingQueue'),
|
1589
|
-
objectGuid = guidFor(object);
|
1590
|
-
|
1591
|
-
delete pendingQueue[objectGuid];
|
1592
|
-
|
1593
|
-
if (isEmptyObject(pendingQueue)) {
|
1594
|
-
manager.send('doneWaiting');
|
1595
|
-
}
|
1596
|
-
},
|
1597
|
-
|
1598
|
-
doneWaiting: function(manager) {
|
1599
|
-
var dirtyType = get(this, 'dirtyType');
|
1600
|
-
manager.goToState(dirtyType + '.inFlight');
|
1601
|
-
}
|
1602
|
-
})
|
1603
|
-
}),
|
1604
|
-
|
1605
|
-
// A record is in the `invalid` state when its client-side
|
1606
|
-
// invalidations have failed, or if the adapter has indicated
|
1607
|
-
// the the record failed server-side invalidations.
|
1608
1323
|
invalid: DS.State.extend({
|
1609
|
-
// FLAGS
|
1610
1324
|
isValid: false,
|
1611
1325
|
|
1612
|
-
// EVENTS
|
1613
|
-
deleteRecord: function(manager) {
|
1614
|
-
manager.goToState('deleted');
|
1615
|
-
},
|
1616
|
-
|
1617
1326
|
setProperty: function(manager, context) {
|
1618
1327
|
setProperty(manager, context);
|
1619
1328
|
|
1620
|
-
var
|
1329
|
+
var stateName = getPath(this, 'parentState.stateName'),
|
1330
|
+
model = get(manager, 'model'),
|
1621
1331
|
errors = get(model, 'errors'),
|
1622
1332
|
key = context.key;
|
1623
1333
|
|
1624
1334
|
delete errors[key];
|
1625
1335
|
|
1626
1336
|
if (isEmptyObject(errors)) {
|
1627
|
-
manager.
|
1337
|
+
manager.goToState(stateName);
|
1628
1338
|
}
|
1629
|
-
},
|
1630
|
-
|
1631
|
-
becameValid: function(manager) {
|
1632
|
-
manager.goToState('uncommitted');
|
1633
1339
|
}
|
1634
1340
|
})
|
1635
1341
|
});
|
1636
1342
|
|
1637
1343
|
var states = {
|
1638
1344
|
rootState: Ember.State.create({
|
1639
|
-
// FLAGS
|
1640
1345
|
isLoaded: false,
|
1641
1346
|
isDirty: false,
|
1642
1347
|
isSaving: false,
|
@@ -1644,126 +1349,80 @@ var states = {
|
|
1644
1349
|
isError: false,
|
1645
1350
|
isNew: false,
|
1646
1351
|
isValid: true,
|
1647
|
-
isPending: false,
|
1648
1352
|
|
1649
|
-
|
1353
|
+
willLoadData: cantLoadData,
|
1354
|
+
|
1355
|
+
didCreate: function(manager) {
|
1356
|
+
manager.goToState('loaded.created');
|
1357
|
+
},
|
1650
1358
|
|
1651
|
-
// A record begins its lifecycle in the `empty` state.
|
1652
|
-
// If its data will come from the adapter, it will
|
1653
|
-
// transition into the `loading` state. Otherwise, if
|
1654
|
-
// the record is being created on the client, it will
|
1655
|
-
// transition into the `created` state.
|
1656
1359
|
empty: DS.State.create({
|
1657
|
-
// EVENTS
|
1658
1360
|
loadingData: function(manager) {
|
1659
1361
|
manager.goToState('loading');
|
1660
|
-
},
|
1661
|
-
|
1662
|
-
setData: function(manager, hash) {
|
1663
|
-
var model = get(manager, 'model');
|
1664
|
-
set(model, 'data', hash);
|
1665
|
-
manager.goToState('loaded.created');
|
1666
1362
|
}
|
1667
1363
|
}),
|
1668
1364
|
|
1669
|
-
// A record enters this state when the store askes
|
1670
|
-
// the adapter for its data. It remains in this state
|
1671
|
-
// until the adapter provides the requested data.
|
1672
|
-
//
|
1673
|
-
// Usually, this process is asynchronous, using an
|
1674
|
-
// XHR to retrieve the data.
|
1675
1365
|
loading: DS.State.create({
|
1676
|
-
|
1366
|
+
willLoadData: Ember.K,
|
1367
|
+
|
1677
1368
|
exit: function(manager) {
|
1678
1369
|
var model = get(manager, 'model');
|
1679
1370
|
model.didLoad();
|
1680
1371
|
},
|
1681
1372
|
|
1682
|
-
// EVENTS
|
1683
1373
|
setData: function(manager, data) {
|
1684
1374
|
var model = get(manager, 'model');
|
1685
1375
|
|
1686
1376
|
model.beginPropertyChanges();
|
1687
|
-
set(
|
1377
|
+
model.set('data', data);
|
1688
1378
|
|
1689
1379
|
if (data !== null) {
|
1690
|
-
manager.
|
1380
|
+
manager.goToState('loaded');
|
1691
1381
|
}
|
1692
1382
|
|
1693
1383
|
model.endPropertyChanges();
|
1694
|
-
},
|
1695
|
-
|
1696
|
-
loadedData: function(manager) {
|
1697
|
-
manager.goToState('loaded');
|
1698
1384
|
}
|
1699
1385
|
}),
|
1700
1386
|
|
1701
|
-
// A record enters this state when its data is populated.
|
1702
|
-
// Most of a record's lifecycle is spent inside substates
|
1703
|
-
// of the `loaded` state.
|
1704
1387
|
loaded: DS.State.create({
|
1705
|
-
initialState: 'saved',
|
1706
|
-
|
1707
|
-
// FLAGS
|
1708
1388
|
isLoaded: true,
|
1709
1389
|
|
1710
|
-
|
1711
|
-
|
1712
|
-
// If there are no local changes to a record, it remains
|
1713
|
-
// in the `saved` state.
|
1714
|
-
saved: DS.State.create({
|
1715
|
-
// EVENTS
|
1716
|
-
setProperty: function(manager, context) {
|
1717
|
-
setProperty(manager, context);
|
1718
|
-
manager.goToState('updated');
|
1719
|
-
},
|
1390
|
+
willLoadData: Ember.K,
|
1720
1391
|
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1392
|
+
setProperty: function(manager, context) {
|
1393
|
+
setProperty(manager, context);
|
1394
|
+
manager.goToState('updated');
|
1395
|
+
},
|
1724
1396
|
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
}
|
1729
|
-
}),
|
1397
|
+
'delete': function(manager) {
|
1398
|
+
manager.goToState('deleted');
|
1399
|
+
},
|
1730
1400
|
|
1731
|
-
// A record is in this state after it has been locally
|
1732
|
-
// created but before the adapter has indicated that
|
1733
|
-
// it has been saved.
|
1734
1401
|
created: DirtyState.create({
|
1735
|
-
|
1736
|
-
|
1737
|
-
// FLAGS
|
1402
|
+
stateName: 'created',
|
1738
1403
|
isNew: true,
|
1739
1404
|
|
1740
|
-
|
1741
|
-
invokeLifecycleCallbacks: function(manager, model) {
|
1405
|
+
notifyModel: function(model) {
|
1742
1406
|
model.didCreate();
|
1743
1407
|
}
|
1744
1408
|
}),
|
1745
1409
|
|
1746
|
-
// A record is in this state if it has already been
|
1747
|
-
// saved to the server, but there are new local changes
|
1748
|
-
// that have not yet been saved.
|
1749
1410
|
updated: DirtyState.create({
|
1750
|
-
|
1411
|
+
stateName: 'updated',
|
1751
1412
|
|
1752
|
-
|
1753
|
-
invokeLifecycleCallbacks: function(manager, model) {
|
1413
|
+
notifyModel: function(model) {
|
1754
1414
|
model.didUpdate();
|
1755
1415
|
}
|
1756
1416
|
})
|
1757
1417
|
}),
|
1758
1418
|
|
1759
|
-
// A record is in this state if it was deleted from the store.
|
1760
1419
|
deleted: DS.State.create({
|
1761
|
-
// FLAGS
|
1762
1420
|
isDeleted: true,
|
1763
1421
|
isLoaded: true,
|
1764
1422
|
isDirty: true,
|
1765
1423
|
|
1766
|
-
|
1424
|
+
willLoadData: cantLoadData,
|
1425
|
+
|
1767
1426
|
enter: function(manager) {
|
1768
1427
|
var model = get(manager, 'model');
|
1769
1428
|
var store = get(model, 'store');
|
@@ -1777,51 +1436,31 @@ var states = {
|
|
1777
1436
|
});
|
1778
1437
|
},
|
1779
1438
|
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
// state. It will exit this state when the record's
|
1784
|
-
// transaction starts to commit.
|
1785
|
-
start: DS.State.create({
|
1786
|
-
willCommit: function(manager) {
|
1787
|
-
manager.goToState('inFlight');
|
1788
|
-
}
|
1789
|
-
}),
|
1439
|
+
willCommit: function(manager) {
|
1440
|
+
manager.goToState('saving');
|
1441
|
+
},
|
1790
1442
|
|
1791
|
-
|
1792
|
-
// before the adapter indicates that the deletion
|
1793
|
-
// has saved to the server, a record is in the
|
1794
|
-
// `inFlight` substate of `deleted`.
|
1795
|
-
inFlight: DS.State.create({
|
1796
|
-
// FLAGS
|
1443
|
+
saving: DS.State.create({
|
1797
1444
|
isSaving: true,
|
1798
1445
|
|
1799
|
-
|
1446
|
+
didDelete: function(manager) {
|
1447
|
+
manager.goToState('saved');
|
1448
|
+
},
|
1449
|
+
|
1800
1450
|
exit: function(stateManager) {
|
1801
1451
|
var model = get(stateManager, 'model');
|
1802
1452
|
|
1803
1453
|
model.withTransaction(function(t) {
|
1804
1454
|
t.modelBecameClean('deleted', model);
|
1805
1455
|
});
|
1806
|
-
},
|
1807
|
-
|
1808
|
-
// EVENTS
|
1809
|
-
didCommit: function(manager) {
|
1810
|
-
manager.goToState('saved');
|
1811
1456
|
}
|
1812
1457
|
}),
|
1813
1458
|
|
1814
|
-
// Once the adapter indicates that the deletion has
|
1815
|
-
// been saved, the record enters the `saved` substate
|
1816
|
-
// of `deleted`.
|
1817
1459
|
saved: DS.State.create({
|
1818
1460
|
isDirty: false
|
1819
1461
|
})
|
1820
1462
|
}),
|
1821
1463
|
|
1822
|
-
// If the adapter indicates that there was an unknown
|
1823
|
-
// error saving a record, the record enters the `error`
|
1824
|
-
// state.
|
1825
1464
|
error: DS.State.create({
|
1826
1465
|
isError: true
|
1827
1466
|
})
|
@@ -1834,12 +1473,6 @@ DS.StateManager = Ember.StateManager.extend({
|
|
1834
1473
|
states: states
|
1835
1474
|
});
|
1836
1475
|
|
1837
|
-
})({});
|
1838
|
-
|
1839
|
-
|
1840
|
-
(function(exports) {
|
1841
|
-
var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
|
1842
|
-
|
1843
1476
|
var retrieveFromCurrentState = Ember.computed(function(key) {
|
1844
1477
|
return get(getPath(this, 'stateManager.currentState'), key);
|
1845
1478
|
}).property('stateManager.currentState').cacheable();
|
@@ -1851,7 +1484,6 @@ DS.Model = Ember.Object.extend({
|
|
1851
1484
|
isDeleted: retrieveFromCurrentState,
|
1852
1485
|
isError: retrieveFromCurrentState,
|
1853
1486
|
isNew: retrieveFromCurrentState,
|
1854
|
-
isPending: retrieveFromCurrentState,
|
1855
1487
|
isValid: retrieveFromCurrentState,
|
1856
1488
|
|
1857
1489
|
clientId: null,
|
@@ -1859,22 +1491,8 @@ DS.Model = Ember.Object.extend({
|
|
1859
1491
|
// because unknownProperty is used, any internal property
|
1860
1492
|
// must be initialized here.
|
1861
1493
|
primaryKey: 'id',
|
1862
|
-
id: Ember.computed(function(key, value) {
|
1863
|
-
var primaryKey = get(this, 'primaryKey'),
|
1864
|
-
data = get(this, 'data');
|
1865
|
-
|
1866
|
-
if (arguments.length === 2) {
|
1867
|
-
set(data, primaryKey, value);
|
1868
|
-
return value;
|
1869
|
-
}
|
1870
|
-
|
1871
|
-
return data && get(data, primaryKey);
|
1872
|
-
}).property('primaryKey', 'data'),
|
1873
|
-
|
1874
1494
|
data: null,
|
1875
|
-
pendingQueue: null,
|
1876
1495
|
transaction: null,
|
1877
|
-
errors: null,
|
1878
1496
|
|
1879
1497
|
didLoad: Ember.K,
|
1880
1498
|
didUpdate: Ember.K,
|
@@ -1885,101 +1503,100 @@ DS.Model = Ember.Object.extend({
|
|
1885
1503
|
model: this
|
1886
1504
|
});
|
1887
1505
|
|
1888
|
-
set(this, 'pendingQueue', {});
|
1889
1506
|
set(this, 'stateManager', stateManager);
|
1890
1507
|
stateManager.goToState('empty');
|
1891
1508
|
},
|
1892
1509
|
|
1510
|
+
withTransaction: function(fn) {
|
1511
|
+
var transaction = get(this, 'transaction') || getPath(this, 'store.defaultTransaction');
|
1512
|
+
|
1513
|
+
if (transaction) { fn(transaction); }
|
1514
|
+
},
|
1515
|
+
|
1516
|
+
setData: function(data) {
|
1517
|
+
var stateManager = get(this, 'stateManager');
|
1518
|
+
stateManager.send('setData', data);
|
1519
|
+
},
|
1520
|
+
|
1521
|
+
setProperty: function(key, value) {
|
1522
|
+
var stateManager = get(this, 'stateManager');
|
1523
|
+
stateManager.send('setProperty', { key: key, value: value });
|
1524
|
+
},
|
1525
|
+
|
1526
|
+
deleteRecord: function() {
|
1527
|
+
var stateManager = get(this, 'stateManager');
|
1528
|
+
stateManager.send('delete');
|
1529
|
+
},
|
1530
|
+
|
1893
1531
|
destroy: function() {
|
1894
|
-
|
1895
|
-
this.deleteRecord();
|
1896
|
-
}
|
1532
|
+
this.deleteRecord();
|
1897
1533
|
this._super();
|
1898
1534
|
},
|
1899
1535
|
|
1900
|
-
|
1901
|
-
|
1536
|
+
loadingData: function() {
|
1537
|
+
var stateManager = get(this, 'stateManager');
|
1538
|
+
stateManager.send('loadingData');
|
1902
1539
|
},
|
1903
1540
|
|
1904
|
-
|
1905
|
-
var
|
1906
|
-
|
1541
|
+
willLoadData: function() {
|
1542
|
+
var stateManager = get(this, 'stateManager');
|
1543
|
+
stateManager.send('willLoadData');
|
1907
1544
|
},
|
1908
1545
|
|
1909
|
-
|
1910
|
-
|
1546
|
+
willCommit: function() {
|
1547
|
+
var stateManager = get(this, 'stateManager');
|
1548
|
+
stateManager.send('willCommit');
|
1911
1549
|
},
|
1912
1550
|
|
1913
|
-
|
1914
|
-
this
|
1551
|
+
adapterDidUpdate: function() {
|
1552
|
+
var stateManager = get(this, 'stateManager');
|
1553
|
+
stateManager.send('didUpdate');
|
1915
1554
|
},
|
1916
1555
|
|
1917
|
-
|
1918
|
-
this
|
1556
|
+
adapterDidCreate: function() {
|
1557
|
+
var stateManager = get(this, 'stateManager');
|
1558
|
+
stateManager.send('didCreate');
|
1919
1559
|
},
|
1920
1560
|
|
1921
|
-
|
1922
|
-
var
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1561
|
+
adapterDidDelete: function() {
|
1562
|
+
var stateManager = get(this, 'stateManager');
|
1563
|
+
stateManager.send('didDelete');
|
1564
|
+
},
|
1565
|
+
|
1566
|
+
wasInvalid: function(errors) {
|
1567
|
+
var stateManager = get(this, 'stateManager');
|
1568
|
+
stateManager.send('wasInvalid', errors);
|
1926
1569
|
},
|
1927
1570
|
|
1928
1571
|
unknownProperty: function(key) {
|
1929
1572
|
var data = get(this, 'data');
|
1930
1573
|
|
1931
|
-
if (data
|
1932
|
-
|
1574
|
+
if (data) {
|
1575
|
+
return get(data, key);
|
1933
1576
|
}
|
1934
1577
|
},
|
1935
1578
|
|
1936
1579
|
setUnknownProperty: function(key, value) {
|
1937
1580
|
var data = get(this, 'data');
|
1581
|
+
ember_assert("You cannot set a model attribute before its data is loaded.", !!data);
|
1938
1582
|
|
1939
|
-
|
1940
|
-
|
1941
|
-
} else {
|
1942
|
-
return this._super(key, value);
|
1943
|
-
}
|
1583
|
+
this.setProperty(key, value);
|
1584
|
+
return value;
|
1944
1585
|
}
|
1945
1586
|
});
|
1946
1587
|
|
1947
|
-
// Helper function to generate store aliases.
|
1948
|
-
// This returns a function that invokes the named alias
|
1949
|
-
// on the default store, but injects the class as the
|
1950
|
-
// first parameter.
|
1951
|
-
var storeAlias = function(methodName) {
|
1952
|
-
return function() {
|
1953
|
-
var store = get(DS, 'defaultStore'),
|
1954
|
-
args = [].slice.call(arguments);
|
1955
|
-
|
1956
|
-
args.unshift(this);
|
1957
|
-
return store[methodName].apply(store, args);
|
1958
|
-
};
|
1959
|
-
};
|
1960
|
-
|
1961
1588
|
DS.Model.reopenClass({
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
1969
|
-
},
|
1970
|
-
|
1971
|
-
createRecord: storeAlias('createRecord')
|
1589
|
+
typeForAssociation: function(association) {
|
1590
|
+
var type = this.metaForProperty(association).type;
|
1591
|
+
if (typeof type === 'string') {
|
1592
|
+
type = getPath(this, type, false) || getPath(window, type);
|
1593
|
+
}
|
1594
|
+
return type;
|
1595
|
+
}
|
1972
1596
|
});
|
1973
1597
|
|
1974
|
-
})({});
|
1975
|
-
|
1976
|
-
|
1977
|
-
(function(exports) {
|
1978
|
-
var get = Ember.get, getPath = Ember.getPath;
|
1979
1598
|
DS.attr = function(type, options) {
|
1980
1599
|
var transform = DS.attr.transforms[type];
|
1981
|
-
ember_assert("Could not find model attribute of type " + type, !!transform);
|
1982
|
-
|
1983
1600
|
var transformFrom = transform.from;
|
1984
1601
|
var transformTo = transform.to;
|
1985
1602
|
|
@@ -2001,24 +1618,73 @@ DS.attr = function(type, options) {
|
|
2001
1618
|
}
|
2002
1619
|
}).property('data');
|
2003
1620
|
};
|
1621
|
+
|
1622
|
+
var embeddedFindRecord = function(store, type, data, key, one) {
|
1623
|
+
var association = data ? get(data, key) : one ? null : [];
|
1624
|
+
if (one) {
|
1625
|
+
return association ? store.load(type, association).id : null;
|
1626
|
+
} else {
|
1627
|
+
return association ? store.loadMany(type, association).ids : [];
|
1628
|
+
}
|
1629
|
+
};
|
1630
|
+
|
1631
|
+
var referencedFindRecord = function(store, type, data, key, one) {
|
1632
|
+
return data ? get(data, key) : one ? null : [];
|
1633
|
+
};
|
1634
|
+
|
1635
|
+
var hasAssociation = function(type, options, one) {
|
1636
|
+
var embedded = options && options.embedded,
|
1637
|
+
findRecord = embedded ? embeddedFindRecord : referencedFindRecord;
|
1638
|
+
|
1639
|
+
return Ember.computed(function(key) {
|
1640
|
+
var data = get(this, 'data'), ids, id, association,
|
1641
|
+
store = get(this, 'store');
|
1642
|
+
|
1643
|
+
if (typeof type === 'string') {
|
1644
|
+
type = getPath(this, type, false) || getPath(window, type);
|
1645
|
+
}
|
1646
|
+
|
1647
|
+
key = (options && options.key) ? options.key : key;
|
1648
|
+
if (one) {
|
1649
|
+
id = findRecord(store, type, data, key, true);
|
1650
|
+
association = id ? store.find(type, id) : null;
|
1651
|
+
} else {
|
1652
|
+
ids = findRecord(store, type, data, key);
|
1653
|
+
association = store.findMany(type, ids);
|
1654
|
+
}
|
1655
|
+
|
1656
|
+
return association;
|
1657
|
+
}).property('data').cacheable().meta({ type: type });
|
1658
|
+
};
|
1659
|
+
|
1660
|
+
DS.hasMany = function(type, options) {
|
1661
|
+
ember_assert("The type passed to DS.hasMany must be defined", !!type);
|
1662
|
+
return hasAssociation(type, options);
|
1663
|
+
};
|
1664
|
+
|
1665
|
+
DS.hasOne = function(type, options) {
|
1666
|
+
ember_assert("The type passed to DS.hasOne must be defined", !!type);
|
1667
|
+
return hasAssociation(type, options, true);
|
1668
|
+
};
|
1669
|
+
|
2004
1670
|
DS.attr.transforms = {
|
2005
1671
|
string: {
|
2006
1672
|
from: function(serialized) {
|
2007
|
-
return
|
1673
|
+
return Em.none(serialized) ? null : String(serialized);
|
2008
1674
|
},
|
2009
1675
|
|
2010
1676
|
to: function(deserialized) {
|
2011
|
-
return
|
1677
|
+
return Em.none(deserialized) ? null : String(deserialized);
|
2012
1678
|
}
|
2013
1679
|
},
|
2014
1680
|
|
2015
1681
|
integer: {
|
2016
1682
|
from: function(serialized) {
|
2017
|
-
return
|
1683
|
+
return Em.none(serialized) ? null : Number(serialized);
|
2018
1684
|
},
|
2019
1685
|
|
2020
1686
|
to: function(deserialized) {
|
2021
|
-
return
|
1687
|
+
return Em.none(deserialized) ? null : Number(deserialized);
|
2022
1688
|
}
|
2023
1689
|
},
|
2024
1690
|
|
@@ -2080,76 +1746,6 @@ DS.attr.transforms = {
|
|
2080
1746
|
}
|
2081
1747
|
};
|
2082
1748
|
|
2083
|
-
|
2084
|
-
})({});
|
2085
|
-
|
2086
|
-
|
2087
|
-
(function(exports) {
|
2088
|
-
var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
|
2089
|
-
DS.Model.reopenClass({
|
2090
|
-
typeForAssociation: function(association) {
|
2091
|
-
var type = this.metaForProperty(association).type;
|
2092
|
-
if (typeof type === 'string') {
|
2093
|
-
type = getPath(this, type, false) || getPath(window, type);
|
2094
|
-
}
|
2095
|
-
return type;
|
2096
|
-
}
|
2097
|
-
});
|
2098
|
-
|
2099
|
-
|
2100
|
-
var embeddedFindRecord = function(store, type, data, key, one) {
|
2101
|
-
var association = data ? get(data, key) : one ? null : [];
|
2102
|
-
if (one) {
|
2103
|
-
return association ? store.load(type, association).id : null;
|
2104
|
-
} else {
|
2105
|
-
return association ? store.loadMany(type, association).ids : [];
|
2106
|
-
}
|
2107
|
-
};
|
2108
|
-
|
2109
|
-
var referencedFindRecord = function(store, type, data, key, one) {
|
2110
|
-
return data ? get(data, key) : one ? null : [];
|
2111
|
-
};
|
2112
|
-
|
2113
|
-
var hasAssociation = function(type, options, one) {
|
2114
|
-
var embedded = options && options.embedded,
|
2115
|
-
findRecord = embedded ? embeddedFindRecord : referencedFindRecord;
|
2116
|
-
|
2117
|
-
return Ember.computed(function(key) {
|
2118
|
-
var data = get(this, 'data'), ids, id, association,
|
2119
|
-
store = get(this, 'store');
|
2120
|
-
|
2121
|
-
if (typeof type === 'string') {
|
2122
|
-
type = getPath(this, type, false) || getPath(window, type);
|
2123
|
-
}
|
2124
|
-
|
2125
|
-
key = (options && options.key) ? options.key : key;
|
2126
|
-
if (one) {
|
2127
|
-
id = findRecord(store, type, data, key, true);
|
2128
|
-
association = id ? store.find(type, id) : null;
|
2129
|
-
} else {
|
2130
|
-
ids = findRecord(store, type, data, key);
|
2131
|
-
association = store.findMany(type, ids);
|
2132
|
-
set(association, 'parentRecord', this);
|
2133
|
-
}
|
2134
|
-
|
2135
|
-
return association;
|
2136
|
-
}).property('data').cacheable().meta({ type: type });
|
2137
|
-
};
|
2138
|
-
|
2139
|
-
DS.hasMany = function(type, options) {
|
2140
|
-
ember_assert("The type passed to DS.hasMany must be defined", !!type);
|
2141
|
-
return hasAssociation(type, options);
|
2142
|
-
};
|
2143
|
-
|
2144
|
-
DS.hasOne = function(type, options) {
|
2145
|
-
ember_assert("The type passed to DS.hasOne must be defined", !!type);
|
2146
|
-
return hasAssociation(type, options, true);
|
2147
|
-
};
|
2148
|
-
|
2149
|
-
})({});
|
2150
|
-
|
2151
|
-
|
2152
|
-
(function(exports) {
|
2153
1749
|
})({});
|
2154
1750
|
|
2155
1751
|
|