{"action":"created","issue":{"url":"https://api.github.com/repos/valum-framework/valum/issues/160","repository_url":"https://api.github.com/repos/valum-framework/valum","labels_url":"https://api.github.com/repos/valum-framework/valum/issues/160/labels{/name}","comments_url":"https://api.github.com/repos/valum-framework/valum/issues/160/comments","events_url":"https://api.github.com/repos/valum-framework/valum/issues/160/events","html_url":"https://github.com/valum-framework/valum/issues/160","id":132356622,"number":160,"title":"Support for a more structured OO API?","user":{"login":"Bob131","id":4337852,"avatar_url":"https://avatars.githubusercontent.com/u/4337852?v=3","gravatar_id":"","url":"https://api.github.com/users/Bob131","html_url":"https://github.com/Bob131","followers_url":"https://api.github.com/users/Bob131/followers","following_url":"https://api.github.com/users/Bob131/following{/other_user}","gists_url":"https://api.github.com/users/Bob131/gists{/gist_id}","starred_url":"https://api.github.com/users/Bob131/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Bob131/subscriptions","organizations_url":"https://api.github.com/users/Bob131/orgs","repos_url":"https://api.github.com/users/Bob131/repos","events_url":"https://api.github.com/users/Bob131/events{/privacy}","received_events_url":"https://api.github.com/users/Bob131/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/valum-framework/valum/labels/documentation","name":"documentation","color":"fbca04"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-02-09T08:14:12Z","updated_at":"2016-02-09T17:35:20Z","closed_at":null,"body":"Hi again, I was just checking out all the new shiny stuff that's been added since I last had a peek, and I have to say I'm actually quite excited by the progress you've made. I've not had enough time with the docs to properly grok all the bits and bobs, but from my quick peruse it looks fantastic.\r\n\r\nThat said, there's a feature I'd be quite interested in. As far as I can see, currently if one so wished they could subclass the `Router` class, add their own functions and call `this.get()` etc in the `construct` block to try and move logic out of `main()` and into it's own discreet class. If this behaviour already works, could this become an official and documented way to use the framework? Perhaps further down the line some introspection magic could be added to automatically register routes based on declared functions (if that's even possible).\r\n\r\nI don't think this would confer any technical benefit, but I feel like officially supporting this method of usage would enable applications leveraging the framework to be more Vala-esque (or at least according to my understanding of \"the Vala style\"). In any case, it would be an additional style in the API consumer's toolbox from which they can choose depending on taste ;)"},"comment":{"url":"https://api.github.com/repos/valum-framework/valum/issues/comments/181973312","html_url":"https://github.com/valum-framework/valum/issues/160#issuecomment-181973312","issue_url":"https://api.github.com/repos/valum-framework/valum/issues/160","id":181973312,"user":{"login":"arteymix","id":1318477,"avatar_url":"https://avatars.githubusercontent.com/u/1318477?v=3","gravatar_id":"","url":"https://api.github.com/users/arteymix","html_url":"https://github.com/arteymix","followers_url":"https://api.github.com/users/arteymix/followers","following_url":"https://api.github.com/users/arteymix/following{/other_user}","gists_url":"https://api.github.com/users/arteymix/gists{/gist_id}","starred_url":"https://api.github.com/users/arteymix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arteymix/subscriptions","organizations_url":"https://api.github.com/users/arteymix/orgs","repos_url":"https://api.github.com/users/arteymix/repos","events_url":"https://api.github.com/users/arteymix/events{/privacy}","received_events_url":"https://api.github.com/users/arteymix/received_events","type":"User","site_admin":false},"created_at":"2016-02-09T17:35:20Z","updated_at":"2016-02-09T17:35:20Z","body":"I've been working on a few things: I try to converge the features into a release for this summer. Right now, I'm working on a formal rule parser to reverse them!\r\n\r\nI don't see anything that would prevent anyone from sub-classing `Router`. It would actually be a very good approach to solve structural complexity. It's worthy of an example and documentation recipe!\r\n\r\nValum supports the concept of subrouting, which can be used to assemble various routers under a single one serving requests.\r\n\r\n```vala\r\nvar app = new Router ();\r\napp.rule (Method.ALL, \"user/*\", new UserRouter ().handle);\r\nnew Server (\"org.valum.example.Subrouting\", app.handle);\r\n```\r\n\r\nIn short, you would have something like:\r\n\r\n```vala\r\npublic class UserRouter : Router {\r\n\r\n    construct {\r\n        rule (\"user/<int:id>(/<method>)?\", setup).then ((req, res, next, ctx) => {\r\n            switch (ctx[\"method\"]) {\r\n                case null:\r\n                    view (req, res, next, ctx);\r\n                    break;\r\n                case \"delete\"\r\n                    delete (req, res, next, ctx);\r\n                    break;\r\n                 default:\r\n                     throw new ClientError.NOT_FOUND (\"method '%s' not defined\", \r\n                                                      ctx[\"method\"]);\r\n            }\r\n        }).then (teardown);\r\n    }\r\n\r\n    public void setup (Request req, Response res, NextCallback next, Context ctx) {\r\n        // verify rights\r\n        next (req, res);\r\n    }\r\n\r\n    public void view (Request req, Response res, NextCallback next, Context ctx) {\r\n         // work here!\r\n        next (req, res);   \r\n    }\r\n\r\n    public void new @delete (Request req, Response res, NextCallback next, Context ctx) {\r\n         // work here!\r\n        next (req, res);   \r\n    }\r\n\r\n    public void teardown (Request req, Response res, NextCallback next, Context ctx) {\r\n        // (render or handle status codes)\r\n    }\r\n}\r\n```\r\n\r\nI like it!\r\n\r\nWhat I think is that this is just what people need. It's flexible on all possible aspects. The rest of the answer is more hypothetical and would probably be a basis for a derived project.\r\n\r\nGObject Introspection is surely powerful enough to automate the binding work (see [template-glib](https://github.com/chergert/template-glib), it's able to resolve method).\r\n\r\nHowever, such a feature (namely a controller layer) would imply that we would enforce some conventions, which is not in line with Valum.\r\n\r\n - what methods are bound to a function (this would require a custom annotation, probably by linking with `libvala`)\r\n - how do we resolve the called function in the controller? (probably a key in the context)\r\n\r\nAlso, this would be useful only for user interaction. APIs have other requirements: work is delegated given on possible manipulations of a resource.\r\n\r\nYou could even go one step further: resolve the controller using GType, so your application would just be a set of class definitions with a middleware that handle all the resolution automatically.\r\n\r\nAs said, this would be a quite complex piece of code, but ultimately very useful."}}