Guest User

Untitled

a guest
Oct 20th, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.80 KB | None | 0 0
  1. (function(exports) {
  2. window.DS = Ember.Namespace.create();
  3.  
  4. })({});
  5.  
  6.  
  7. (function(exports) {
  8. DS.Adapter = Ember.Object.extend({
  9. commit: function(store, commitDetails) {
  10. commitDetails.updated.eachType(function(type, array) {
  11. this.updateRecords(store, type, array.slice());
  12. }, this);
  13.  
  14. commitDetails.created.eachType(function(type, array) {
  15. this.createRecords(store, type, array.slice());
  16. }, this);
  17.  
  18. commitDetails.deleted.eachType(function(type, array) {
  19. this.deleteRecords(store, type, array.slice());
  20. }, this);
  21. },
  22.  
  23. createRecords: function(store, type, models) {
  24. models.forEach(function(model) {
  25. this.createRecord(store, type, model);
  26. }, this);
  27. },
  28.  
  29. updateRecords: function(store, type, models) {
  30. models.forEach(function(model) {
  31. this.updateRecord(store, type, model);
  32. }, this);
  33. },
  34.  
  35. deleteRecords: function(store, type, models) {
  36. models.forEach(function(model) {
  37. this.deleteRecord(store, type, model);
  38. }, this);
  39. },
  40.  
  41. findMany: function(store, type, ids) {
  42. ids.forEach(function(id) {
  43. this.find(store, type, id);
  44. }, this);
  45. }
  46. });
  47. })({});
  48.  
  49.  
  50. (function(exports) {
  51. DS.fixtureAdapter = DS.Adapter.create({
  52. find: function(store, type, id) {
  53. var fixtures = type.FIXTURES;
  54.  
  55. ember_assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
  56. if (fixtures.hasLoaded) { return; }
  57.  
  58. setTimeout(function() {
  59. store.loadMany(type, fixtures);
  60. fixtures.hasLoaded = true;
  61. }, 300);
  62. },
  63.  
  64. findMany: function() {
  65. this.find.apply(this, arguments);
  66. },
  67.  
  68. findAll: function(store, type) {
  69. var fixtures = type.FIXTURES;
  70.  
  71. ember_assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
  72.  
  73. var ids = fixtures.map(function(item, index, self){ return item.id });
  74. store.loadMany(type, ids, fixtures);
  75. }
  76.  
  77. });
  78.  
  79. })({});
  80.  
  81.  
  82. (function(exports) {
  83. var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
  84.  
  85. DS.RESTAdapter = DS.Adapter.extend({
  86. createRecord: function(store, type, model) {
  87. var root = this.rootForType(type);
  88.  
  89. var data = {};
  90. data[root] = get(model, 'data');
  91.  
  92. this.ajax("/" + this.pluralize(root), "POST", {
  93. data: data,
  94. success: function(json) {
  95. store.didCreateRecord(model, json[root]);
  96. }
  97. });
  98. },
  99.  
  100. createRecords: function(store, type, models) {
  101. if (get(this, 'bulkCommit') === false) {
  102. return this._super(store, type, models);
  103. }
  104.  
  105. var root = this.rootForType(type),
  106. plural = this.pluralize(root);
  107.  
  108. var data = {};
  109. data[plural] = models.map(function(model) {
  110. return get(model, 'data');
  111. });
  112.  
  113. this.ajax("/" + this.pluralize(root), "POST", {
  114. data: data,
  115. success: function(json) {
  116. store.didCreateRecords(type, models, json[plural]);
  117. }
  118. });
  119. },
  120.  
  121. updateRecord: function(store, type, model) {
  122. var primaryKey = getPath(type, 'proto.primaryKey'),
  123. id = get(model, primaryKey);
  124. var root = this.rootForType(type);
  125.  
  126. var data = {};
  127. data[root] = get(model, 'data');
  128.  
  129. var url = ["", this.pluralize(root), id].join("/");
  130.  
  131. this.ajax(url, "PUT", {
  132. data: data,
  133. success: function(json) {
  134. store.didUpdateRecord(model, json[root]);
  135. }
  136. });
  137. },
  138.  
  139. updateRecords: function(store, type, models) {
  140. if (get(this, 'bulkCommit') === false) {
  141. return this._super(store, type, models);
  142. }
  143.  
  144. var root = this.rootForType(type),
  145. plural = this.pluralize(root);
  146.  
  147. var data = {};
  148. data[plural] = models.map(function(model) {
  149. return get(model, 'data');
  150. });
  151.  
  152. this.ajax("/" + this.pluralize(root), "POST", {
  153. data: data,
  154. success: function(json) {
  155. store.didUpdateRecords(models, json[plural]);
  156. }
  157. });
  158. },
  159.  
  160. deleteRecord: function(store, type, model) {
  161. var primaryKey = getPath(type, 'proto.primaryKey'),
  162. id = get(model, primaryKey);
  163. var root = this.rootForType(type);
  164.  
  165. var url = ["", this.pluralize(root), id].join("/");
  166.  
  167. this.ajax(url, "DELETE", {
  168. success: function(json) {
  169. store.didDeleteRecord(model);
  170. }
  171. });
  172. },
  173.  
  174. deleteRecords: function(store, type, models) {
  175. if (get(this, 'bulkCommit') === false) {
  176. return this._super(store, type, models);
  177. }
  178.  
  179. var root = this.rootForType(type),
  180. plural = this.pluralize(root),
  181. primaryKey = getPath(type, 'proto.primaryKey');
  182.  
  183. var data = {};
  184. data[plural] = models.map(function(model) {
  185. return get(model, primaryKey);
  186. });
  187.  
  188. this.ajax("/" + this.pluralize(root) + "/delete", "POST", {
  189. data: data,
  190. success: function(json) {
  191. store.didDeleteRecords(models);
  192. }
  193. });
  194. },
  195.  
  196. find: function(store, type, id) {
  197. var root = this.rootForType(type);
  198.  
  199. var url = ["", this.pluralize(root), id].join("/");
  200.  
  201. this.ajax(url, "GET", {
  202. success: function(json) {
  203. store.load(type, json[root]);
  204. }
  205. });
  206. },
  207.  
  208. findMany: function(store, type, ids) {
  209. var root = this.rootForType(type), plural = this.pluralize(root);
  210.  
  211. this.ajax("/" + plural, "GET", {
  212. data: { ids: ids },
  213. success: function(json) {
  214. store.loadMany(type, ids, json[plural]);
  215. }
  216. });
  217. var url = "/" + plural;
  218. },
  219.  
  220. findAll: function(store, type) {
  221. var root = this.rootForType(type), plural = this.pluralize(root);
  222.  
  223. this.ajax("/" + plural, "GET", {
  224. success: function(json) {
  225. store.loadMany(type, json[plural]);
  226. }
  227. });
  228. },
  229.  
  230. findQuery: function(store, type, query, modelArray) {
  231. var root = this.rootForType(type), plural = this.pluralize(root);
  232.  
  233. this.ajax("/" + plural, "GET", {
  234. data: query,
  235. success: function(json) {
  236. modelArray.load(json[plural]);
  237. }
  238. });
  239. },
  240.  
  241. // HELPERS
  242.  
  243. plurals: {},
  244.  
  245. // define a plurals hash in your subclass to define
  246. // special-case pluralization
  247. pluralize: function(name) {
  248. return this.plurals[name] || name + "s";
  249. },
  250.  
  251. rootForType: function(type) {
  252. if (type.url) { return type.url; }
  253.  
  254. // use the last part of the name as the URL
  255. var parts = type.toString().split(".");
  256. var name = parts[parts.length - 1];
  257. return name.replace(/([A-Z])/g, '_$1').toLowerCase().slice(1);
  258. },
  259.  
  260. ajax: function(url, type, hash) {
  261. hash.url = url;
  262. hash.type = type;
  263. hash.dataType = "json";
  264.  
  265. jQuery.ajax(hash);
  266. }
  267. });
  268.  
  269.  
  270. })({});
  271.  
  272.  
  273. (function(exports) {
  274. var get = Ember.get, set = Ember.set;
  275.  
  276. DS.ModelArray = Ember.ArrayProxy.extend({
  277. type: null,
  278. content: null,
  279. store: null,
  280.  
  281. init: function() {
  282. set(this, 'modelCache', Ember.A([]));
  283. this._super();
  284. },
  285.  
  286. arrayDidChange: function(array, index, removed, added) {
  287. var modelCache = get(this, 'modelCache');
  288. modelCache.replace(index, 0, Array(added));
  289.  
  290. this._super(array, index, removed, added);
  291. },
  292.  
  293. arrayWillChange: function(array, index, removed, added) {
  294. this._super(array, index, removed, added);
  295.  
  296. var modelCache = get(this, 'modelCache');
  297. modelCache.replace(index, removed);
  298. },
  299.  
  300. objectAtContent: function(index) {
  301. var modelCache = get(this, 'modelCache');
  302. var model = modelCache.objectAt(index);
  303.  
  304. if (!model) {
  305. var store = get(this, 'store');
  306. var content = get(this, 'content');
  307.  
  308. var contentObject = content.objectAt(index);
  309.  
  310. if (contentObject !== undefined) {
  311. model = store.findByClientId(get(this, 'type'), contentObject);
  312. modelCache.replace(index, 1, [model]);
  313. }
  314. }
  315.  
  316. return model;
  317. }
  318. });
  319.  
  320. DS.FilteredModelArray = DS.ModelArray.extend({
  321. filterFunction: null,
  322.  
  323. updateFilter: Ember.observer(function() {
  324. var store = get(this, 'store');
  325. store.updateModelArrayFilter(this, get(this, 'type'), get(this, 'filterFunction'));
  326. }, 'filterFunction')
  327. });
  328.  
  329. DS.AdapterPopulatedModelArray = DS.ModelArray.extend({
  330. query: null,
  331. isLoaded: false,
  332.  
  333. load: function(array) {
  334. var store = get(this, 'store'), type = get(this, 'type');
  335.  
  336. var clientIds = store.loadMany(type, array).clientIds;
  337.  
  338. this.beginPropertyChanges();
  339. set(this, 'content', Ember.A(clientIds));
  340. set(this, 'isLoaded', true);
  341. this.endPropertyChanges();
  342. }
  343. });
  344.  
  345. })({});
  346.  
  347.  
  348. (function(exports) {
  349. var get = Ember.get, set = Ember.set, getPath = Ember.getPath, fmt = Ember.String.fmt;
  350.  
  351. var OrderedSet = Ember.Object.extend({
  352. init: function() {
  353. this.clear();
  354. },
  355.  
  356. clear: function() {
  357. this.set('presenceSet', {});
  358. this.set('list', Ember.NativeArray.apply([]));
  359. },
  360.  
  361. add: function(obj) {
  362. var guid = Ember.guidFor(obj),
  363. presenceSet = get(this, 'presenceSet'),
  364. list = get(this, 'list');
  365.  
  366. if (guid in presenceSet) { return; }
  367.  
  368. presenceSet[guid] = true;
  369. list.pushObject(obj);
  370. },
  371.  
  372. remove: function(obj) {
  373. var guid = Ember.guidFor(obj),
  374. presenceSet = get(this, 'presenceSet'),
  375. list = get(this, 'list');
  376.  
  377. delete presenceSet[guid];
  378. list.removeObject(obj);
  379. },
  380.  
  381. isEmpty: function() {
  382. return getPath(this, 'list.length') === 0;
  383. },
  384.  
  385. forEach: function(fn, self) {
  386. get(this, 'list').forEach(function(item) {
  387. fn.call(self, item);
  388. });
  389. },
  390.  
  391. toArray: function() {
  392. return get(this, 'list').slice();
  393. }
  394. });
  395.  
  396. /**
  397. A Hash stores values indexed by keys. Unlike JavaScript's
  398. default Objects, the keys of a Hash can be any JavaScript
  399. object.
  400.  
  401. Internally, a Hash has two data structures:
  402.  
  403. `keys`: an OrderedSet of all of the existing keys
  404. `values`: a JavaScript Object indexed by the
  405. Ember.guidFor(key)
  406.  
  407. When a key/value pair is added for the first time, we
  408. add the key to the `keys` OrderedSet, and create or
  409. replace an entry in `values`. When an entry is deleted,
  410. we delete its entry in `keys` and `values`.
  411. */
  412.  
  413. var Hash = Ember.Object.extend({
  414. init: function() {
  415. set(this, 'keys', OrderedSet.create());
  416. set(this, 'values', {});
  417. },
  418.  
  419. add: function(key, value) {
  420. var keys = get(this, 'keys'), values = get(this, 'values');
  421. var guid = Ember.guidFor(key);
  422.  
  423. keys.add(key);
  424. values[guid] = value;
  425.  
  426. return value;
  427. },
  428.  
  429. remove: function(key) {
  430. var keys = get(this, 'keys'), values = get(this, 'values');
  431. var guid = Ember.guidFor(key), value;
  432.  
  433. keys.remove(key);
  434.  
  435. value = values[guid];
  436. delete values[guid];
  437.  
  438. return value;
  439. },
  440.  
  441. fetch: function(key) {
  442. var values = get(this, 'values');
  443. var guid = Ember.guidFor(key);
  444.  
  445. return values[guid];
  446. },
  447.  
  448. forEach: function(fn, binding) {
  449. var keys = get(this, 'keys'), values = get(this, 'values');
  450.  
  451. keys.forEach(function(key) {
  452. var guid = Ember.guidFor(key);
  453. fn.call(binding, key, values[guid]);
  454. });
  455. }
  456. });
  457.  
  458. DS.Transaction = Ember.Object.extend({
  459. init: function() {
  460. set(this, 'dirty', {
  461. created: Hash.create(),
  462. updated: Hash.create(),
  463. deleted: Hash.create()
  464. });
  465. },
  466.  
  467. createRecord: function(type, hash) {
  468. var store = get(this, 'store');
  469.  
  470. return store.createRecord(type, hash, this);
  471. },
  472.  
  473. add: function(model) {
  474. var modelTransaction = get(model, 'transaction');
  475. ember_assert("Models cannot belong to more than one transaction at a time.", !modelTransaction);
  476.  
  477. set(model, 'transaction', this);
  478. },
  479.  
  480. modelBecameDirty: function(kind, model) {
  481. var dirty = get(get(this, 'dirty'), kind),
  482. type = model.constructor;
  483.  
  484. var models = dirty.fetch(type);
  485.  
  486. models = models || dirty.add(type, OrderedSet.create());
  487. models.add(model);
  488. },
  489.  
  490. modelBecameClean: function(kind, model) {
  491. var dirty = get(get(this, 'dirty'), kind),
  492. type = model.constructor;
  493.  
  494. var models = dirty.fetch(type);
  495. models.remove(model);
  496.  
  497. set(model, 'transaction', null);
  498. },
  499.  
  500. commit: function() {
  501. var dirtyMap = get(this, 'dirty');
  502.  
  503. var iterate = function(kind, fn, binding) {
  504. var dirty = get(dirtyMap, kind);
  505.  
  506. dirty.forEach(function(type, models) {
  507. if (models.isEmpty()) { return; }
  508.  
  509. models.forEach(function(model) { model.willCommit(); });
  510. fn.call(binding, type, models.toArray());
  511. });
  512. };
  513.  
  514. var commitDetails = {
  515. updated: {
  516. eachType: function(fn, binding) { iterate('updated', fn, binding); }
  517. },
  518.  
  519. created: {
  520. eachType: function(fn, binding) { iterate('created', fn, binding); }
  521. },
  522.  
  523. deleted: {
  524. eachType: function(fn, binding) { iterate('deleted', fn, binding); }
  525. }
  526. };
  527.  
  528. var store = get(this, 'store');
  529. var adapter = get(store, '_adapter');
  530. if (adapter && adapter.commit) { adapter.commit(store, commitDetails); }
  531. else { throw fmt("Adapter is either null or do not implement `commit` method", this); }
  532. }
  533. });
  534.  
  535. })({});
  536.  
  537.  
  538. (function(exports) {
  539. var get = Ember.get, set = Ember.set, getPath = Ember.getPath, fmt = Ember.String.fmt;
  540.  
  541. var OrderedSet = Ember.Object.extend({
  542. init: function() {
  543. this.clear();
  544. },
  545.  
  546. clear: function() {
  547. this.set('presenceSet', {});
  548. this.set('list', Ember.NativeArray.apply([]));
  549. },
  550.  
  551. add: function(obj) {
  552. var guid = Ember.guidFor(obj),
  553. presenceSet = get(this, 'presenceSet'),
  554. list = get(this, 'list');
  555.  
  556. if (guid in presenceSet) { return; }
  557.  
  558. presenceSet[guid] = true;
  559. list.pushObject(obj);
  560. },
  561.  
  562. remove: function(obj) {
  563. var guid = Ember.guidFor(obj),
  564. presenceSet = get(this, 'presenceSet'),
  565. list = get(this, 'list');
  566.  
  567. delete presenceSet[guid];
  568. list.removeObject(obj);
  569. },
  570.  
  571. isEmpty: function() {
  572. return getPath(this, 'list.length') === 0;
  573. },
  574.  
  575. forEach: function(fn, self) {
  576. get(this, 'list').forEach(function(item) {
  577. fn.call(self, item);
  578. });
  579. }
  580. });
  581.  
  582. // Implementors Note:
  583. //
  584. // The variables in this file are consistently named according to the following
  585. // scheme:
  586. //
  587. // * +id+ means an identifier managed by an external source, provided inside the
  588. // data hash provided by that source.
  589. // * +clientId+ means a transient numerical identifier generated at runtime by
  590. // the data store. It is important primarily because newly created objects may
  591. // not yet have an externally generated id.
  592. // * +type+ means a subclass of DS.Model.
  593.  
  594. /**
  595. The store contains all of the hashes for data models loaded from the server.
  596. It is also responsible for creating instances of DS.Model when you request one
  597. of these data hashes, so that they can be bound to in your Handlebars templates.
  598.  
  599. Create a new store like this:
  600.  
  601. MyApp.store = DS.Store.create();
  602.  
  603. You can retrieve DS.Model instances from the store in several ways. To retrieve
  604. a model for a specific id, use the `find()` method:
  605.  
  606. var model = MyApp.store.find(MyApp.Contact, 123);
  607.  
  608. By default, the store will talk to your backend using a standard REST mechanism.
  609. You can customize how the store talks to your backend by specifying a custom adapter:
  610.  
  611. MyApp.store = DS.Store.create({
  612. adapter: 'MyApp.CustomAdapter'
  613. });
  614.  
  615. You can learn more about writing a custom adapter by reading the `DS.Adapter`
  616. documentation.
  617. */
  618. DS.Store = Ember.Object.extend({
  619.  
  620. /**
  621. Many methods can be invoked without specifying which store should be used.
  622. In those cases, the first store created will be used as the default. If
  623. an application has multiple stores, it should specify which store to use
  624. when performing actions, such as finding records by id.
  625.  
  626. The init method registers this store as the default if none is specified.
  627. */
  628. init: function() {
  629. if (!get(DS, 'defaultStore') || get(this, 'isDefaultStore')) {
  630. set(DS, 'defaultStore', this);
  631. }
  632.  
  633. set(this, 'data', []);
  634. set(this, '_typeMap', {});
  635. set(this, 'models', []);
  636. set(this, 'modelArrays', []);
  637. set(this, 'modelArraysByClientId', {});
  638. set(this, 'defaultTransaction', DS.Transaction.create({ store: this }));
  639.  
  640. return this._super();
  641. },
  642.  
  643. transaction: function() {
  644. return DS.Transaction.create({ store: this });
  645. },
  646.  
  647. modelArraysForClientId: function(clientId) {
  648. var modelArrays = get(this, 'modelArraysByClientId');
  649. var ret = modelArrays[clientId];
  650.  
  651. if (!ret) {
  652. ret = modelArrays[clientId] = OrderedSet.create();
  653. }
  654.  
  655. return ret;
  656. },
  657.  
  658. /**
  659. The adapter to use to communicate to a backend server or other persistence layer.
  660.  
  661. This can be specified as an instance, a class, or a property path that specifies
  662. where the adapter can be located.
  663.  
  664. @property {DS.Adapter|String}
  665. */
  666. adapter: null,
  667.  
  668. _adapter: Ember.computed(function() {
  669. var adapter = get(this, 'adapter');
  670. if (typeof adapter === 'string') {
  671. return getPath(this, adapter, false) || getPath(window, adapter);
  672. }
  673. return adapter;
  674. }).property('adapter').cacheable(),
  675.  
  676. clientIdCounter: -1,
  677.  
  678. // ....................
  679. // . CREATE NEW MODEL .
  680. // ....................
  681.  
  682. createRecord: function(type, hash, transaction) {
  683. hash = hash || {};
  684.  
  685. var id = hash[getPath(type, 'proto.primaryKey')] || null;
  686.  
  687. var model = type.create({
  688. data: hash || {},
  689. store: this,
  690. transaction: transaction
  691. });
  692.  
  693. model.adapterDidCreate();
  694.  
  695. var data = this.clientIdToHashMap(type);
  696. var models = get(this, 'models');
  697.  
  698. var clientId = this.pushHash(hash, id, type);
  699.  
  700. set(model, 'clientId', clientId);
  701.  
  702. models[clientId] = model;
  703.  
  704. this.updateModelArrays(type, clientId, hash);
  705.  
  706. return model;
  707. },
  708.  
  709. // ................
  710. // . DELETE MODEL .
  711. // ................
  712.  
  713. deleteRecord: function(model) {
  714. model.deleteRecord();
  715. },
  716.  
  717. // ...............
  718. // . FIND MODELS .
  719. // ...............
  720.  
  721. /**
  722. Finds a model by its id. If the data for that model has already been
  723. loaded, an instance of DS.Model with that data will be returned
  724. immediately. Otherwise, an empty DS.Model instance will be returned in
  725. the loading state. As soon as the requested data is available, the model
  726. will be moved into the loaded state and all of the information will be
  727. available.
  728.  
  729. Note that only one DS.Model instance is ever created per unique id for a
  730. given type.
  731.  
  732. Example:
  733.  
  734. var record = MyApp.store.find(MyApp.Person, 1234);
  735.  
  736. @param {DS.Model} type
  737. @param {String|Number} id
  738. */
  739. find: function(type, id, query) {
  740. if (id === undefined) {
  741. return this.findMany(type, null, null);
  742. }
  743.  
  744. if (query !== undefined) {
  745. return this.findMany(type, id, query);
  746. } else if (Ember.typeOf(id) === 'object') {
  747. return this.findQuery(type, id);
  748. }
  749.  
  750. if (Ember.isArray(id)) {
  751. return this.findMany(type, id);
  752. }
  753.  
  754. var clientId = this.clientIdForId(type, id);
  755.  
  756. return this.findByClientId(type, clientId, id);
  757. },
  758.  
  759. findByClientId: function(type, clientId, id) {
  760. var model;
  761.  
  762. var models = get(this, 'models');
  763. var data = this.clientIdToHashMap(type);
  764.  
  765. // If there is already a clientId assigned for this
  766. // type/id combination, try to find an existing
  767. // model for that id and return. Otherwise,
  768. // materialize a new model and set its data to the
  769. // value we already have.
  770. if (clientId !== undefined) {
  771. model = models[clientId];
  772.  
  773. if (!model) {
  774. // create a new instance of the model in the
  775. // 'isLoading' state
  776. model = this.createModel(type, clientId);
  777.  
  778. // immediately set its data
  779. model.setData(data[clientId] || null);
  780. }
  781. } else {
  782. clientId = this.pushHash(null, id, type);
  783.  
  784. // create a new instance of the model in the
  785. // 'isLoading' state
  786. model = this.createModel(type, clientId);
  787.  
  788. // let the adapter set the data, possibly async
  789. var adapter = get(this, '_adapter');
  790. if (adapter && adapter.find) { adapter.find(this, type, id); }
  791. else { throw fmt("Adapter is either null or do not implement `find` method", this); }
  792. }
  793.  
  794. return model;
  795. },
  796.  
  797. /** @private
  798. */
  799. findMany: function(type, ids, query) {
  800. var idToClientIdMap = this.idToClientIdMap(type);
  801. var data = this.clientIdToHashMap(type), needed;
  802.  
  803. var clientIds = Ember.A([]);
  804.  
  805. if (ids) {
  806. needed = [];
  807.  
  808. ids.forEach(function(id) {
  809. var clientId = idToClientIdMap[id];
  810. if (clientId === undefined || data[clientId] === undefined) {
  811. clientId = this.pushHash(null, id, type);
  812. needed.push(id);
  813. }
  814.  
  815. clientIds.push(clientId);
  816. }, this);
  817. } else {
  818. needed = null;
  819. }
  820.  
  821. if ((needed && get(needed, 'length') > 0) || query) {
  822. var adapter = get(this, '_adapter');
  823. if (adapter && adapter.findMany) { adapter.findMany(this, type, needed, query); }
  824. else { throw fmt("Adapter is either null or do not implement `findMany` method", this); }
  825. }
  826.  
  827. return this.createModelArray(type, clientIds);
  828. },
  829.  
  830. findQuery: function(type, query) {
  831. var array = DS.AdapterPopulatedModelArray.create({ type: type, content: Ember.A([]), store: this });
  832. var adapter = get(this, '_adapter');
  833. if (adapter && adapter.findQuery) { adapter.findQuery(this, type, query, array); }
  834. else { throw fmt("Adapter is either null or do not implement `findQuery` method", this); }
  835. return array;
  836. },
  837.  
  838. findAll: function(type) {
  839.  
  840. var typeMap = this.typeMapFor(type),
  841. findAllCache = typeMap.findAllCache;
  842.  
  843. if (findAllCache) { return findAllCache; }
  844.  
  845. var array = DS.ModelArray.create({ type: type, content: Ember.A([]), store: this });
  846. this.registerModelArray(array, type);
  847.  
  848. var adapter = get(this, '_adapter');
  849. if (adapter && adapter.findAll) { adapter.findAll(this, type); }
  850.  
  851. typeMap.findAllCache = array;
  852. return array;
  853. },
  854.  
  855. filter: function(type, filter) {
  856. var array = DS.FilteredModelArray.create({ type: type, content: Ember.A([]), store: this, filterFunction: filter });
  857.  
  858. this.registerModelArray(array, type, filter);
  859.  
  860. return array;
  861. },
  862.  
  863. // ............
  864. // . UPDATING .
  865. // ............
  866.  
  867. hashWasUpdated: function(type, clientId) {
  868. var clientIdToHashMap = this.clientIdToHashMap(type);
  869. var hash = clientIdToHashMap[clientId];
  870.  
  871. this.updateModelArrays(type, clientId, hash);
  872. },
  873.  
  874. // ..............
  875. // . PERSISTING .
  876. // ..............
  877.  
  878. commit: function() {
  879. get(this, 'defaultTransaction').commit();
  880. },
  881.  
  882. didUpdateRecords: function(array, hashes) {
  883. if (arguments.length === 2) {
  884. array.forEach(function(model, idx) {
  885. this.didUpdateRecord(model, hashes[idx]);
  886. }, this);
  887. } else {
  888. array.forEach(function(model) {
  889. this.didUpdateRecord(model);
  890. }, this);
  891. }
  892. },
  893.  
  894. didUpdateRecord: function(model, hash) {
  895. if (arguments.length === 2) {
  896. var clientId = get(model, 'clientId');
  897. var data = this.clientIdToHashMap(model.constructor);
  898.  
  899. data[clientId] = hash;
  900. model.set('data', hash);
  901. }
  902.  
  903. model.adapterDidUpdate();
  904. },
  905.  
  906. didDeleteRecords: function(array) {
  907. array.forEach(function(model) {
  908. model.adapterDidDelete();
  909. });
  910. },
  911.  
  912. didDeleteRecord: function(model) {
  913. model.adapterDidDelete();
  914. },
  915.  
  916. didCreateRecords: function(type, array, hashes) {
  917. var id, clientId, primaryKey = getPath(type, 'proto.primaryKey');
  918.  
  919. var idToClientIdMap = this.idToClientIdMap(type);
  920. var data = this.clientIdToHashMap(type);
  921. var idList = this.idList(type);
  922.  
  923. for (var i=0, l=get(array, 'length'); i<l; i++) {
  924. var model = array[i], hash = hashes[i];
  925. id = hash[primaryKey];
  926. clientId = get(model, 'clientId');
  927.  
  928. data[clientId] = hash;
  929. set(model, 'data', hash);
  930.  
  931. idToClientIdMap[id] = clientId;
  932. idList.push(id);
  933.  
  934. model.adapterDidUpdate();
  935. }
  936. },
  937.  
  938. didCreateRecord: function(model, hash) {
  939. var type = model.constructor;
  940.  
  941. var id, clientId, primaryKey = getPath(type, 'proto.primaryKey');
  942.  
  943. var idToClientIdMap = this.idToClientIdMap(type);
  944. var data = this.clientIdToHashMap(type);
  945. var idList = this.idList(type);
  946.  
  947. id = hash[primaryKey];
  948.  
  949. clientId = get(model, 'clientId');
  950. data[clientId] = hash;
  951. set(model, 'data', hash);
  952.  
  953. idToClientIdMap[id] = clientId;
  954. idList.push(id);
  955.  
  956. model.adapterDidUpdate();
  957. },
  958.  
  959. recordWasInvalid: function(record, errors) {
  960. record.wasInvalid(errors);
  961. },
  962.  
  963. // ................
  964. // . MODEL ARRAYS .
  965. // ................
  966.  
  967. registerModelArray: function(array, type, filter) {
  968. var modelArrays = get(this, 'modelArrays');
  969. var idToClientIdMap = this.idToClientIdMap(type);
  970.  
  971. modelArrays.push(array);
  972.  
  973. this.updateModelArrayFilter(array, type, filter);
  974. },
  975.  
  976. createModelArray: function(type, clientIds) {
  977. var array = DS.ModelArray.create({ type: type, content: clientIds, store: this });
  978.  
  979. clientIds.forEach(function(clientId) {
  980. var modelArrays = this.modelArraysForClientId(clientId);
  981. modelArrays.add(array);
  982. }, this);
  983.  
  984. return array;
  985. },
  986.  
  987. updateModelArrayFilter: function(array, type, filter) {
  988. var data = this.clientIdToHashMap(type);
  989. var allClientIds = this.clientIdList(type);
  990.  
  991. for (var i=0, l=allClientIds.length; i<l; i++) {
  992. clientId = allClientIds[i];
  993.  
  994. hash = data[clientId];
  995.  
  996. if (hash) {
  997. this.updateModelArray(array, filter, type, clientId, hash);
  998. }
  999. }
  1000. },
  1001.  
  1002. updateModelArrays: function(type, clientId, hash) {
  1003. var modelArrays = get(this, 'modelArrays');
  1004.  
  1005. modelArrays.forEach(function(array) {
  1006. modelArrayType = get(array, 'type');
  1007. filter = get(array, 'filterFunction');
  1008.  
  1009. if (type !== modelArrayType) { return; }
  1010.  
  1011. this.updateModelArray(array, filter, type, clientId, hash);
  1012. }, this);
  1013. },
  1014.  
  1015. updateModelArray: function(array, filter, type, clientId, hash) {
  1016. var shouldBeInArray;
  1017.  
  1018. if (!filter) {
  1019. shouldBeInArray = true;
  1020. } else {
  1021. shouldBeInArray = filter(hash);
  1022. }
  1023.  
  1024. var content = get(array, 'content');
  1025. var alreadyInArray = content.indexOf(clientId) !== -1;
  1026.  
  1027. var modelArrays = this.modelArraysForClientId(clientId);
  1028.  
  1029. if (shouldBeInArray && !alreadyInArray) {
  1030. modelArrays.add(array);
  1031. content.pushObject(clientId);
  1032. } else if (!shouldBeInArray && alreadyInArray) {
  1033. modelArrays.remove(array);
  1034. content.removeObject(clientId);
  1035. }
  1036. },
  1037.  
  1038. removeFromModelArrays: function(model) {
  1039. var clientId = get(model, 'clientId');
  1040. var modelArrays = this.modelArraysForClientId(clientId);
  1041.  
  1042. modelArrays.forEach(function(array) {
  1043. var content = get(array, 'content');
  1044. content.removeObject(clientId);
  1045. });
  1046. },
  1047.  
  1048. // ............
  1049. // . TYPE MAP .
  1050. // ............
  1051.  
  1052. typeMapFor: function(type) {
  1053. var ids = get(this, '_typeMap');
  1054. var guidForType = Ember.guidFor(type);
  1055.  
  1056. var typeMap = ids[guidForType];
  1057.  
  1058. if (typeMap) {
  1059. return typeMap;
  1060. } else {
  1061. return (ids[guidForType] =
  1062. {
  1063. idToCid: {},
  1064. idList: [],
  1065. cidList: [],
  1066. cidToHash: {}
  1067. });
  1068. }
  1069. },
  1070.  
  1071. idToClientIdMap: function(type) {
  1072. return this.typeMapFor(type).idToCid;
  1073. },
  1074.  
  1075. idList: function(type) {
  1076. return this.typeMapFor(type).idList;
  1077. },
  1078.  
  1079. clientIdList: function(type) {
  1080. return this.typeMapFor(type).cidList;
  1081. },
  1082.  
  1083. clientIdToHashMap: function(type) {
  1084. return this.typeMapFor(type).cidToHash;
  1085. },
  1086.  
  1087. /** @private
  1088.  
  1089. For a given type and id combination, returns the client id used by the store.
  1090. If no client id has been assigned yet, `undefined` is returned.
  1091.  
  1092. @param {DS.Model} type
  1093. @param {String|Number} id
  1094. */
  1095. clientIdForId: function(type, id) {
  1096. return this.typeMapFor(type).idToCid[id];
  1097. },
  1098.  
  1099. idForHash: function(type, hash) {
  1100. var primaryKey = getPath(type, 'proto.primaryKey');
  1101.  
  1102. ember_assert("A data hash was loaded for a model of type " + type.toString() + " but no primary key '" + primaryKey + "' was provided.", !!hash[primaryKey]);
  1103. return hash[primaryKey];
  1104. },
  1105.  
  1106. // ................
  1107. // . LOADING DATA .
  1108. // ................
  1109.  
  1110. /**
  1111. Load a new data hash into the store for a given id and type combination.
  1112. If data for that model had been loaded previously, the new information
  1113. overwrites the old.
  1114.  
  1115. If the model you are loading data for has outstanding changes that have not
  1116. yet been saved, an exception will be thrown.
  1117.  
  1118. @param {DS.Model} type
  1119. @param {String|Number} id
  1120. @param {Object} hash the data hash to load
  1121. */
  1122. load: function(type, id, hash) {
  1123. if (hash === undefined) {
  1124. hash = id;
  1125. var primaryKey = getPath(type, 'proto.primaryKey');
  1126. ember_assert("A data hash was loaded for a model of type " + type.toString() + " but no primary key '" + primaryKey + "' was provided.", !!hash[primaryKey]);
  1127. id = hash[primaryKey];
  1128. }
  1129.  
  1130. var data = this.clientIdToHashMap(type);
  1131. var models = get(this, 'models');
  1132.  
  1133. var clientId = this.clientIdForId(type, id);
  1134.  
  1135. if (clientId !== undefined) {
  1136. data[clientId] = hash;
  1137.  
  1138. var model = models[clientId];
  1139. if (model) {
  1140. model.willLoadData();
  1141. model.setData(hash);
  1142. }
  1143. } else {
  1144. clientId = this.pushHash(hash, id, type);
  1145. }
  1146.  
  1147. this.updateModelArrays(type, clientId, hash);
  1148.  
  1149. return { id: id, clientId: clientId };
  1150. },
  1151.  
  1152. loadMany: function(type, ids, hashes) {
  1153. var clientIds = Ember.A([]);
  1154.  
  1155. if (hashes === undefined) {
  1156. hashes = ids;
  1157. ids = [];
  1158. var primaryKey = getPath(type, 'proto.primaryKey');
  1159.  
  1160. ids = hashes.map(function(hash) {
  1161. ember_assert("A data hash was loaded for a model of type " + type.toString() + " but no primary key '" + primaryKey + "' was provided.", !!hash[primaryKey]);
  1162. return hash[primaryKey];
  1163. });
  1164. }
  1165.  
  1166. for (var i=0, l=get(ids, 'length'); i<l; i++) {
  1167. var loaded = this.load(type, ids[i], hashes[i]);
  1168. clientIds.pushObject(loaded.clientId);
  1169. }
  1170.  
  1171. return { clientIds: clientIds, ids: ids };
  1172. },
  1173.  
  1174. /** @private
  1175.  
  1176. Stores a data hash for the specified type and id combination and returns
  1177. the client id.
  1178.  
  1179. @param {Object} hash
  1180. @param {String|Number} id
  1181. @param {DS.Model} type
  1182. @returns {Number}
  1183. */
  1184. pushHash: function(hash, id, type) {
  1185. var idToClientIdMap = this.idToClientIdMap(type);
  1186. var clientIdList = this.clientIdList(type);
  1187. var idList = this.idList(type);
  1188. var data = this.clientIdToHashMap(type);
  1189.  
  1190. var clientId = this.incrementProperty('clientIdCounter');
  1191.  
  1192. data[clientId] = hash;
  1193.  
  1194. // if we're creating an item, this process will be done
  1195. // later, once the object has been persisted.
  1196. if (id) {
  1197. idToClientIdMap[id] = clientId;
  1198. idList.push(id);
  1199. }
  1200.  
  1201. clientIdList.push(clientId);
  1202.  
  1203. return clientId;
  1204. },
  1205.  
  1206. // .........................
  1207. // . MODEL MATERIALIZATION .
  1208. // .........................
  1209.  
  1210. createModel: function(type, clientId) {
  1211. var model;
  1212.  
  1213. get(this, 'models')[clientId] = model = type.create({ store: this, clientId: clientId });
  1214. set(model, 'clientId', clientId);
  1215. model.loadingData();
  1216. return model;
  1217. }
  1218. });
  1219.  
  1220.  
  1221. })({});
  1222.  
  1223.  
  1224. (function(exports) {
  1225. var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
  1226.  
  1227. var stateProperty = Ember.computed(function(key) {
  1228. var parent = get(this, 'parentState');
  1229. if (parent) {
  1230. return get(parent, key);
  1231. }
  1232. }).property();
  1233.  
  1234. DS.State = Ember.State.extend({
  1235. isLoaded: stateProperty,
  1236. isDirty: stateProperty,
  1237. isSaving: stateProperty,
  1238. isDeleted: stateProperty,
  1239. isError: stateProperty,
  1240. isNew: stateProperty,
  1241. isValid: stateProperty
  1242. });
  1243.  
  1244. var cantLoadData = function() {
  1245. // TODO: get the current state name
  1246. throw "You cannot load data into the store when its associated model is in its current state";
  1247. };
  1248.  
  1249. var isEmptyObject = function(obj) {
  1250. for (var prop in obj) {
  1251. if (!obj.hasOwnProperty(prop)) { continue; }
  1252. return false;
  1253. }
  1254.  
  1255. return true;
  1256. };
  1257.  
  1258. var setProperty = function(manager, context) {
  1259. var key = context.key, value = context.value;
  1260.  
  1261. var model = get(manager, 'model'), type = model.constructor;
  1262. var store = get(model, 'store');
  1263. var data = get(model, 'data');
  1264.  
  1265. data[key] = value;
  1266.  
  1267. if (store) { store.hashWasUpdated(type, get(model, 'clientId')); }
  1268. };
  1269.  
  1270. // several states share extremely common functionality, so we are factoring
  1271. // them out into a common class.
  1272. var DirtyState = DS.State.extend({
  1273. // these states are virtually identical except that
  1274. // they (thrice) use their states name explicitly.
  1275. //
  1276. // child classes implement stateName.
  1277. stateName: null,
  1278. isDirty: true,
  1279. willLoadData: cantLoadData,
  1280.  
  1281. enter: function(manager) {
  1282. var stateName = get(this, 'stateName'),
  1283. model = get(manager, 'model');
  1284.  
  1285. model.withTransaction(function (t) {
  1286. t.modelBecameDirty(stateName, model);
  1287. });
  1288. },
  1289.  
  1290. exit: function(manager) {
  1291. var stateName = get(this, 'stateName'),
  1292. model = get(manager, 'model');
  1293.  
  1294. this.notifyModel(model);
  1295.  
  1296. model.withTransaction(function (t) {
  1297. t.modelBecameClean(stateName, model);
  1298. });
  1299. },
  1300.  
  1301. setProperty: setProperty,
  1302.  
  1303. willCommit: function(manager) {
  1304. manager.goToState('saving');
  1305. },
  1306.  
  1307. saving: DS.State.extend({
  1308. isSaving: true,
  1309.  
  1310. didUpdate: function(manager) {
  1311. manager.goToState('loaded');
  1312. },
  1313.  
  1314. wasInvalid: function(manager, errors) {
  1315. var model = get(manager, 'model');
  1316.  
  1317. set(model, 'errors', errors);
  1318. manager.goToState('invalid');
  1319. }
  1320. }),
  1321.  
  1322. invalid: DS.State.extend({
  1323. isValid: false,
  1324.  
  1325. setProperty: function(manager, context) {
  1326. setProperty(manager, context);
  1327.  
  1328. var stateName = getPath(this, 'parentState.stateName'),
  1329. model = get(manager, 'model'),
  1330. errors = get(model, 'errors'),
  1331. key = context.key;
  1332.  
  1333. delete errors[key];
  1334.  
  1335. if (isEmptyObject(errors)) {
  1336. manager.goToState(stateName);
  1337. }
  1338. }
  1339. })
  1340. });
  1341.  
  1342. var states = {
  1343. rootState: Ember.State.create({
  1344. isLoaded: false,
  1345. isDirty: false,
  1346. isSaving: false,
  1347. isDeleted: false,
  1348. isError: false,
  1349. isNew: false,
  1350. isValid: true,
  1351.  
  1352. willLoadData: cantLoadData,
  1353.  
  1354. didCreate: function(manager) {
  1355. manager.goToState('loaded.created');
  1356. },
  1357.  
  1358. empty: DS.State.create({
  1359. loadingData: function(manager) {
  1360. manager.goToState('loading');
  1361. }
  1362. }),
  1363.  
  1364. loading: DS.State.create({
  1365. willLoadData: Ember.K,
  1366.  
  1367. exit: function(manager) {
  1368. var model = get(manager, 'model');
  1369. model.didLoad();
  1370. },
  1371.  
  1372. setData: function(manager, data) {
  1373. var model = get(manager, 'model');
  1374.  
  1375. model.beginPropertyChanges();
  1376. model.set('data', data);
  1377.  
  1378. if (data !== null) {
  1379. manager.goToState('loaded');
  1380. }
  1381.  
  1382. model.endPropertyChanges();
  1383. }
  1384. }),
  1385.  
  1386. loaded: DS.State.create({
  1387. isLoaded: true,
  1388.  
  1389. willLoadData: Ember.K,
  1390.  
  1391. setProperty: function(manager, context) {
  1392. setProperty(manager, context);
  1393. manager.goToState('updated');
  1394. },
  1395.  
  1396. 'delete': function(manager) {
  1397. manager.goToState('deleted');
  1398. },
  1399.  
  1400. created: DirtyState.create({
  1401. stateName: 'created',
  1402. isNew: true,
  1403.  
  1404. notifyModel: function(model) {
  1405. model.didCreate();
  1406. }
  1407. }),
  1408.  
  1409. updated: DirtyState.create({
  1410. stateName: 'updated',
  1411.  
  1412. notifyModel: function(model) {
  1413. model.didUpdate();
  1414. }
  1415. })
  1416. }),
  1417.  
  1418. deleted: DS.State.create({
  1419. isDeleted: true,
  1420. isLoaded: true,
  1421. isDirty: true,
  1422.  
  1423. willLoadData: cantLoadData,
  1424.  
  1425. enter: function(manager) {
  1426. var model = get(manager, 'model');
  1427. var store = get(model, 'store');
  1428.  
  1429. if (store) {
  1430. store.removeFromModelArrays(model);
  1431. }
  1432.  
  1433. model.withTransaction(function(t) {
  1434. t.modelBecameDirty('deleted', model);
  1435. });
  1436. },
  1437.  
  1438. willCommit: function(manager) {
  1439. manager.goToState('saving');
  1440. },
  1441.  
  1442. saving: DS.State.create({
  1443. isSaving: true,
  1444.  
  1445. didDelete: function(manager) {
  1446. manager.goToState('saved');
  1447. },
  1448.  
  1449. exit: function(stateManager) {
  1450. var model = get(stateManager, 'model');
  1451.  
  1452. model.withTransaction(function(t) {
  1453. t.modelBecameClean('deleted', model);
  1454. });
  1455. }
  1456. }),
  1457.  
  1458. saved: DS.State.create({
  1459. isDirty: false
  1460. })
  1461. }),
  1462.  
  1463. error: DS.State.create({
  1464. isError: true
  1465. })
  1466. })
  1467. };
  1468.  
  1469. DS.StateManager = Ember.StateManager.extend({
  1470. model: null,
  1471. initialState: 'rootState',
  1472. states: states
  1473. });
  1474.  
  1475. var retrieveFromCurrentState = Ember.computed(function(key) {
  1476. return get(getPath(this, 'stateManager.currentState'), key);
  1477. }).property('stateManager.currentState').cacheable();
  1478.  
  1479. DS.Model = Ember.Object.extend({
  1480. isLoaded: retrieveFromCurrentState,
  1481. isDirty: retrieveFromCurrentState,
  1482. isSaving: retrieveFromCurrentState,
  1483. isDeleted: retrieveFromCurrentState,
  1484. isError: retrieveFromCurrentState,
  1485. isNew: retrieveFromCurrentState,
  1486. isValid: retrieveFromCurrentState,
  1487.  
  1488. clientId: null,
  1489.  
  1490. // because unknownProperty is used, any internal property
  1491. // must be initialized here.
  1492. primaryKey: 'id',
  1493. data: null,
  1494. transaction: null,
  1495.  
  1496. didLoad: Ember.K,
  1497. didUpdate: Ember.K,
  1498. didCreate: Ember.K,
  1499.  
  1500. init: function() {
  1501. var stateManager = DS.StateManager.create({
  1502. model: this
  1503. });
  1504.  
  1505. set(this, 'stateManager', stateManager);
  1506. stateManager.goToState('empty');
  1507. },
  1508.  
  1509. withTransaction: function(fn) {
  1510. var transaction = get(this, 'transaction') || getPath(this, 'store.defaultTransaction');
  1511.  
  1512. if (transaction) { fn(transaction); }
  1513. },
  1514.  
  1515. setData: function(data) {
  1516. var stateManager = get(this, 'stateManager');
  1517. stateManager.send('setData', data);
  1518. },
  1519.  
  1520. setProperty: function(key, value) {
  1521. var stateManager = get(this, 'stateManager');
  1522. stateManager.send('setProperty', { key: key, value: value });
  1523. },
  1524.  
  1525. deleteRecord: function() {
  1526. var stateManager = get(this, 'stateManager');
  1527. stateManager.send('delete');
  1528. },
  1529.  
  1530. destroy: function() {
  1531. this.deleteRecord();
  1532. this._super();
  1533. },
  1534.  
  1535. loadingData: function() {
  1536. var stateManager = get(this, 'stateManager');
  1537. stateManager.send('loadingData');
  1538. },
  1539.  
  1540. willLoadData: function() {
  1541. var stateManager = get(this, 'stateManager');
  1542. stateManager.send('willLoadData');
  1543. },
  1544.  
  1545. willCommit: function() {
  1546. var stateManager = get(this, 'stateManager');
  1547. stateManager.send('willCommit');
  1548. },
  1549.  
  1550. adapterDidUpdate: function() {
  1551. var stateManager = get(this, 'stateManager');
  1552. stateManager.send('didUpdate');
  1553. },
  1554.  
  1555. adapterDidCreate: function() {
  1556. var stateManager = get(this, 'stateManager');
  1557. stateManager.send('didCreate');
  1558. },
  1559.  
  1560. adapterDidDelete: function() {
  1561. var stateManager = get(this, 'stateManager');
  1562. stateManager.send('didDelete');
  1563. },
  1564.  
  1565. wasInvalid: function(errors) {
  1566. var stateManager = get(this, 'stateManager');
  1567. stateManager.send('wasInvalid', errors);
  1568. },
  1569.  
  1570. unknownProperty: function(key) {
  1571. var data = get(this, 'data');
  1572.  
  1573. if (data) {
  1574. return get(data, key);
  1575. }
  1576. },
  1577.  
  1578. setUnknownProperty: function(key, value) {
  1579. var data = get(this, 'data');
  1580. ember_assert("You cannot set a model attribute before its data is loaded.", !!data);
  1581.  
  1582. this.setProperty(key, value);
  1583. return value;
  1584. }
  1585. });
  1586.  
  1587. DS.Model.reopenClass({
  1588. typeForAssociation: function(association) {
  1589. var type = this.metaForProperty(association).type;
  1590. if (typeof type === 'string') {
  1591. type = getPath(this, type, false) || getPath(window, type);
  1592. }
  1593. return type;
  1594. }
  1595. });
  1596.  
  1597. DS.attr = function(type, options) {
  1598. var transform = DS.attr.transforms[type];
  1599. var transformFrom = transform.from;
  1600. var transformTo = transform.to;
  1601.  
  1602. return Ember.computed(function(key, value) {
  1603. var data = get(this, 'data');
  1604.  
  1605. key = (options && options.key) ? options.key : key;
  1606.  
  1607. if (value === undefined) {
  1608. if (!data) { return; }
  1609.  
  1610. return transformFrom(data[key]);
  1611. } else {
  1612. ember_assert("You cannot set a model attribute before its data is loaded.", !!data);
  1613.  
  1614. value = transformTo(value);
  1615. this.setProperty(key, value);
  1616. return value;
  1617. }
  1618. }).property('data');
  1619. };
  1620.  
  1621. var embeddedFindRecord = function(store, type, data, key, one) {
  1622. var association = data ? get(data, key) : one ? null : [];
  1623. if (one) {
  1624. return association ? store.load(type, association).id : null;
  1625. } else {
  1626. return association ? store.loadMany(type, association).ids : [];
  1627. }
  1628. };
  1629.  
  1630. var referencedFindRecord = function(store, type, data, key, one) {
  1631. return data ? get(data, key) : one ? null : [];
  1632. };
  1633.  
  1634. var hasAssociation = function(type, options, one) {
  1635. var embedded = options && options.embedded,
  1636. findRecord = embedded ? embeddedFindRecord : referencedFindRecord;
  1637.  
  1638. return Ember.computed(function(key) {
  1639. var data = get(this, 'data'), ids, id, association,
  1640. store = get(this, 'store');
  1641.  
  1642. if (typeof type === 'string') {
  1643. type = getPath(this, type, false) || getPath(window, type);
  1644. }
  1645.  
  1646. key = (options && options.key) ? options.key : key;
  1647. if (one) {
  1648. id = findRecord(store, type, data, key, true);
  1649. association = id ? store.find(type, id) : null;
  1650. } else {
  1651. ids = findRecord(store, type, data, key);
  1652. association = store.findMany(type, ids);
  1653. }
  1654.  
  1655. return association;
  1656. }).property('data').cacheable().meta({ type: type });
  1657. };
  1658.  
  1659. DS.hasMany = function(type, options) {
  1660. ember_assert("The type passed to DS.hasMany must be defined", !!type);
  1661. return hasAssociation(type, options);
  1662. };
  1663.  
  1664. DS.hasOne = function(type, options) {
  1665. ember_assert("The type passed to DS.hasOne must be defined", !!type);
  1666. return hasAssociation(type, options, true);
  1667. };
  1668.  
  1669. DS.attr.transforms = {
  1670. string: {
  1671. from: function(serialized) {
  1672. return Em.none(serialized) ? null : String(serialized);
  1673. },
  1674.  
  1675. to: function(deserialized) {
  1676. return Em.none(deserialized) ? null : String(deserialized);
  1677. }
  1678. },
  1679.  
  1680. integer: {
  1681. from: function(serialized) {
  1682. return Em.none(serialized) ? null : Number(serialized);
  1683. },
  1684.  
  1685. to: function(deserialized) {
  1686. return Em.none(deserialized) ? null : Number(deserialized);
  1687. }
  1688. },
  1689.  
  1690. boolean: {
  1691. from: function(serialized) {
  1692. return Boolean(serialized);
  1693. },
  1694.  
  1695. to: function(deserialized) {
  1696. return Boolean(deserialized);
  1697. }
  1698. },
  1699.  
  1700. date: {
  1701. from: function(serialized) {
  1702. var type = typeof serialized;
  1703.  
  1704. if (type === "string" || type === "number") {
  1705. return new Date(serialized);
  1706. } else if (serialized === null || serialized === undefined) {
  1707. // if the value is not present in the data,
  1708. // return undefined, not null.
  1709. return serialized;
  1710. } else {
  1711. return null;
  1712. }
  1713. },
  1714.  
  1715. to: function(date) {
  1716. if (date instanceof Date) {
  1717. var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  1718. var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  1719.  
  1720. var pad = function(num) {
  1721. return num < 10 ? "0"+num : ""+num;
  1722. };
  1723.  
  1724. var utcYear = date.getUTCFullYear(),
  1725. utcMonth = date.getUTCMonth(),
  1726. utcDayOfMonth = date.getUTCDate(),
  1727. utcDay = date.getUTCDay(),
  1728. utcHours = date.getUTCHours(),
  1729. utcMinutes = date.getUTCMinutes(),
  1730. utcSeconds = date.getUTCSeconds();
  1731.  
  1732.  
  1733. var dayOfWeek = days[utcDay];
  1734. var dayOfMonth = pad(utcDayOfMonth);
  1735. var month = months[utcMonth];
  1736.  
  1737. return dayOfWeek + ", " + dayOfMonth + " " + month + " " + utcYear + " " +
  1738. pad(utcHours) + ":" + pad(utcMinutes) + ":" + pad(utcSeconds) + " GMT";
  1739. } else if (date === undefined) {
  1740. return undefined;
  1741. } else {
  1742. return null;
  1743. }
  1744. }
  1745. }
  1746. };
  1747.  
  1748. })({});
  1749.  
  1750.  
  1751. (function(exports) {
  1752. //Copyright (C) 2011 by Living Social, Inc.
  1753.  
  1754. //Permission is hereby granted, free of charge, to any person obtaining a copy of
  1755. //this software and associated documentation files (the "Software"), to deal in
  1756. //the Software without restriction, including without limitation the rights to
  1757. //use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  1758. //of the Software, and to permit persons to whom the Software is furnished to do
  1759. //so, subject to the following conditions:
  1760.  
  1761. //The above copyright notice and this permission notice shall be included in all
  1762. //copies or substantial portions of the Software.
  1763.  
  1764. //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1765. //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1766. //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1767. //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  1768. //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  1769. //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  1770. //SOFTWARE.
  1771. })({});
Add Comment
Please, Sign In to add comment