-
-
Notifications
You must be signed in to change notification settings - Fork 718
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
Deep Diff checking is not working #692
Comments
Hey, could you add some code examples - so like what you fill in your model, how you've configured (want to configure) the activitylog and what you would expect to be logged. I agree that the JSON support isn't as complete as the base attributes. With knowing about your expectations it will be easier to add/support (some of) them. |
Specifically I am using this in combination with Laravel Nova and custom JSON field which ends up having to update all the attributes of the extra_attributes that is the schemaless-attributes package. In this way the extra_attributes I presume is made dirty, but normally in this case, the standard attributes are dismissed from the activity log using the array_diff_uassoc call in this package to handle the log only dirty functionality. I also have an import from data files for this so the call is basically just:
SO more concretely:
And then usage like:
This will also set the whole extra_attributes as being "changed" when it's potentially really not changed at all. There are more things stored there than just a single property but I figured this being a relatively simple case would be easiest. |
Okay, so if you define the JSON sub-keys in the
$submitEmptyLogs = false;
$logOnlyDirty = true;
$logAttributes = ['extra_attributes->phone', 'extra_attributes->details']; $location = Location::create([
'name' => 'Hamburg',
'extra_attributes' => ['details' => '', 'phone' => '1231231234']
]);
// the log will contain both keys because it's a new record
// * extra_attributes->phone
// * extra_attributes->details
$location->update(['name' => 'London');
// no log because the name is not tracked
$location->update(['extra_attributes' => ['details' => 'new details']]);
// the log will contain only the details sub-key because nothing else is changed
// * extra_attributes->details
$location->update(['extra_attributes' => ['phone' => '1231231234']]);
// no log because the phone has not changed
$location = $location->update([
'name' => 'New York',
'extra_attributes' => ['details' => 'new details', 'phone' => '987654321']
]);
// the log will contain only the phone sub-key because nothing else is changed or tracked
// * extra_attributes->phone Do these examples describe your expected behavior? |
That seems to sound correct yes. I would also just tack on that if logAttributes was set to * and still logOnlyDirty, then it should still have the same effect as you've described with the only addition. I'm assuming that's an included case, but just figured I would make sure it was taken into consideration as well. |
Because a full deeplevel comparison and possible different expectations I will exclude this case. |
While I understand the number of random edge cases that could come up, wouldn't the same logic apply whether the logAttributes were set to Your example of using Carbon as a change while I see how non-trivial the detection of when to break out edge cases could occur. However it doesn't have to be an all or nothing scenario...take for example
which would trigger an object level deep diff check without needing to cover every single deep diff case, and would be at least better than having to list off like 10 attributes all prefixed with the base json attribute like |
Okay based on @Gummibeer replay above And a kind explanation from him I quote:
I tend to agree more with @ragingdave about meeting in mid point and only enables deep diff checking only and only when explicitly define it on i.e. $logAttributes = ['*', 'extra_attributes.*']; @ragingdave if you can spare some time I'll be working on this issue this week end :) |
The wildcard is a wildcard and will/should log EVERY and FULL changed attribute. The deep checking should only happen for explicit keys. |
The wildcard being a wildcard sure, I get that. What about when you have logOnlyDirty set to true? Would that enable deep diffing or would it just be like it is now and log the whole json attribute? If it will just log the whole thing, then the friction for the dev to have to specify a whitelist of keys to log, because otherwise it won't log the diff in the json, then it's not really worth it. I would think that the wildcard would apply hierarchically, so that in the spirit of the wildcard + logOnlyDirty, it would recursively log everything, but only things that changed. So if there's no changes to the keys of the json property, then it wouldn't log it. Maybe we are just talking about different cases though because that cut and dry where it sounds kind of terrible from a DX perspective for wildcard is wildcard. |
The dirty check would be on the listed attributes. Running deep diff per Default to the deepest possible level would lead to a lot of unexpected results. If the deep diff only on listed attributes isn't what you want or what would solve your issue we can close this issue. |
I suggest we introduce a new attribute to enable deep diff checking on only JSON attributes, set aside any other custom object casts since there's no demand for it at least for now. Because I believe that logging only changed attributes on a JSON would be very helpful in so many situations like in #647. The new attribute would called something like
That would limit the random edgecases and make a reasonable amount of testing for such behavior. As for the wildcards being a wildcards, sure, we can get around this by introducing a new attribute (flag) I would say to only enables deep diff checking only when needed. |
I actually had a completely different approach here, that might end up resolving the issue (maybe?) much simpler than recursion or having to denote nested keys. Instead of treating json as json, why not just convert the properties of the model to dot notated versions, then run the diff check as is, then un-dot them. This would effectively treat the entire property set as a single level key object and prevent any recursion. So for example, a model using extra attributes would have an array of properties on top of the model properties: Book: So normally you'd potentially have to recursively check diff on 3 levels to actually achieve what is being wanted here. After the diff checking, you just undot the properties and bob's your uncle! Here's an example undot macro as well:
I think it's a rather elegant solution if I don't say so myself ;) There's probably something I'm not thinking of, but this way would make potentially a non-breaking change, and would potentially require no additional properties or configuration to put in place. |
@ragingdave that's a good idea to dot the array! 🚀 |
Hey @ragingdave, I just love your elegant solution; I think it'll be a great example to add to the test suite and documentation! As @Gummibeer has mentioned above the new pipeline approach will provide so much flexibility to create even more elegant solutions for so many problems. In the mean time here you'll find an example of json diff, I know it's so basic, would you please PR an example with this elegant solution using pipeline to include it in the test suite and docs. Thanks! |
I will close this issue even if v4 isn't released yet. But the task itself is done and I want to check which tasks are really open. Please keep an eye on #787 |
@Gummibeer Is deep checking available in v4 release? I did not see it in the documentation. |
@amrshakya we do and we don't. 😂 |
When using a package like spatie's own schemaless-attributes, the extra attributes are logged as being different every touch of the model, which not only generates useless logs even when using
$logOnlyDirty
but just creates confusion in the activity log itself. While specifying specific json attributes is supported, that functionality isn't carried over into the dirty checks to confirm that what's going into the activity log is only specifically changed json attributes. Additionally, the reverse filtering that normally works isn't applied either (being able to set logAttributes = *, and then exclude attributes from ever being logged).It seems that there was quite a bit more that needed to be done to add json attribute logging that what's currently there. On top of that, in enabling that functionality or really handling any deep diffing is completely unsupported.
The text was updated successfully, but these errors were encountered: