Merge pull request #29 from strongloop/scope-remoting
Create remote functions for predefined scopes/relations
This commit is contained in:
commit
24e93248d1
|
@ -0,0 +1,90 @@
|
||||||
|
var DataSource = require('../index').DataSource;
|
||||||
|
var ds = new DataSource('memory');
|
||||||
|
|
||||||
|
var Order = ds.createModel('Order', {
|
||||||
|
customerId: Number,
|
||||||
|
orderDate: Date
|
||||||
|
});
|
||||||
|
|
||||||
|
var Customer = ds.createModel('Customer', {
|
||||||
|
name: String
|
||||||
|
});
|
||||||
|
|
||||||
|
Order.belongsTo(Customer);
|
||||||
|
|
||||||
|
Customer.create({name: 'John'}, function (err, customer) {
|
||||||
|
Order.create({customerId: customer.id, orderDate: new Date()}, function (err, order) {
|
||||||
|
order.customer(console.log);
|
||||||
|
order.customer(true, console.log);
|
||||||
|
|
||||||
|
Customer.create({name: 'Mary'}, function (err, customer2) {
|
||||||
|
order.customer(customer2);
|
||||||
|
order.customer(console.log);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Customer.hasMany(Order, {as: 'orders', foreignKey: 'customerId'});
|
||||||
|
|
||||||
|
Customer.create({name: 'Ray'}, function (err, customer) {
|
||||||
|
Order.create({customerId: customer.id, orderDate: new Date()}, function (err, order) {
|
||||||
|
customer.orders(console.log);
|
||||||
|
customer.orders.create({orderDate: new Date()}, console.log);
|
||||||
|
customer.orders.findById('2', console.log);
|
||||||
|
customer.orders.destroy('2', console.log);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Physician = ds.createModel('Physician', {
|
||||||
|
name: String
|
||||||
|
});
|
||||||
|
|
||||||
|
var Patient = ds.createModel('Patient', {
|
||||||
|
name: String
|
||||||
|
});
|
||||||
|
|
||||||
|
var Appointment = ds.createModel('Appointment', {
|
||||||
|
physicianId: Number,
|
||||||
|
patientId: Number,
|
||||||
|
appointmentDate: Date
|
||||||
|
});
|
||||||
|
|
||||||
|
Appointment.belongsTo(Patient);
|
||||||
|
Appointment.belongsTo(Physician);
|
||||||
|
|
||||||
|
Physician.hasMany(Patient, {through: Appointment});
|
||||||
|
Patient.hasMany(Physician, {through: Appointment});
|
||||||
|
|
||||||
|
Physician.create({name: 'Smith'}, function (err, physician) {
|
||||||
|
Patient.create({name: 'Mary'}, function (err, patient) {
|
||||||
|
Appointment.create({appointmentDate: new Date(), physicianId: physician.id, patientId: patient.id},
|
||||||
|
function (err, appt) {
|
||||||
|
physician.patients(console.log);
|
||||||
|
patient.physicians(console.log);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var Assembly = ds.createModel('Assembly', {
|
||||||
|
name: String
|
||||||
|
});
|
||||||
|
|
||||||
|
var Part = ds.createModel('Part', {
|
||||||
|
partNumber: String
|
||||||
|
});
|
||||||
|
|
||||||
|
Assembly.hasAndBelongsToMany(Part);
|
||||||
|
Part.hasAndBelongsToMany(Assembly);
|
||||||
|
|
||||||
|
Assembly.create({name: 'car'}, function (err, assembly) {
|
||||||
|
Part.create({partNumber: 'engine'}, function (err, part) {
|
||||||
|
assembly.parts.add(part, function(err) {
|
||||||
|
assembly.parts(console.log);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -41,8 +41,7 @@ Relation.hasMany = function hasMany(anotherClass, params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var methodName = params.as ||
|
var methodName = params.as || i8n.camelize(anotherClass.pluralModelName, true);
|
||||||
i8n.camelize(i8n.pluralize(anotherClass.modelName), true);
|
|
||||||
var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true);
|
var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true);
|
||||||
|
|
||||||
this.relations[methodName] = {
|
this.relations[methodName] = {
|
||||||
|
@ -141,12 +140,14 @@ Relation.hasMany = function hasMany(anotherClass, params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function destroy(id, cb) {
|
function destroy(id, cb) {
|
||||||
this.findById(id, function (err, inst) {
|
var self = this;
|
||||||
|
anotherClass.findById(id, function (err, inst) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (inst) {
|
if (!inst) return cb(new Error('Not found'));
|
||||||
|
if (inst[fk] && inst[fk].toString() == self.id.toString()) {
|
||||||
inst.destroy(cb);
|
inst.destroy(cb);
|
||||||
} else {
|
} else {
|
||||||
cb(new Error('Not found'));
|
cb(new Error('Permission denied'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
39
lib/scope.js
39
lib/scope.js
|
@ -20,6 +20,7 @@ function defineScope(cls, targetClass, name, params, methods) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define a property for the scope
|
||||||
Object.defineProperty(cls, name, {
|
Object.defineProperty(cls, name, {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
|
@ -80,6 +81,44 @@ function defineScope(cls, targetClass, name, params, methods) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wrap the property into a function for remoting
|
||||||
|
var fn = function() {
|
||||||
|
var f = this[name];
|
||||||
|
f.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn.shared = true;
|
||||||
|
fn.http = {verb: 'get', path: '/' + name};
|
||||||
|
fn.accepts = {arg: 'where', type: 'object'};
|
||||||
|
fn.description = 'Fetches ' + name;
|
||||||
|
fn.returns = {arg: name, type: 'array', root: true};
|
||||||
|
|
||||||
|
cls['__get__' + name] = fn;
|
||||||
|
|
||||||
|
var fn_create = function() {
|
||||||
|
var f = this[name].create;
|
||||||
|
f.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
fn_create.shared = true;
|
||||||
|
fn_create.http = {verb: 'post', path: '/' + name};
|
||||||
|
fn_create.accepts = {arg: 'data', type: 'object', source: 'body'};
|
||||||
|
fn_create.description = 'Creates ' + name;
|
||||||
|
fn_create.returns = {arg: 'data', type: 'object', root: true};
|
||||||
|
|
||||||
|
cls['__create__' + name] = fn_create;
|
||||||
|
|
||||||
|
var fn_delete = function() {
|
||||||
|
var f = this[name].destroyAll;
|
||||||
|
f.apply(this, arguments);
|
||||||
|
};
|
||||||
|
fn_delete.shared = true;
|
||||||
|
fn_delete.http = {verb: 'delete', path: '/' + name};
|
||||||
|
fn_delete.description = 'Deletes ' + name;
|
||||||
|
fn_delete.returns = {arg: 'data', type: 'object', root: true};
|
||||||
|
|
||||||
|
cls['__delete__' + name] = fn_delete;
|
||||||
|
|
||||||
// and it should have create/build methods with binded thisModelNameId param
|
// and it should have create/build methods with binded thisModelNameId param
|
||||||
function build(data) {
|
function build(data) {
|
||||||
return new targetClass(mergeParams(this._scope, {where:data || {}}).where);
|
return new targetClass(mergeParams(this._scope, {where:data || {}}).where);
|
||||||
|
|
Loading…
Reference in New Issue