Skip to content

Instantly share code, notes, and snippets.

@renatodex
Created September 12, 2016 18:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renatodex/9f787607b79eda1f1ff25d18ee93d490 to your computer and use it in GitHub Desktop.
Save renatodex/9f787607b79eda1f1ff25d18ee93d490 to your computer and use it in GitHub Desktop.
App Model Idea
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
}
}();
@renatodex
Copy link
Author

renatodex commented Sep 12, 2016

Defining your model

var User = AppModel.extend({
    methods: {
        full_name: function() {
            return this.get('first_name') + " " + this.get('last_name')
        }
    }
})

Using your model

var myuser = new User({first_name: "Renato", last_name: "Alves"});
console.log("Should be equal to 'Renato' -> ", myuser.get('first_name'));
console.log("Should be equal to 'Alves' -> ", myuser.get('last_name'));

myuser.set('last_name', 'Freire'); 
console.log("Should be equal to 'Freire' -> ", myuser.get('last_name'));

console.log("Should be equal to 'Renato Freire' -> ", myuser.full_name());

@jotafeldmann
Copy link

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('bla@bla.com').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

@renatodex
Copy link
Author

renatodex commented Sep 29, 2016

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
});

@renatodex
Copy link
Author

renatodex commented Sep 29, 2016

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 );

@jotafeldmann
Copy link

Faz sentido uma abordagem com 1 e 2. Só acho que validação é inerente quando falamos de model, ainda que desacoplados.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment