{"action":"created","issue":{"url":"https://api.github.com/repos/strongloop/loopback/issues/1241","labels_url":"https://api.github.com/repos/strongloop/loopback/issues/1241/labels{/name}","comments_url":"https://api.github.com/repos/strongloop/loopback/issues/1241/comments","events_url":"https://api.github.com/repos/strongloop/loopback/issues/1241/events","html_url":"https://github.com/strongloop/loopback/issues/1241","id":64023799,"number":1241,"title":"investigate soft delete feature","user":{"login":"clarkbw","id":2134,"avatar_url":"https://avatars.githubusercontent.com/u/2134?v=3","gravatar_id":"","url":"https://api.github.com/users/clarkbw","html_url":"https://github.com/clarkbw","followers_url":"https://api.github.com/users/clarkbw/followers","following_url":"https://api.github.com/users/clarkbw/following{/other_user}","gists_url":"https://api.github.com/users/clarkbw/gists{/gist_id}","starred_url":"https://api.github.com/users/clarkbw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clarkbw/subscriptions","organizations_url":"https://api.github.com/users/clarkbw/orgs","repos_url":"https://api.github.com/users/clarkbw/repos","events_url":"https://api.github.com/users/clarkbw/events{/privacy}","received_events_url":"https://api.github.com/users/clarkbw/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-03-24T15:25:25Z","updated_at":"2015-03-28T23:00:10Z","closed_at":null,"body":"This is a fork of the issue strongloop/loopback-component-push#57 and the related pull request strongloop/loopback-component-push#72 where a quick patch was created to investigate implementing a soft delete for the strongloop/loopback-component-push module.\r\n\r\n@raymondfeng mentioned that this would make sense to generalize and bring up to the loopback level so I'm opening this issue for that.\r\n\r\nI'd appreciate any comments from @karlmikko who mentioned here https://github.com/strongloop/loopback/issues/222#issuecomment-46518381 implementing a soft delete via a boot script.\r\n\r\nI'm assuming we want a field, perhaps configurable, which looks something like `_is_deleted` that defaults to `false` and is changed to `true` where we intend to delete.  When this soft delete option is turned on for a Model the find and upsert methods likely want to filter for instances where the `_is_deleted` property is true.\r\n\r\nHere's an example model definition with a possible option:\r\n\r\n```json\r\n{\r\n  \"name\": \"Customer\",\r\n  \"description\": \"A Customer model representing our customers.\",\r\n  \"base\": \"User\",\r\n  \"softDelete\" : true\r\n  }\r\n}\r\n```\r\n\r\nAnd this could also allow implementers to specify the attribute name so they can match this up with data they might already have.\r\n\r\n```json\r\n{\r\n  \"name\": \"Customer\",\r\n  \"description\": \"A Customer model representing our customers.\",\r\n  \"base\": \"User\",\r\n  \"softDelete\" : {\r\n    \"attribute\": \"isDeleted\"\r\n  }\r\n  }\r\n}\r\n```\r\n\r\nFrom a quick search I see a couple options:\r\n* Use the PersistedModel setup method to wrap the `destroyAll` functions changing from a `destroyAll` to `updateAll` call passing `{ _is_deleted : true }`\r\n* Add a _default scope_ to the model so our find methods all work as expected.\r\n* Instead of default scope we could use the PersistedModel setup to wrap the find / upsert methods to filter for the soft delete attribute\r\n\r\nBelow is just for clarity, we would set the default scope programmatically, but this is what the model definition would look like with a `soft delete default scope`.\r\n\r\n```json\r\n{\r\n  \"name\": \"Customer\",\r\n  \"description\": \"A Customer model representing our customers.\",\r\n  \"base\": \"User\",\r\n  \"scope\": {\r\n    \"where\": {\r\n      \"_is_deleted\": false\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nI also looked at doing this from the connector level but I don't think connectors should be aware of options in the models, they are better kept simple to just implement the required CRUD methods."},"comment":{"url":"https://api.github.com/repos/strongloop/loopback/issues/comments/87325190","html_url":"https://github.com/strongloop/loopback/issues/1241#issuecomment-87325190","issue_url":"https://api.github.com/repos/strongloop/loopback/issues/1241","id":87325190,"user":{"login":"fabien","id":2749,"avatar_url":"https://avatars.githubusercontent.com/u/2749?v=3","gravatar_id":"","url":"https://api.github.com/users/fabien","html_url":"https://github.com/fabien","followers_url":"https://api.github.com/users/fabien/followers","following_url":"https://api.github.com/users/fabien/following{/other_user}","gists_url":"https://api.github.com/users/fabien/gists{/gist_id}","starred_url":"https://api.github.com/users/fabien/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fabien/subscriptions","organizations_url":"https://api.github.com/users/fabien/orgs","repos_url":"https://api.github.com/users/fabien/repos","events_url":"https://api.github.com/users/fabien/events{/privacy}","received_events_url":"https://api.github.com/users/fabien/received_events","type":"User","site_admin":false},"created_at":"2015-03-28T23:00:09Z","updated_at":"2015-03-28T23:00:09Z","body":"@seriousben thanks for the heads-up. AFAIK this is already working (or perhaps this is still pending with this: https://github.com/strongloop/loopback-boot/pull/111 ?) - I'm not really sure, because I'm waiting forever to have this patch merged ... I have been using the patched code since last year though, which enabled me to extract all kinds of 'traits' as mixins."}}