extjs-mvc 0.4.0.j → 0.4.0.k

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. data/Rakefile +1 -1
  2. data/VERSION +1 -1
  3. data/lib/extjs-mvc.rb +0 -14
  4. data/lib/extjs-mvc/api.rb +14 -27
  5. data/lib/extjs-mvc/src/App.js +219 -0
  6. data/lib/extjs-mvc/src/MVC.js +260 -0
  7. data/lib/extjs-mvc/src/Presenter.js +52 -0
  8. data/lib/extjs-mvc/src/README.rdoc +69 -0
  9. data/lib/extjs-mvc/src/controller/Controller.js +278 -0
  10. data/lib/extjs-mvc/src/controller/CrudController.js +460 -0
  11. data/lib/extjs-mvc/src/lib/Array.js +26 -0
  12. data/lib/extjs-mvc/src/lib/Booter.js +417 -0
  13. data/lib/extjs-mvc/src/lib/ClassManager.js +191 -0
  14. data/lib/extjs-mvc/src/lib/ControllerClassManager.js +95 -0
  15. data/lib/extjs-mvc/src/lib/Dependencies.js +44 -0
  16. data/lib/extjs-mvc/src/lib/DispatchMatcher.js +98 -0
  17. data/lib/extjs-mvc/src/lib/Dispatcher.js +129 -0
  18. data/lib/extjs-mvc/src/lib/Environment.js +43 -0
  19. data/lib/extjs-mvc/src/lib/Inflector.js +155 -0
  20. data/lib/extjs-mvc/src/lib/ModelClassManager.js +19 -0
  21. data/lib/extjs-mvc/src/lib/Route.js +139 -0
  22. data/lib/extjs-mvc/src/lib/Router.js +282 -0
  23. data/lib/extjs-mvc/src/lib/String.js +94 -0
  24. data/lib/extjs-mvc/src/lib/ViewClassManager.js +229 -0
  25. data/lib/extjs-mvc/src/lib/notes.txt +32 -0
  26. data/lib/extjs-mvc/src/model/AdapterManager.js +30 -0
  27. data/lib/extjs-mvc/src/model/Association.js +26 -0
  28. data/lib/extjs-mvc/src/model/Base.js +63 -0
  29. data/lib/extjs-mvc/src/model/BelongsToAssociation.js +116 -0
  30. data/lib/extjs-mvc/src/model/Cache.js +131 -0
  31. data/lib/extjs-mvc/src/model/HasManyAssociation.js +160 -0
  32. data/lib/extjs-mvc/src/model/Model.js +331 -0
  33. data/lib/extjs-mvc/src/model/UrlBuilder.js +106 -0
  34. data/lib/extjs-mvc/src/model/adapters/AbstractAdapter.js +296 -0
  35. data/lib/extjs-mvc/src/model/adapters/MemoryAdapter.js +103 -0
  36. data/lib/extjs-mvc/src/model/adapters/RESTAdapter.js +345 -0
  37. data/lib/extjs-mvc/src/model/adapters/RESTJSONAdapter.js +68 -0
  38. data/lib/extjs-mvc/src/model/adapters/notes.txt +42 -0
  39. data/lib/extjs-mvc/src/model/associations/Association.js +192 -0
  40. data/lib/extjs-mvc/src/model/associations/notes.txt +87 -0
  41. data/lib/extjs-mvc/src/model/validations/Errors.js +136 -0
  42. data/lib/extjs-mvc/src/model/validations/Plugin.js +139 -0
  43. data/lib/extjs-mvc/src/model/validations/Validations.js +276 -0
  44. data/lib/extjs-mvc/src/notes/Charts.graffle +0 -0
  45. data/lib/extjs-mvc/src/overrides/Ext.Component.js +21 -0
  46. data/lib/extjs-mvc/src/overrides/Ext.extend.js +142 -0
  47. data/lib/extjs-mvc/src/spec/Array.spec.js +15 -0
  48. data/lib/extjs-mvc/src/spec/ExtMVC.spec.js +65 -0
  49. data/lib/extjs-mvc/src/spec/Model.spec.js +370 -0
  50. data/lib/extjs-mvc/src/spec/OS.spec.js +83 -0
  51. data/lib/extjs-mvc/src/spec/Router.spec.js +99 -0
  52. data/lib/extjs-mvc/src/spec/SpecHelper.js +106 -0
  53. data/lib/extjs-mvc/src/spec/String.spec.js +83 -0
  54. data/lib/extjs-mvc/src/spec/model/AbstractAdapter.spec.js +49 -0
  55. data/lib/extjs-mvc/src/spec/model/Associations.spec.js +99 -0
  56. data/lib/extjs-mvc/src/spec/model/Cache.spec.js +5 -0
  57. data/lib/extjs-mvc/src/spec/model/RESTAdapter.spec.js +19 -0
  58. data/lib/extjs-mvc/src/spec/model/ValidationErrors.spec.js +64 -0
  59. data/lib/extjs-mvc/src/spec/model/Validations.spec.js +166 -0
  60. data/lib/extjs-mvc/src/spec/model/ValidationsPlugin.spec.js +108 -0
  61. data/lib/extjs-mvc/src/spec/suite.html +60 -0
  62. data/lib/extjs-mvc/src/specs-old/JSSpec.css +216 -0
  63. data/lib/extjs-mvc/src/specs-old/JSSpec.js +1512 -0
  64. data/lib/extjs-mvc/src/specs-old/all.html +66 -0
  65. data/lib/extjs-mvc/src/specs-old/base.js +14 -0
  66. data/lib/extjs-mvc/src/specs-old/controller.js +17 -0
  67. data/lib/extjs-mvc/src/specs-old/diff_match_patch.js +1 -0
  68. data/lib/extjs-mvc/src/specs-old/model.js +70 -0
  69. data/lib/extjs-mvc/src/specs-old/route.js +38 -0
  70. data/lib/extjs-mvc/src/specs-old/router.js +59 -0
  71. data/lib/extjs-mvc/src/specs-old/string.js +22 -0
  72. data/lib/extjs-mvc/src/testrunner/JSpecFormatter.js +111 -0
  73. data/lib/extjs-mvc/src/testrunner/TestClient.js +181 -0
  74. data/lib/extjs-mvc/src/testrunner/TestGrid.js +351 -0
  75. data/lib/extjs-mvc/src/testrunner/TestRunner.js +110 -0
  76. data/lib/extjs-mvc/src/testrunner/TestViewport.js +94 -0
  77. data/lib/extjs-mvc/src/vendor.yml +30 -0
  78. data/lib/extjs-mvc/src/vendor/ext-3.1.1/vendor.yml +16 -0
  79. data/lib/extjs-mvc/src/view/FormWindow.js +184 -0
  80. data/lib/extjs-mvc/src/view/HasManyEditorGridPanel.js +211 -0
  81. data/lib/extjs-mvc/src/view/scaffold/Edit.js +46 -0
  82. data/lib/extjs-mvc/src/view/scaffold/Index.js +561 -0
  83. data/lib/extjs-mvc/src/view/scaffold/New.js +20 -0
  84. data/lib/extjs-mvc/src/view/scaffold/ScaffoldFormPanel.js +255 -0
  85. data/lib/{vendor.yml → extjs-mvc/vendor.yml} +0 -0
  86. data/test/app/vendor/extjs-mvc/App.js +219 -0
  87. data/test/app/vendor/extjs-mvc/MVC.js +260 -0
  88. data/test/app/vendor/extjs-mvc/Presenter.js +52 -0
  89. data/test/app/vendor/extjs-mvc/README.rdoc +69 -0
  90. data/test/app/vendor/extjs-mvc/controller/Controller.js +278 -0
  91. data/test/app/vendor/extjs-mvc/controller/CrudController.js +460 -0
  92. data/test/app/vendor/extjs-mvc/lib/Array.js +26 -0
  93. data/test/app/vendor/extjs-mvc/lib/Booter.js +417 -0
  94. data/test/app/vendor/extjs-mvc/lib/ClassManager.js +191 -0
  95. data/test/app/vendor/extjs-mvc/lib/ControllerClassManager.js +95 -0
  96. data/test/app/vendor/extjs-mvc/lib/Dependencies.js +44 -0
  97. data/test/app/vendor/extjs-mvc/lib/DispatchMatcher.js +98 -0
  98. data/test/app/vendor/extjs-mvc/lib/Dispatcher.js +129 -0
  99. data/test/app/vendor/extjs-mvc/lib/Environment.js +43 -0
  100. data/test/app/vendor/extjs-mvc/lib/Inflector.js +155 -0
  101. data/test/app/vendor/extjs-mvc/lib/ModelClassManager.js +19 -0
  102. data/test/app/vendor/extjs-mvc/lib/Route.js +139 -0
  103. data/test/app/vendor/extjs-mvc/lib/Router.js +282 -0
  104. data/test/app/vendor/extjs-mvc/lib/String.js +94 -0
  105. data/test/app/vendor/extjs-mvc/lib/ViewClassManager.js +229 -0
  106. data/test/app/vendor/extjs-mvc/lib/notes.txt +32 -0
  107. data/test/app/vendor/extjs-mvc/model/AdapterManager.js +30 -0
  108. data/test/app/vendor/extjs-mvc/model/Association.js +26 -0
  109. data/test/app/vendor/extjs-mvc/model/Base.js +63 -0
  110. data/test/app/vendor/extjs-mvc/model/BelongsToAssociation.js +116 -0
  111. data/test/app/vendor/extjs-mvc/model/Cache.js +131 -0
  112. data/test/app/vendor/extjs-mvc/model/HasManyAssociation.js +160 -0
  113. data/test/app/vendor/extjs-mvc/model/Model.js +331 -0
  114. data/test/app/vendor/extjs-mvc/model/UrlBuilder.js +106 -0
  115. data/test/app/vendor/extjs-mvc/model/adapters/AbstractAdapter.js +296 -0
  116. data/test/app/vendor/extjs-mvc/model/adapters/MemoryAdapter.js +103 -0
  117. data/test/app/vendor/extjs-mvc/model/adapters/RESTAdapter.js +345 -0
  118. data/test/app/vendor/extjs-mvc/model/adapters/RESTJSONAdapter.js +68 -0
  119. data/test/app/vendor/extjs-mvc/model/adapters/notes.txt +42 -0
  120. data/test/app/vendor/extjs-mvc/model/associations/Association.js +192 -0
  121. data/test/app/vendor/extjs-mvc/model/associations/notes.txt +87 -0
  122. data/test/app/vendor/extjs-mvc/model/validations/Errors.js +136 -0
  123. data/test/app/vendor/extjs-mvc/model/validations/Plugin.js +139 -0
  124. data/test/app/vendor/extjs-mvc/model/validations/Validations.js +276 -0
  125. data/test/app/vendor/extjs-mvc/notes/Charts.graffle +0 -0
  126. data/test/app/vendor/extjs-mvc/overrides/Ext.Component.js +21 -0
  127. data/test/app/vendor/extjs-mvc/overrides/Ext.extend.js +142 -0
  128. data/test/app/vendor/extjs-mvc/spec/Array.spec.js +15 -0
  129. data/test/app/vendor/extjs-mvc/spec/ExtMVC.spec.js +65 -0
  130. data/test/app/vendor/extjs-mvc/spec/Model.spec.js +370 -0
  131. data/test/app/vendor/extjs-mvc/spec/OS.spec.js +83 -0
  132. data/test/app/vendor/extjs-mvc/spec/Router.spec.js +99 -0
  133. data/test/app/vendor/extjs-mvc/spec/SpecHelper.js +106 -0
  134. data/test/app/vendor/extjs-mvc/spec/String.spec.js +83 -0
  135. data/test/app/vendor/extjs-mvc/spec/model/AbstractAdapter.spec.js +49 -0
  136. data/test/app/vendor/extjs-mvc/spec/model/Associations.spec.js +99 -0
  137. data/test/app/vendor/extjs-mvc/spec/model/Cache.spec.js +5 -0
  138. data/test/app/vendor/extjs-mvc/spec/model/RESTAdapter.spec.js +19 -0
  139. data/test/app/vendor/extjs-mvc/spec/model/ValidationErrors.spec.js +64 -0
  140. data/test/app/vendor/extjs-mvc/spec/model/Validations.spec.js +166 -0
  141. data/test/app/vendor/extjs-mvc/spec/model/ValidationsPlugin.spec.js +108 -0
  142. data/test/app/vendor/extjs-mvc/spec/suite.html +60 -0
  143. data/test/app/vendor/extjs-mvc/specs-old/JSSpec.css +216 -0
  144. data/test/app/vendor/extjs-mvc/specs-old/JSSpec.js +1512 -0
  145. data/test/app/vendor/extjs-mvc/specs-old/all.html +66 -0
  146. data/test/app/vendor/extjs-mvc/specs-old/base.js +14 -0
  147. data/test/app/vendor/extjs-mvc/specs-old/controller.js +17 -0
  148. data/test/app/vendor/extjs-mvc/specs-old/diff_match_patch.js +1 -0
  149. data/test/app/vendor/extjs-mvc/specs-old/model.js +70 -0
  150. data/test/app/vendor/extjs-mvc/specs-old/route.js +38 -0
  151. data/test/app/vendor/extjs-mvc/specs-old/router.js +59 -0
  152. data/test/app/vendor/extjs-mvc/specs-old/string.js +22 -0
  153. data/test/app/vendor/extjs-mvc/testrunner/JSpecFormatter.js +111 -0
  154. data/test/app/vendor/extjs-mvc/testrunner/TestClient.js +181 -0
  155. data/test/app/vendor/extjs-mvc/testrunner/TestGrid.js +351 -0
  156. data/test/app/vendor/extjs-mvc/testrunner/TestRunner.js +110 -0
  157. data/test/app/vendor/extjs-mvc/testrunner/TestViewport.js +94 -0
  158. data/test/app/vendor/extjs-mvc/vendor.yml +30 -0
  159. data/test/app/vendor/extjs-mvc/vendor/ext-3.1.1/vendor.yml +16 -0
  160. data/test/app/vendor/extjs-mvc/view/FormWindow.js +184 -0
  161. data/test/app/vendor/extjs-mvc/view/HasManyEditorGridPanel.js +211 -0
  162. data/test/app/vendor/extjs-mvc/view/scaffold/Edit.js +46 -0
  163. data/test/app/vendor/extjs-mvc/view/scaffold/Index.js +561 -0
  164. data/test/app/vendor/extjs-mvc/view/scaffold/New.js +20 -0
  165. data/test/app/vendor/extjs-mvc/view/scaffold/ScaffoldFormPanel.js +255 -0
  166. data/test/helper.rb +7 -1
  167. data/test/test_extjs-mvc.rb +46 -0
  168. metadata +167 -7
  169. data/test/test_extjs-mvc-gem.rb +0 -7
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @class ExtMVC.UrlBuilder
3
+ * Builds URLs...
4
+ */
5
+ ExtMVC.UrlBuilder = function() {
6
+
7
+ };
8
+
9
+ ExtMVC.UrlBuilder.prototype = {
10
+
11
+ /**
12
+ * @property baseUrlNamespace
13
+ * @type String
14
+ * An optional url namespace to prepend to all urls (e.g. /admin). Defaults to an empty string
15
+ */
16
+ baseUrlNamespace: '',
17
+
18
+ /**
19
+ * @property baseUrlFormat
20
+ * @type String
21
+ * An optional url extension to append to all urls (e.g. .json). Defaults to an empty string
22
+ */
23
+ baseUrlFormat: '',
24
+
25
+ /**
26
+ * @property segmentJoiner
27
+ * @type String
28
+ * The string to join url segments on (defaults to '/')
29
+ */
30
+ segmentJoiner: '/',
31
+
32
+ /**
33
+ * Generates a url for the given object or function definition
34
+ * @param {Mixed} obj The object to create a URL for
35
+ * @return {String} The generated URL
36
+ */
37
+ urlFor: function() {
38
+ var config = {};
39
+ var lastArg = Array.prototype.slice.call(arguments, arguments.length - 1)[0];
40
+
41
+ //if the last argument is a config object
42
+ if (typeof lastArg == 'object' && !lastArg.className) {
43
+ //set some default url building options
44
+ Ext.apply(config, lastArg, {
45
+ format: this.baseUrlFormat,
46
+ urlNamespace: this.baseUrlNamespace
47
+ });
48
+
49
+ //use all but the last argument now
50
+ var arguments = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
51
+ };
52
+
53
+ //set some default url building options
54
+ Ext.applyIf(config, {
55
+ format: this.baseUrlFormat,
56
+ urlNamespace: this.baseUrlNamespace
57
+ });
58
+
59
+ var segments = [config.urlNamespace];
60
+
61
+ //iterate over valid arguments, appending each to segments
62
+ for (var i=0; i < arguments.length; i++) {
63
+ var arg = arguments[i];
64
+ var res = [];
65
+
66
+ switch(typeof arg) {
67
+ case 'string': res = [arg]; break;
68
+ case 'object': res = this.segmentsForInstance(arg); break;
69
+ case 'function': res = this.segmentsForClass(arg); break;
70
+ }
71
+
72
+ for (var j=0; j < res.length; j++) {
73
+ segments.push(res[j]);
74
+ };
75
+ };
76
+
77
+ var url = segments.join(this.segmentJoiner);
78
+ if (config.format) { url += "." + config.format; }
79
+
80
+ return url;
81
+ },
82
+
83
+ /**
84
+ * Returns an array of url segments for a model instance
85
+ * @param {ExtMVC.model} instance A Model instance with at least its primary key value set
86
+ * @return {Array} An array of segments for this url (e.g. ['users', '10'])
87
+ */
88
+ segmentsForInstance: function(instance) {
89
+ return [instance.constructor.urlName, instance.data.id];
90
+ },
91
+
92
+ /**
93
+ * Returns an array of url segments for a given class and optional primary key
94
+ * @param {Function} cls The class to generate a url for
95
+ * @param {String} id An optional ID to add to the segments
96
+ * @return {Array} An array of segments for this class
97
+ */
98
+ segmentsForClass: function(cls, id) {
99
+ var segs = [cls.urlName];
100
+ if (id) { segs.push(id); }
101
+
102
+ return segs;
103
+ }
104
+ };
105
+
106
+ ExtMVC.UrlBuilder = new ExtMVC.UrlBuilder();
@@ -0,0 +1,296 @@
1
+ /**
2
+ * @class ExtMVC.model.plugin.adapter
3
+ * @ignore
4
+ */
5
+ ExtMVC.model.plugin.adapter = {
6
+ initialize: function(model) {
7
+ var adapter = new this.RESTJSONAdapter();
8
+
9
+ Ext.override(Ext.data.Record, adapter.instanceMethods());
10
+ Ext.apply(model, adapter.classMethods());
11
+
12
+ //associations are optional so only add them if they are present
13
+ // try {
14
+ // Ext.override(ExtMVC.model.plugin.association.HasMany, adapter.hasManyAssociationMethods());
15
+ // Ext.override(ExtMVC.model.plugin.association.BelongsTo, adapter.belongsToAssociationMethods());
16
+ // } catch(e) {};
17
+ }
18
+ };
19
+
20
+ ExtMVC.model.addPlugin(ExtMVC.model.plugin.adapter);
21
+
22
+ /**
23
+ * @class ExtMVC.model.plugin.adapter.Abstract
24
+ * Abstract adapter class containing methods that all Adapters should provide
25
+ * All of these methods are expected to be asynchronous except for loaded()
26
+ */
27
+
28
+ /**
29
+ * @constructor
30
+ * @param {ExtMVC.model} model The model this adapter represents
31
+ */
32
+ ExtMVC.model.plugin.adapter.Abstract = function(model) {
33
+ /**
34
+ * @property model
35
+ * @type ExtMVC.model.Base
36
+ * The model this adapter represents (set on initialize)
37
+ */
38
+ // this.model = model;
39
+ };
40
+
41
+ ExtMVC.model.plugin.adapter.Abstract.prototype = {
42
+
43
+ /**
44
+ * Abstract save method which should be overridden by an Adapter subclass
45
+ * @param {ExtMVC.model.Base} instance A model instance to save
46
+ * @param {Object} options Save options (e.g. {success: function(), failure: function()})
47
+ */
48
+ doSave: Ext.emptyFn,
49
+
50
+ /**
51
+ * Abstract find method which should be overridden by an Adapter subclass
52
+ * @param {Object} options Options for the find, such as primaryKey and conditions
53
+ */
54
+ doFind: Ext.emptyFn,
55
+
56
+ /**
57
+ * Abstract destroy method which should be overridden by an Adapter subclass
58
+ * @param {ExtMVC.model.Base} instance The model instance to destroy
59
+ */
60
+ doDestroy: Ext.emptyFn,
61
+
62
+ /**
63
+ * @property instanceMethods
64
+ * @type Object
65
+ * An object of properties that get added to the model's prototype
66
+ * These all run within the scope of a model instance
67
+ */
68
+ instanceMethods: function() {
69
+ return {
70
+ adapter: this,
71
+
72
+ /**
73
+ * Attempts to save this instance
74
+ * @member ExtMVC.model.Base
75
+ * @param {Object} options Options (see collectionMethods.create for arguments)
76
+ */
77
+ save: function(options) {
78
+ options = options || {};
79
+ if (options.skipValidation === true || this.isValid()) {
80
+ //looks good, attempt the save
81
+ return this.adapter.doSave(this, options);
82
+ } else {
83
+ //couldn't save
84
+ if (typeof options.failure == 'function') {
85
+ return options.failure.call(options.scope || this, this);
86
+ };
87
+ };
88
+ },
89
+
90
+ /**
91
+ * Attempts to destroy this instance (asynchronously)
92
+ * @member ExtMVC.model.Base
93
+ * @param {Object} options Options to pass to the destroy command (see collectionMethods.create for args)
94
+ */
95
+ destroy: function(options) {
96
+ return this.adapter.doDestroy(this, options);
97
+ },
98
+
99
+ /**
100
+ * Updates selected fields with new values and saves straight away
101
+ * @member ExtMVC.model.Base
102
+ * @param {Object} data The fields to update with new values
103
+ * @param {Object} options Options (see collectionMethods.create for arguments)
104
+ */
105
+ update: function(data, options) {
106
+ this.setValues(data);
107
+ this.save(options);
108
+ },
109
+
110
+ /**
111
+ * Returns true if this instance has been loaded from backend storage or has only been instantiated
112
+ * @member ExtMVC.model.Base
113
+ * @return {Boolean} True if loaded from the server
114
+ */
115
+ loaded: function() {
116
+
117
+ }
118
+ };
119
+ },
120
+
121
+ classMethods: function() {
122
+ return {
123
+ adapter: this,
124
+
125
+ /**
126
+ * Attempts to create and save a new instance of this model
127
+ * @param {Object} data The data to use in creating and saving an instance of this model
128
+ * @param {Object} options Options object:
129
+ * * skipValidation - set to true to bypass validation before saving (defaults to false)
130
+ * * scope - The scope to run callback functions in
131
+ * * success - pass in a function as a callback if save succeeds. Function called with 1
132
+ * argument - the new model instance
133
+ * * failure - pass in a function as a callback if save succeeds. Function called with 2
134
+ * arguments - the unsaved model instance and the json response
135
+ */
136
+ create: function(data, options) {
137
+ var instance = new this(data);
138
+ instance.save(options);
139
+
140
+ return instance;
141
+ },
142
+
143
+ /**
144
+ * Builds a new model on this collection but does not save it
145
+ * @param {Object} data The data to use in creating and saving an instance of this model
146
+ * @return {Object} The new model instance
147
+ */
148
+ build: function(data) {
149
+ return new this(data);
150
+ },
151
+
152
+ /**
153
+ * Finds the given related model on a relationship
154
+ * @param {Number|String|Object} conditions The unique identifier for this model, or a conditions object
155
+ * @param {Object} options Options (see collectionMethods.create for arguments)
156
+ */
157
+ find: function(conditions, options) {
158
+ //assume to be the primary key
159
+ if (typeof(conditions) == 'number' || typeof(conditions) == 'string') conditions = {primaryKey: conditions};
160
+
161
+ return this.adapter.doFind(conditions, options, this);
162
+ },
163
+
164
+ /**
165
+ * Issues a destroy (delete) command to delete the appropriate related object by ID
166
+ * @param {Number|String} id The ID of the associated model to delete
167
+ * @param {Object} options Options (see collectionMethods.create for arguments)
168
+ */
169
+ destroy: function(id, options) {
170
+ return this.adapter.doDestroy(id, options, this);
171
+ }
172
+ };
173
+ },
174
+
175
+ /**
176
+ * @property hasManyAssociationMethods
177
+ * @type Object
178
+ * An object full of properties and functions that get mixed in to hasMany association collections
179
+ * These methods are run in the scope of the model instance that owns the association, e.g. if
180
+ * User hasMany Posts, then 'this' refers to the user instance
181
+ */
182
+ hasManyAssociationMethods: function() {
183
+ return {
184
+ /**
185
+ * @member ExtMVC.model.plugin.association.HasMany
186
+ * @ignore (member doesn't seem to work for properties)
187
+ * @property adapter
188
+ * @type ExtMVC.model.plugin.adapter.Abstract
189
+ * A reference to the adapter attached to this association. Useful if you need to dip down to a lower
190
+ * level than the methods inside HasMany provide
191
+ */
192
+ adapter: this,
193
+
194
+ /**
195
+ * Attempts to create and save a new instance of this model
196
+ * @member ExtMVC.model.plugin.association.HasMany
197
+ * @param {Object} data The data to use in creating and saving an instance of this model
198
+ * @param {Object} options Options object:
199
+ * * skipValidation - set to true to bypass validation before saving (defaults to false)
200
+ * * success - pass in a function as a callback if save succeeds. Function called with 1
201
+ * arguments - the new model instance
202
+ * * failure - pass in a function as a callback if save succeeds. Function called with 2
203
+ * arguments - the unsaved model instance and the json response
204
+ */
205
+ create: function(data, options) {
206
+ var instance = new this.associatedClass(data);
207
+
208
+ //automatically set the foreign key here
209
+ // instance.set(this.foreignKey, )
210
+ },
211
+
212
+ /**
213
+ * Builds a new model on this collection but does not save it
214
+ * @member ExtMVC.model.plugin.association.HasMany
215
+ * @param {Object} data The data to use in creating and saving an instance of this model
216
+ * @return {Object} The new model instance
217
+ */
218
+ build: function(data, options) {
219
+
220
+ },
221
+
222
+ /**
223
+ * Finds the given related model on a relationship
224
+ * @member ExtMVC.model.plugin.association.HasMany
225
+ * @param {Number|String} id The unique identifier for this model.
226
+ */
227
+ find: function(id) {
228
+
229
+ },
230
+
231
+ /**
232
+ * Returns true if this association has been fully loaded yet
233
+ * @member ExtMVC.model.plugin.association.HasMany
234
+ * @return {Boolean} True if this association has been loaded yet
235
+ */
236
+ loaded: function() {
237
+
238
+ },
239
+
240
+ /**
241
+ * Issues a destroy (delete) command to delete the appropriate related object by ID
242
+ * @member ExtMVC.model.plugin.association.HasMany
243
+ * @param {Number|String} id The ID of the associated model to delete
244
+ */
245
+ destroy: function(id) {
246
+
247
+ }
248
+ };
249
+ },
250
+
251
+ /**
252
+ * @property belongsToAssociationMethods
253
+ * @type Object
254
+ * An object full of properties and functions that get mixed in to belongsTo association collections
255
+ */
256
+ belongsToAssociationMethods: function() {
257
+ return {
258
+ /**
259
+ * @member ExtMVC.model.plugin.association.BelongsTo
260
+ * @ignore (member doesn't seem to work for properties)
261
+ * @property adapter
262
+ * @type ExtMVC.model.plugin.adapter.Abstract
263
+ * A reference to the adapter attached to this association. Useful if you need to dip down to a lower
264
+ * level than the methods inside BelongsTo provide
265
+ */
266
+ adapter: this,
267
+
268
+ /**
269
+ * Finds the given related model on a relationship
270
+ * @member ExtMVC.model.plugin.association.BelongsTo
271
+ * @param {Number|String} id The unique identifier for this model.
272
+ */
273
+ find: function(id) {
274
+
275
+ },
276
+
277
+ /**
278
+ * Returns true if this association has been fully loaded yet
279
+ * @member ExtMVC.model.plugin.association.BelongsTo
280
+ * @return {Boolean} True if this association has been loaded yet
281
+ */
282
+ loaded: function() {
283
+
284
+ },
285
+
286
+ /**
287
+ * Issues a destroy (delete) command to delete the appropriate related object by ID
288
+ * @member ExtMVC.model.plugin.association.BelongsTo
289
+ * @param {Number|String} id The ID of the associated model to delete
290
+ */
291
+ destroy: function(id) {
292
+
293
+ }
294
+ };
295
+ }
296
+ };
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @class ExtMVC.model.plugin.adapter.MemoryAdapter
3
+ * @extends ExtMVC.model.plugin.adapter.Abstract
4
+ * Provides a very basic storage system where model data get stored to an object in memory
5
+ */
6
+ ExtMVC.model.plugin.adapter.MemoryAdapter = Ext.extend(ExtMVC.model.plugin.adapter.Abstract, {
7
+
8
+ /**
9
+ * @property store
10
+ * @type Object
11
+ * A simple object that models get saved to
12
+ */
13
+ store: {},
14
+
15
+ primaryKeys: {},
16
+
17
+ /**
18
+ * Performs the actual save request. Uses POST for new records, PUT when updating existing ones
19
+ */
20
+ doSave: function(instance, options) {
21
+ if (typeof instance == 'undefined') throw new Error('No instance provided to REST Adapter save');
22
+ options = options || {};
23
+
24
+ //if this model doesn't have a primary key yet, give it one now and mark it as saved
25
+ var id = instance.get(instance.primaryKey);
26
+ if (typeof id == 'undefined') {
27
+ id = this.primaryKeyFor(instance);
28
+ instance.set(instance.primaryKey, id);
29
+ }
30
+
31
+ //put the model data into its store
32
+ this.store[instance.tableName] = this.store[instance.tableName] || {};
33
+ this.store[instance.tableName][id.toString()] = instance.data;
34
+ },
35
+
36
+ /**
37
+ * Performs the actual find request.
38
+ * @param {Object} conditions An object containing find conditions. If a primaryKey is set this will be used
39
+ * to build the url for that particular instance, otherwise the collection url will be used
40
+ * @param {Object} options Callbacks (use callback, success and failure)
41
+ */
42
+ doFind: function(conditions, options, constructor) {
43
+ conditions = conditions || {}; options = options || {};
44
+
45
+ //helper function to cut down repetition in Ajax request callback
46
+ var callIf = function(callback, args) {
47
+ if (typeof callback == 'function') callback.apply(options.scope, args);
48
+ };
49
+
50
+ var modelStore = this.store[constructor.prototype.tableName] || {};
51
+
52
+ if (typeof conditions.primaryKey == 'undefined') {
53
+ //return everything
54
+ var records = [];
55
+
56
+ for (primaryKey in modelStore) {
57
+ records.push((modelStore[primaryKey]));
58
+ }
59
+
60
+ console.log(records);
61
+
62
+ return new Ext.data.Store({
63
+ autoLoad: true,
64
+ data: {'rows': records},
65
+ // proxy: new Ext.data.MemoryProxy({'rows': records}),
66
+ fields: constructor.prototype.fields.items,
67
+ reader: new Ext.data.JsonReader({root: 'rows'}, constructor)
68
+ });
69
+
70
+ } else {
71
+ var data = modelStore[conditions.primaryKey.toString()];
72
+
73
+ if (typeof data == 'undefined') {
74
+ callIf(options.failure);
75
+ } else {
76
+ callIf(options.success, [new constructor(data)]);
77
+ }
78
+ }
79
+ },
80
+
81
+ doDestroy: function(instance, options) {
82
+ if (typeof instance == 'undefined') throw new Error('No instance provided to REST Adapter save');
83
+ options = options || {};
84
+
85
+ Ext.Ajax.request(
86
+ Ext.applyIf(options, {
87
+ method: this.destroyMethod,
88
+ url: this.instanceUrl(instance)
89
+ })
90
+ );
91
+ },
92
+
93
+ /**
94
+ * Returns the next available primary key for a model instance
95
+ * @param {ExtMVC.model.Base} instance The model instance
96
+ * @return {Number} The primary key to use for this instance
97
+ */
98
+ primaryKeyFor: function(instance) {
99
+ this.primaryKeys[instance.tableName] = this.primaryKeys[instance.tableName] || 1;
100
+
101
+ return this.primaryKeys[instance.tableName] ++;
102
+ }
103
+ });