Remove static models - #1551
Conversation
Migration guide for meTurning eloquent model Enum implementationAssuming all possible model values are written into the corresponding
Creating the migrationFind all foreign keys and their constraint names using
Editing old migrationsInstead of removing the tables from the migrations, it's easier to keep them and replace eloquent model method calls Common needed replacements
|
Will do that once the PR has been reviewed
|
@mzur I've started working on the maia code, but this PR is ready for review. It shouldn't be merged before the maia PR though. Most of the changes are the result of the above migration guide I created for myself. There are a few TODOs scattered through the code, but they could maybe just be removed. And I can't really test the entirety of the application, but the tests pass and the basic things I tried locally (annotations, reports, admin area, ...) worked without issues. I've long been thinking about creating an E2E regression test with something like Cypress for regression cases like this, what is your opinion on that? Just a single test that logs in and tests some basic things (create a project, open image/video annotation tool, create an annotation, generate a report, ...). |
mzur
left a comment
There was a problem hiding this comment.
I'm thinking if we switch to this new pattern we could just as well embrace it completely although it may be a lot of work. On the other hand, this could be a lot of work with only marginal performance gains (the performance impact of cached models could be minimal although it saves network roundtrips to the cache). It could be mostly a logical refactor without tangible gains...
Since you already put some work into this: Do you feel the change is worth it? We could still pull the plug before putting even more work into this.
If we go ahead:
I think the cleanest approach would be to rename columns like volumes.media_type_id to volumes.media_type and then use enum casting for this property. This way we don't have to implement custom accessors for every enum property.
Instead of implementing the enums to mimic the old static models (with MediaType::video() or MediaType::videoId() methods, for example) I'd fully switch to enum syntax (i.e. MediaType::VIDEO and MediaType::VIDEO->value). This would require updates to every place a static model was used (including modules).
Let's discuss the high-level comments first. I didn't go into too much detail below.
| ], | ||
| 'confidence' => 'required|numeric|between:0,1', | ||
| 'shape_id' => 'required|integer|exists:shapes,id', | ||
| 'shape_id' => ['required', 'integer', Rule::in(Shape::pluckById()->keys()->all())], |
There was a problem hiding this comment.
Isn't this equivalent to:
(also for other validation cases)
| 'shape_id' => ['required', 'integer', Rule::in(Shape::pluckById()->keys()->all())], | |
| 'shape_id' => ['required', 'integer', Rule::enum(Shape::class)], |
| { | ||
| // Image annotations cannot have the whole frame shape. | ||
| $shapeIds = Shape::whereKeyNot(Shape::wholeFrameId())->pluck('id'); | ||
| $shapeIds = Shape::pluckById(Shape::wholeFrame())->keys(); |
There was a problem hiding this comment.
A little confusing syntax. Maybe use:
| $shapeIds = Shape::pluckById(Shape::wholeFrame())->keys(); | |
| $shapeIds = Shape::pluckById(except: Shape::wholeFrame())->keys(); |
| public function toArray(): array | ||
| { | ||
| return [ | ||
| 'id' => $this->value, | ||
| 'name' => $this->label() | ||
| ]; | ||
| } | ||
|
|
||
| #[Override] | ||
| public function jsonSerialize(): mixed | ||
| { | ||
| return $this->toArray(); | ||
| } |
There was a problem hiding this comment.
Maybe put this into a trait (or Laravel already has something like this)?
| case IMAGE = 3; | ||
| case VIDEO = 4; |
There was a problem hiding this comment.
You can't rely on these IDs in the DB. The migration must override the existing IDs in the DB to match the enums in all cases. The enums can have new IDs starting at 1.
There was a problem hiding this comment.
I was wondering about that. Given the migrations execute changes in a defined order and that insert statements result in 1-indexed IDs also with a defined order I assumed the DB-values are the same everywhere? Would be nice for backwards-compatibility.
There was a problem hiding this comment.
It can be different if migrations are rolled back and reapplied because the sequence for the incrementing IDs is not reset during rollback.
There was a problem hiding this comment.
This should be called something like replace_role_table_with_enum. If it's called remove_roles it implies something completely different.
| // TODO Discuss if we want to "be safe" by mapping here or if it's enough | ||
| // to check in psql/with the migrations that the enum used the same numbers | ||
| // as the db table, in which case mapping is unnecessary |
There was a problem hiding this comment.
The mapping is essential for all static models (see above).
| ->update([$column => $newId]); | ||
| } | ||
|
|
||
| Schema::table($table, fn (Blueprint $t) => $t->dropForeign([$column])); |
There was a problem hiding this comment.
Isn't this required before you update the IDs to something potentially invalid above?
| biigle.$declare('labelTrees.members', {!! $members !!}); | ||
| biigle.$declare('labelTrees.roles', {!! $roles !!}); | ||
| biigle.$declare('labelTrees.defaultRole', {!! Biigle\Role::editor() !!}); | ||
| biigle.$declare('labelTrees.defaultRole', @json(Biigle\Role::editor()->toArray())); |
There was a problem hiding this comment.
Maybe also add implements Stringable to the enums?
|
Regarding E2E integration tests: I'd like to stick with testing the backend/API only because I feel full UI/E2E tests would quickly become a burden to maintain with our little resources. If people start paying for BIIGLE to be reliable in business-critical applications, we can reconsider this. Besides, since I just noticed this: In the future, please try to align your commit messages to the convention we use. |
|
@mzur I agree with your suggestions, and I don't think it will take more than a couple of hours to add these other changes. Shouldn't be a problem. |
|
I think this is not an issue of priorities (besides that "low" issues are basically never worked on), it's more my habit of writing down ideas as issues without always giving much though about gain/effort. So we have issues with medium priority that we definitely need sitting next to issues with the same priority that we should be more careful with. I'm not sure how to deal with it other than asking you to think about implications first and talking to me if you think gain/effort is too low. P.S.: You find issues with low priority in the full roadmap. The task list is already the version filtered by me. |
Closes #1048