UNPKG

6.3 kBJavaScriptView Raw
1var fs = require('fs'),
2 path = require('path'),
3 async = require('async'),
4 Document = require('./document'),
5 Queriable = require('./query'),
6 db_helper = require('./connection'),
7 logger = require('./logger');
8
9var defined_models = {};
10
11
12var ModelDocument = function (model_type, schema, views) {
13
14 var self = this;
15 var base = self;
16
17 self.model_type = model_type;
18 self.schema = schema;
19 self.views = views;
20 self.methods = {};
21
22 this.beforeSave = function (fn) {
23 self.beforeSaveFn = fn;
24 };
25
26 this.afterSave = function (fn) {
27 self.afterSaveFn = fn;
28 };
29
30 this.beforeCreate = function (fn) {
31 self.beforeCreateFn = fn;
32 };
33
34 this.beforeRemove = function (fn) {
35 self.beforeRemoveFn = fn
36 };
37
38 this.afterRemove = function (fn) {
39 self.afterRemoveFn = fn
40 };
41
42 this.validate = function (fn) {
43 self.validateFn = fn;
44 };
45
46 this.addView = function (view_name, view) {
47 self.views[view_name] = view;
48 };
49
50 this.addMethod = function (method_name, method) {
51 self.methods[method_name] = method;
52 };
53
54
55 this.view = function (view_name, options, cb) {
56 if (cb) {
57 this._view(self.model_type + '/' + view_name, options, cb);
58 } else {
59 this._view(self.model_type + '/' + view_name, options);
60 }
61 };
62
63 self.load = function (model_data) {
64 logger.info("Create model %s for %s", self.schema, model_data);
65
66 var model = new Document( self.beforeSaveFn,
67 self.beforeAfterFn,
68 self.beforeRemoveFn,
69 self.afterRemoveFn,
70 self.validateFn,
71 self.schema,
72 self.model_type);
73
74 self._load_methods(model);
75
76 if (!model_data) return model;
77
78 self._load_model_from_schema(key, model, model_data);
79
80 if (model_data._id) {
81 model.id = model_data._id;
82 }
83
84 if(model_data._rev) {
85 model.rev = model_data._rev;
86 }
87
88 model.dateCreated = model_data.dateCreated;
89 model.lastUpdated = model_data.lastUpdated;
90
91 return model;
92 };
93
94 self._load_methods = function (model) {
95 Object.keys(self.methods).forEach(function (key) {
96 model[key] = self.methods[key];
97 });
98 };
99
100 self._load_model_from_schema = function (key, model, model_data) {
101 // TODO convert to correct type if needed
102 Object.keys(self.schema).forEach(function (key) {
103
104 if (self.schema[key].type.has_one) {
105 model[key] = self.schema[key].type.has_one.load(model_data[key]);
106
107 } else if (self.schema[key].type.has_many) {
108 var created_docs = [];
109 var key_store = key;
110
111 if(model_data[key]) {
112
113 model_data[key].forEach(function (item) {
114 created_docs.push(Model(item.model_type).load(item));
115 });
116 }
117
118 model[key] = created_docs;
119
120 } else if (model_data[key] !== undefined) {
121 model[key] = model_data[key];
122
123 } else {
124 model[key] = schema[key].default;
125 }
126 });
127
128 }
129
130 self.create = function (model_data) {
131
132 var model = self.load(model_data);
133 self.beforeCreateFn && self.beforeCreateFn(model);
134
135 return model;
136 };
137
138 self.onDocLoad(self.load);
139
140};
141
142
143// Mixins http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/
144Queriable.call(ModelDocument.prototype);
145
146
147var Model = function (model_type) {
148 var model_document = defined_models[model_type];
149
150 if (!model_document) {
151 logger.error("No schema defined for", model_type);
152 throw {
153 message: "Model " + model_type + " does not exist"
154 }
155 }
156
157 if (model_document.instance) {
158 return model_document.instance;
159 }
160
161 model_document.instance = new ModelDocument(model_type, model_document.schema);
162
163 return model_document.instance;
164};
165
166Model.create_connection= function (db_name) {
167 return db_helper.create_connection(db_name);
168}
169
170Model.connect = Model.create_connection;
171
172Model.create_views = function (model_type, model_schema) {
173 logger.info("creating views for %s", model_type);
174 var db = db_helper.connection();
175
176 var model_views = {};
177
178 Object.keys(model_schema).forEach(function (property) {
179 model_views[property] = {};
180 model_views[property].map = 'function (doc) {if (doc.model_type === \''+model_type+'\' && doc.' +property +') { emit(doc.' +property +',doc)} }'
181 });
182
183 model_views.all = {};
184 model_views.all.map = 'function (doc) { if (doc.model_type === \''+model_type+'\'){emit(null, doc)}}';
185
186 return model_views
187};
188
189
190Model.load = function () {
191 var cb = function () {};
192 if (typeof(arguments[0]) === 'string') {
193 var dir = path.resolve(process.cwd(),arguments[0]);
194 fs.readdirSync(dir).forEach(function (file) {
195 var full_path = path.join(dir,file);
196 logger.info("loading " + full_path);
197 require(full_path);
198 });
199 }
200
201 var _cb = arguments[arguments.length - 1];
202
203 if (typeof(_cb) === 'function') {
204 cb = _cb;
205 }
206
207 logger.info("saving views");
208 var db = db_helper.connection();
209
210 Object.keys(defined_models).forEach(function (model_type) {
211 var model_document = defined_models[model_type]
212
213 db.save('_design/'+model_type, model_document.views, function (err, res) {
214 if (err) {
215 logger.error("Error creating views for %s %s",model_type, err);
216 return cb(err)
217 }
218
219 cb();
220 });
221 });
222
223};
224
225
226Model.define = function (model_type, model_schema) {
227 var schema = create_schema(model_schema);
228
229 var model_document = {};
230 model_document.schema = schema;
231 model_document.views = Model.create_views(model_type, schema);
232 model_document.instance = new ModelDocument(model_type, schema, model_document.views);
233
234 defined_models[model_type] = model_document;
235
236 logger.info("Defined schema %s for %s", schema, model_type);
237
238 return model_document.instance
239};
240
241function create_schema(model_schema) {
242 for (key in model_schema) {
243 if (model_schema[key].hasOwnProperty('type')) {
244 if (!model_schema[key].hasOwnProperty('default')) {
245 model_schema[key].default = undefined;
246 }
247 } else {
248 model_schema[key] = {
249 type: model_schema[key],
250 default: undefined
251 };
252 }
253 };
254
255 return model_schema;
256};
257
258
259// ----- For testing -------
260Model.remove_models = function () {
261 defined_models = {};
262};
263
264Model.dump = function () {
265 console.dir(defined_models);
266};
267
268
269
270module.exports = Model;