Move category dropdown menu content into a turbo frame #782
Reference in New Issue
Block a user
Delete Branch "category-menu-frame"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR fixes (or at least improves by a large margin) the performance issues reported in #739.
Each transaction row comes with a huge amount of HTML representing the contents of the category dropdown, 99% of which will never viewed by the user. Moving the dropdown contents into a lazily loaded turbo frame makes an account page with 1k transaction about 20x smaller (2.5 MB instead of 51 MB).
Before

After

After this change there is a slight delay when you click a category badge before the dropdown contents are loaded, but it seems ok with a reasonable amount of categories. This can be further improved in the future by prefetching the dropdown contents when the badge is hovered.
@jakubkottnauer nice idea on the lazy loaded turbo frame, I definitely agree that we should be utilizing that for this scenario.
I don't mind the slight delay, but I think we could probably add some sort of "skeleton" loader, maybe something like this?
Also, the
category_menu_content_transactionpath feels a little off to me. What about something like this?@zachgoll Thank you for the review! Though I ended up defining the route differently; your suggestion results in path
/transactions/categories/:transaction_category_id/dropdown/newwhereas we need something more like/transactions/:id/categories/dropdown(the dropdown needs a transaction ID in order to get the transaction's current category and mark it as selected in the UI).Let me know if there's a nicer way to define such a route, I'm still quite new to RoR :)
@jakubkottnauer let me start by saying that the following suggestions are not necessarily 100% related to this specific PR, so if you'd like to get this change in and ignore these for now, I'm fine with that. Just let me know and I'll get it merged.
But I think why we're having such a hard time with this one is because our existing routing structure for transactions and categories doesn't fit the "singular" nature of a transaction category (i.e. a transaction can have a max of 1 category). We've currently got it setup like so:
If I'm not mistaken here, I think a better way to express all of this would be:
The routes this produces are fairly similar to what we have already, but feel a little more natural to me and expose the transaction ID that we need by default:
To implement this we'd need to rename a few folders, but IMO this would be a good improvement to what we currently have.
Would be happy to hear other ideas and critiques to this.
We'd also need a separate routing structure to independently manage these categories (i.e. in the Settings view), but I think that would be okay to have both the general editing and transaction-specific editing?
@josefarias no worries if you're busy with other things, but curious to hear if you'd agree with the comment above?
@jakubkottnauer @josefarias disregard my comment above about the singular resources. I wasn't reading things correctly before and see why we need the "collection" (to edit these outside the context of a transaction).
Wondering if we just add this above the existing route structure?
Hey @zachgoll @jakubkottnauer, great work here!
Here's how I'd suggest modeling this:
Could also do
as: :transaction_category_dropdownif that's more natural in english, I'm not sure!Here's the reasoning behind that:
transaction_categories_dropdown_path(selection_id: @transaction.category_id)showinstead ofnewhere because the dropdown is a resource we won't be callingcreateon. It's an entity that already exists. If anything, we'd callupdate/destroyon it — but even that doesn't make much sense in this context.:new, no problem.As far as rendering the actual dropdown, I'd do something like this in the controller (pseudocode, not tested):
@josefarias appreciate the help here!
I think what you've outlined makes sense and I'd agree that
showis probably a better action to use.The helper name you came up with makes sense to me as well. As I was playing around with the routes, came up with the following, which attempts to leverage auto-generated path helper names a bit more:
The only change that would be required to get tests passing again is update the
set_categorymethod inDeletionsControllerto use the param:category_idrather than:transaction_category_id. From a resource perspective, I think:category_idmakes sense given the independent nature of categories as we've discussed above?Any objections to this?
No objections! I like that better as well
@josefarias awesome, thanks again for the assist here!
@jakubkottnauer if you're good with the discussion and proposed changes above, I think we've got a path forward? Looks like you've got all the pieces here, just need a slight rework of the routing and the update to
DeletionsControllerI had mentioned above.@josefarias @zachgoll Thank you both for the great suggestions, I think we've gotten something really nice out of it 👍 I have implemented the changes. I ended up doing
instead of
because the latter doesn't work when no category is selected on a transaction. I'm a bit surprised that just wrapping the resource with
collection doinstead of puttingon: :collectiondirectly on the resource has this kind of impact on the generated route.Looks good! Thanks for the iterations on this.
And to your question about the
collectionblock—that's my bad,resourceandresourcesdo not accept anonoption. It was just silently failing there. So I think your solution is the right one!You had updated to v16.x right? Maybe this isn't related to the PG version after all.
My bad, I haven't noticed this has snuck in again, reverted. But yes, I had upgraded to 16.3 and still get this schema change when I run
bin/setupInteresting, I'll have to look into this again and see if there's a way to avoid in the future.