Closed smolinari closed 7 years ago
Hi Scott,
this 8 space indentations are more likely how github parse and show the code. For instance, in my editor (Atom) there are 4 space indentations.
Koa2 was chosen because of Promises which can be used with async/await. But Express 5 is also going to have Promises in all handlers so I recently made a switch from Koa to Express. I'll push a new version quite shortly.
I'm also considering some new improvements regarding how to integrate Contextable models to GraphQL schema in a more simple way.
I'll take a look at dataloader. Thx for the suggestion.
No problem.
On contextable models. Have you seen this? https://github.com/xpepermint/contextablejs (I'll be honest, I found it looking up what contextable models actually means. LOL!) :smile:
Scott
Yes. @xpepermint is my co-worker. This library contextablejs is just awesome. Recommend!
Cool! Great minds think and work alike! LOL!
Something else I was looking at is peasy. https://github.com/peasy/peasy-js
Could this be a good stack? Although, it seems contextable and peasy-js cover some of the same bases, like validation.
Scott
Hey @smolinari. We all heavily invest our time into openousrce projects that make our code clean and long-term sustainable.
If you are building an API using GraphQL or Express/Koa framework, then Contextable could be a perfect fit. There are also plans to add caching so you'll have dataloader integrated. About ODM/db-drivers, everything is added to the context
object thus you can access it anywhere in your app/model. We are about a month away from using all this in production and we are very happy about the results so far.
What's really cool about Contextable is that you can use it as GraphQL root resolver directly (see the example here). The package is ment for server and browser and everything is easily extendable. If you use Vue.js, then there is a super simple plugin for form validation using contextable, called vue-contextable.
I hope these helps. But then again, we have the same goal but we are all different thus I think you simple have to try other solutions and see what best fit into your code.
@xpepermint - Sounds good! And I appreciate the tips a lot!
I hope you don't mind me asking this, but where would the actual business logic fit in to Contextable (or wouldn't it)? An example would be, we are building an ecommerce application and the customer's cart exceedes a value for free shipping. So, instead of calculating a price for shipping, it is given the value "0". Where would I need to be making these decisions? This is why I thought peasy would be a good addition to the stack, as the rules can also be used client-side too.
Scott
It's all about the Model. Model is where business logic should be defined.
In Contextable, a Model is created from a Schema.
Example:
module.exports = new Schema({ // exposing model schema instance
fields: { // model fields
id: {
type: 'Integer'
},
...
},
instanceMethods: { // model instance methods
async isFreeShipping () {
let count = await this.$context.mongo.collection('shipping').count(); // `mongo` is a variable attached to the context object (check the docs)
return count > MAX_FREE_SHIPPING; //
},
...
},
...
});
I encourage you to check this tutorial and an example app for more. If you have further questions, feel free to ask ...
That makes sense. How about testing the methods though? Isn't context sort of like a god object?
Scott
True, new Context()
is a god object but it's there only to provide a central application context hold variables which are exposed as this.$context.{var}
in your models.
You do unit-testing of your models the same way you would for any other method in your code. Take a look at this file.
Thanks. I am still a bit unsure about such a large object, but that might just be my inexperience with things I've been told are generally bad practice while learning to program and yet I haven't necessarily run into such things.
Theoretically, all the business logic could still be built and tested in units, but then composed to build the context object at runtime, couldn't it? What I am trying to get at is a system where client devs can manipulate business rules, but the "under the hood" stuff should be left to the system devs.
Also, could you envision the Schema being automatically built? I mean, letting devs hack at the Schema at code level is one thing, but then allowing "domain users" to define Schema / the Model with a UI could bring the two worlds together better. When the user clicks on "Save", the system builds out the Schema definitions automatically.
Scott
It's possible but I'm not sure that this is a good practice. I would have to understand your use case better to advise further. In case of dynamic
data I would think of a different data model instead.
If you are concered about having big models, then Schema({mixins: [...]})
should do the trick.
I'll dig deeper myself, then if I have any questions about contextable, I'll ask that repo.
Thanks for the help! :+1:
Scott
Hi,
Thanks for this example.
Just a couple of questions. There are 8 space indentations in the models. Is there a particular reason for that?
Also, are you looking to expand this api example in any way? Would you consider also adding examples to use dataloader?
Is there a particular reason why you went with Koa and not Express?
Scott