{"action":"created","issue":{"url":"https://api.github.com/repos/sequelize/sequelize/issues/965","repository_url":"https://api.github.com/repos/sequelize/sequelize","labels_url":"https://api.github.com/repos/sequelize/sequelize/issues/965/labels{/name}","comments_url":"https://api.github.com/repos/sequelize/sequelize/issues/965/comments","events_url":"https://api.github.com/repos/sequelize/sequelize/issues/965/events","html_url":"https://github.com/sequelize/sequelize/issues/965","id":20606477,"number":965,"title":"Implement asynchronicity in getters / setters","user":{"login":"thanpolas","id":458813,"avatar_url":"https://avatars.githubusercontent.com/u/458813?v=3","gravatar_id":"","url":"https://api.github.com/users/thanpolas","html_url":"https://github.com/thanpolas","followers_url":"https://api.github.com/users/thanpolas/followers","following_url":"https://api.github.com/users/thanpolas/following{/other_user}","gists_url":"https://api.github.com/users/thanpolas/gists{/gist_id}","starred_url":"https://api.github.com/users/thanpolas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thanpolas/subscriptions","organizations_url":"https://api.github.com/users/thanpolas/orgs","repos_url":"https://api.github.com/users/thanpolas/repos","events_url":"https://api.github.com/users/thanpolas/events{/privacy}","received_events_url":"https://api.github.com/users/thanpolas/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":29,"created_at":"2013-10-07T11:44:34Z","updated_at":"2016-03-09T08:00:37Z","closed_at":"2013-11-19T15:10:56Z","body":"Allow for async execution of virtual getters / setters.\r\n\r\nI will implement this feature as it's a show-stopper for me (hashing algo for passwords is async).\r\n\r\nSince there is no established pattern for async callbacks in Sequelize (apart from chained promises) i'll take the initiative to use the [`this.async()`](http://gruntjs.com/creating-tasks#why-doesn-t-my-asynchronous-task-complete) pattern.\r\n\r\nI'm not choosing detecting function arity (ala express.js) as this has side-effects in combination with promises.\r\n\r\n\r\n### Proposed Pattern using this.async()\r\n```js\r\nvar Foo = sequelize.define('Foo', {\r\n  title: {type     : Sequelize.STRING, allowNull: false,}\r\n\r\n  }, {\r\n\r\n  getterMethods   : {\r\n    title_slug  : function()  { \r\n      var done = this.async();\r\n\r\n      doSomethingAsync(function(){\r\n        done(slugify(this.title));\r\n      })\r\n    }\r\n});\r\n```\r\n\r\n### Using Function Arity Detection\r\n\r\n```js\r\nvar Foo = sequelize.define('Foo', {\r\n  title: {type     : Sequelize.STRING, allowNull: false,}\r\n\r\n  }, {\r\n\r\n  getterMethods   : {\r\n    title_slug  : function(done)  {  // defining an argument means async\r\n      doSomethingAsync(function(){\r\n        done(slugify(this.title));\r\n      })\r\n    }\r\n});\r\n```\r\n\r\n// @sdepold"},"comment":{"url":"https://api.github.com/repos/sequelize/sequelize/issues/comments/194168956","html_url":"https://github.com/sequelize/sequelize/issues/965#issuecomment-194168956","issue_url":"https://api.github.com/repos/sequelize/sequelize/issues/965","id":194168956,"user":{"login":"tremby","id":199635,"avatar_url":"https://avatars.githubusercontent.com/u/199635?v=3","gravatar_id":"","url":"https://api.github.com/users/tremby","html_url":"https://github.com/tremby","followers_url":"https://api.github.com/users/tremby/followers","following_url":"https://api.github.com/users/tremby/following{/other_user}","gists_url":"https://api.github.com/users/tremby/gists{/gist_id}","starred_url":"https://api.github.com/users/tremby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tremby/subscriptions","organizations_url":"https://api.github.com/users/tremby/orgs","repos_url":"https://api.github.com/users/tremby/repos","events_url":"https://api.github.com/users/tremby/events{/privacy}","received_events_url":"https://api.github.com/users/tremby/received_events","type":"User","site_admin":false},"created_at":"2016-03-09T08:00:36Z","updated_at":"2016-03-09T08:00:36Z","body":"I added an afterFind hook which just logs out the second argument.\r\n\r\nWhen I try the following\r\n\r\n```coffee\r\n  console.log \"find by id\"\r\n  models.User.findById 1,\r\n    attributes:\r\n      include: 'position'\r\n  .then ->\r\n    console.log \"findall\"\r\n    models.User.findAll\r\n      attributes:\r\n        include: 'position'\r\n```\r\n\r\nI get back this:\r\n\r\n```\r\nfind by id\r\n{ attributes: \r\n   [ 'id',\r\n     'provider',\r\n     'providerId',\r\n     'name',\r\n     'image',\r\n     'email',\r\n     'createdAt',\r\n     'updatedAt' ],\r\n  where: '`User`.`id` = 1',\r\n  plain: true,\r\n  hooks: true,\r\n  tableNames: [ 'Users' ],\r\n  type: 'SELECT',\r\n  model: User }\r\nfindall\r\n{ attributes: \r\n   [ 'id',\r\n     'provider',\r\n     'providerId',\r\n     'name',\r\n     'image',\r\n     'email',\r\n     'createdAt',\r\n     'updatedAt' ],\r\n  hooks: true,\r\n  tableNames: [ 'Users' ],\r\n  type: 'SELECT',\r\n  model: User }\r\n```\r\n\r\nIf I instead have, as the options,\r\n\r\n```coffee\r\n    attributes:\r\n      include: ['position']\r\n```\r\n\r\nI get the same output.\r\n\r\nIf I have\r\n\r\n```coffee\r\n    attributes:\r\n      include: ['position', 'pos']\r\n```\r\n\r\nI'm told `pos` doesn't exist (that's correct).\r\n\r\nIf I have\r\n\r\n```coffee\r\n    attributes:\r\n      include: [\r\n        ['position', 'pos']\r\n      ]\r\n```\r\n\r\nI'm told `Unknown column 'position' in 'field list'`. This is legit, because that column doesn't exist. But it is a virtual field so I expected it not to really add it to the query.\r\n\r\nIf I have\r\n\r\n```coffee\r\n    attributes:\r\n      include: [\r\n        ['(select 1)', 'one']\r\n      ]\r\n```\r\n\r\nI get\r\n\r\n```\r\nfind by id\r\n{ attributes: \r\n   [ 'id',\r\n     'provider',\r\n     'providerId',\r\n     'name',\r\n     'image',\r\n     'email',\r\n     'createdAt',\r\n     'updatedAt',\r\n     [ '(select 1)', 'one' ] ],\r\n  where: '`User`.`id` = 1',\r\n  plain: true,\r\n  hooks: true,\r\n  tableNames: [ 'Users' ],\r\n  type: 'SELECT',\r\n  model: User }\r\nfindall\r\n{ attributes: \r\n   [ 'id',\r\n     'provider',\r\n     'providerId',\r\n     'name',\r\n     'image',\r\n     'email',\r\n     'createdAt',\r\n     'updatedAt',\r\n     [ '(select 1)', 'one' ] ],\r\n  hooks: true,\r\n  tableNames: [ 'Users' ],\r\n  type: 'SELECT',\r\n  model: User }\r\n```\r\n\r\nWhat I want is to request the `position` attribute (which is defined as `VIRTUAL`), and have the afterFind know about it, as you suggested was possible above. Am I going about this totally wrongly?"}}