rightnow_oms 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|