New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: Soft deletes #315
WIP: Soft deletes #315
Conversation
Hey @radmen! 👋 Thanks for helping us build this feature. One thing you need to consider to be careful about the |
@RomainLanz thanks for pointing that. Indeed it can be a problem. Do know any solution for this problem? I see some possible ones:
Me, personally, would stick to option three for the time being. It's not something which is required for the first iteration (it's just a matter of putting additional note somewhere in the docs). |
@radmen Just because Laravel doesn't do it, I will not ignore the bug (or tradeoff). I would like to explore the possibilities and see if it can be managed by default and if not, we should have some strong reasoning behind it. If you can make it work (without Maybe we need some way to modify the internal representation of the knex where clauses. You can explore the possibilities and I will jump on it later (on something else right now) |
All I'm saying is that it shouldn't be necessary implemented in v1.
I'm afraid that this could lead to some strange behaviors.
Will take a look at QueryBuilder. Was thinking about introducing something like |
Ohh typo there. I wanted to say |
I've taken a look at knex queryBuilder. Looks like without writing a wrapper for it it won't be possible to add something like Basically, such wrapper should:
It can be done, however, it will be another layer of complexity added to the library. What do you think about it? |
Sorry for the delay, I like the idea! |
@RomainLanz thanks for info. I'll check whats possible. Yet, before I start. Is the general shape of the idea ok (see: my first comment)? |
|
||
await this.constructor.$hooks.after.exec('restore', this) | ||
|
||
return !!affected |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
equivelent to return affected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It converts it to a boolean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice trick, thanks (y)
register (Model) { | ||
Model.addGlobalScope( | ||
query => { | ||
query.whereNull('deleted_at') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query.whereNull(`${Model.table}.deleted_at`)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jessicamrbr thanks, good catch!
@RomainLanz it's been a month since my last comment. I didn't receive any response. Would it be possible for you to look at it? Thank you :) |
Hey @radmen, I'm sorry I was completely busy with other stuff and forget to get back to you. |
I like the idea of having a
I believe we can deprecate |
that makes sense. When I was implementing soft delete trait hooks did not allow me to do this (they're quite strict and it's not possible to extend them in a project). In this case I can simply update the implementation of Hooks module.
If we deprecate it this code will be useless and should be removed. I think it has it's purpose so I'd say that we should keep get isDeleted() {
return this.$frozen && !this.isTrashed
} What do you think about it? |
I would like to have the feedback of @thetutlage |
ab40458
to
db3245a
Compare
any progress with softDeletes() ? how can I help you ? thanks |
@LordZombi you can look at the questions I left. Maybe you can help me and answer to them? :) |
@radmen i would suggest that you publish is as a standalone package so that people could use and contribute to it and then later at some point it gets merged into lucid. this way people will have something to work with rather than nothing. |
@hadihallak I could do it this way, yet the implementation is a bit hacky. It can blow some things and I would not like to be responsible for that :) If you want to I can put it as is, without tests, nothing. The risk is on you folks. If I get the answers to the things I can't figure out I will try to finish the implementation. |
@radmen You could make it clear in the repo that it's not production ready yet... Lets say a "Developer Preview". The reason i think we should make it available as is, is so that people could try it, open issues, make pull requests and start some discussion around it and then when it's ready i'm sure Virk wouldn't mind merging it since it's on the Adonis V5 roadmap anyway. what i'm saying is that having a half baked solution that the community can fix and enhance is better than not having one at all. |
@hadihallak I've thought for a while on what you suggested. I think it's a good idea to publish what is and let people test it. Maybe this way we can find out what's important in this functionality and actually reimplement it back to Adonis. I will prepare this package (currently adding test suite) and publish it in upcoming days. |
@radmen Awesome! cant wait to try it 👍 |
@hadihallak @LordZombi I've published package based on this PR. Feel free to use and leave some feedback. Thanks! https://www.npmjs.com/package/@radmen/adonis-lucid-soft-deletes |
Hey @radmen! Have you received any feedback about your package? |
@RomainLanz unfortunately not much. Two bug reports which were fixed and that was all. According to NPM stats package has some downloads, yet that's all I can tell. |
Soft deleting would be a cool feature, any news about the process to put it to the core? :) |
To give some feedback I still encountered some cases where it didn't filter out the deleted records Specifically with
I wonder if something like this could also be prevented const User = use('App/Models/User')
Table.query().join('users', 'user_id', 'users.id')
.whereNull('deleted_at') by doing const User = use('App/Models/User')
Table.query().join(User) |
@MZanggl could you give examples when this was failing? Maybe you could leave separate issues in the package repository? |
29554eb
to
297acd1
Compare
Any news in here? I would love to use this feature! |
@enbermudas from my side there's no news regarding this issue.
You can! :) I've extracted a package with the suggested implementation: https://github.com/radmen/adonis-lucid-soft-deletes |
FYI: this MR is outdated. The package I've created received few updates, which are not included here. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
In my recent project, I had to add support for soft deletes in models.
I thought that it could be a good starting point for #257.
I decided to create a PR to start a discussion whether this approach is correct. If yes - I can write missing parts.
For now, there's nothing much - just a trait I wrote in my project.
Changed behavior:
delete()
by default setsdeleted_at
timestamp (trashes model); it accepts object withforce
option, when set model will be removedisTrashed
attribute returns alwaysfalse
- it's a hack, should be removeddeleted_at
property setAdded behavior:
restore()
unsetsdeleted_at
which marks model as non-trashedisTrashed
propertywasTrashed
- returnsTRUE
ifdeleted_at
changed tonull
Things to consider:
delete
hooks; maybe there should betrash
hook?trash
hookwasTrashed
property could be removedisDeleted
property should behave. I've hardcodedfalse
because it allowed me to work with the models internal state. Otherwise, I should change few things in Lucid internals, can't remember what it was exactly...TODO:
withTrashed
query scopestatic get deletedAtColumn()
)softDeletes()
helper method for schema migration