-
-
Save renatodex/9f787607b79eda1f1ff25d18ee93d490 to your computer and use it in GitHub Desktop.
var AppModel = function() { | |
this.extend = function(model_setup) { | |
return function(model_data) { | |
return new factory_methods(model_setup, model_data); | |
} | |
} | |
this.factory_methods = function(model_setup, model_data) { | |
var custom_methods = model_setup["methods"]; | |
var base_methods = { | |
get: function(key){ | |
return model_data[key]; | |
}, | |
set: function(key, value) { | |
model_data[key] = value; | |
}, | |
attributes: function() { | |
return model_data; | |
} | |
} | |
return $.extend(base_methods, custom_methods); | |
} | |
return { | |
extend: extend | |
} | |
}(); |
Proposta:
function Model () { //magic goes here } // maybe class?
function myAjaxComponent ( data ) { // interface }
let User = new Model ( 'user' , {
name : { type : String, maxLength : 100, required : true },
age : { type : Number.Integer, customValidator : ageValidator, readonly : true },
email: ...
}, myAjaxComponent );
User.find ( { name : 'Renato' }).then...;
//
let user = new User({name: "Renato", age: 20 });
user.getName();
// Renato
user.getAge();
// 20
user.setName ( 'Renato Alves' );
user.name = 'Renato Alves';
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set
user.setName('Milhouse').setEmail('[email protected]').save().then...
// Chain is good! Promises awesome!
user.setAge ( 'bla');
// ValidationError: [type] must be [Number.Integer]
user.setAge ( 30 );
// Error: ageValidator consumes
user.save()
class Admin extends User...
// https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Classes
Uma definição de "model forte":
Validation engine (tipo joi) + schema json object pra manipular + possibilidade de inserir um factory ou callback para coisas do tipo recurso
Extra: geradores de model.js, que possam ser usados no FE e no BE.
Extra 2: persistência FE, com Local storage, cookies, whatever.
Referências:
https://github.com/tjworks/angoose
https://github.com/hapijs/joi
https://github.com/archangel-irk/storage
Saquei.
Tenho umas observações:
1. Sobre a definição da Model
Acho que não é legal instanciar a definição da Model, pode gerar uma confusão semantica, ex:
let User = new Model ( 'user' , {
name : { type : String, maxLength : 100, required : true },
age : { type : Number.Integer, customValidator : ageValidator, readonly : true },
email: ...
}, myAjaxComponent );
Sinto que ficaria mais semântico se a definição da classe fosse o retorno de um método estático, da mesma forma que o Waterline faz, ex:
var userCollection = Waterline.Collection.extend({
identity: 'user',
connection: 'default',
attributes: {
firstName: 'string',
lastName: 'string',
// Add a reference to Pets
pets: {
collection: 'pet',
via: 'owner'
}
}
});
Waterline: https://github.com/balderdashy/waterline-docs/blob/master/introduction/getting-started.md
O legal dessa abordagem é que dá pra você separar totalmente a camada de atributos da model, se você quiser criar uma espécie de Store:
var userAttributes = AppModel.Attributes.extend({
firstName: 'string',
lastName: 'string',
// Add a reference to Pets
pets: {
collection: 'pet',
via: 'owner'
}
})
var userCollection = AppModel.Collection.extend({
identity: 'user',
connection: 'default',
attributes: userAttributes
});
2. Sobre Validações e Atributos
Acho que validação é validação, e atributo é atributo, é mais interessante a gente separar esses conceitos, pra possibilitar uma modularização da coisa.
Pegando o exemplo da sua DSL:
let User = new Model ( 'user' , {
name : { type : String, maxLength : 100, required : true },
age : { type : Number.Integer, customValidator : ageValidator, readonly : true },
email: ...
}, myAjaxComponent );
Penso que poderia ser algo mais desacoplado, exemplo:
let User = new Model ( 'user' , {
attributes: {
name: Model.String,
age: Model.Integer,
email: Model.Email
},
validations: {
name: {
maxLength: 100,
required: true
},
age: {
customValidator: ageValidator,
readonly: true
}
}
}, myAjaxComponent );
Dessa forma, teríamos mais liberdade para desacoplar os conceitos.
Tô seguindo meio que a inspiração de um cara do Meteor chamado Simple Schema. Ele usa uns blocos de Schema que são acoplados ao banco. É interessante. (https://github.com/aldeed/meteor-simple-schema)
Seguindo a abordagem do tópico anterior, a gente consegue desacoplar cada parte da definição da model, olha só que legal:
let UserAttributes = new ModelAttributes({
name: Model.String,
age: Model.Integer,
email: Model.Email
})
let UserValidations = new ModelValidations({
name: {
maxLength: 100,
required: true
},
age: {
customValidator: ageValidator,
readonly: true
}
})
let User = new Model ( 'user' , {
attributes: UserAttributes,
validations: UserValidations,
}, myAjaxComponent );
Faz sentido uma abordagem com 1 e 2. Só acho que validação é inerente quando falamos de model, ainda que desacoplados.
Defining your model
Using your model