Skip to content
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

Marketplace Tags enhancements #2431

Merged
merged 2 commits into from
Jun 3, 2024
Merged

Marketplace Tags enhancements #2431

merged 2 commits into from
Jun 3, 2024

Conversation

rosschapman
Copy link
Contributor

@rosschapman rosschapman commented Jun 1, 2024

A handful of useful, low-bar follow-ups to #2361 that was scoped out in #2426.

  • Adds tag deletion
  • Renames group* -> menu*
    💬 Did my best to migrate this language in the code and for end users. Feedback very welcome.
  • Adds sort_alpha scope for Products
  • Adds new Display and Admin components for tags
    • Adds product tag count to Tag admin, with pluralized string
      image
      image

@@ -70,6 +70,7 @@ en:
success: "Notification Method '%{contact_location}' Saved!"
destroy:
success: "Notification Method '%{contact_location}' Removed!"
link_to: "Remove Notification Method '%{contact_location}'"
Copy link
Contributor Author

@rosschapman rosschapman Jun 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discovered hitting a different bug when running testing spec/furniture/marketplace/marketplace_tags_system_spec.rb surfaced this missing translation. 🤷‍♀️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably worth submitting independently so it can be merged without being hung up on feedback for this feature.

@rosschapman rosschapman changed the title WIP Marketplace Tags enhancements Jun 2, 2024
@rosschapman rosschapman marked this pull request as ready for review June 3, 2024 16:02
<%= render CardComponent.new(dom_id: dom_id(tag)) do |card| %>
<div class="flex flex-col gap-2">
<h3><%= tag.label %></h3>
<span class="text-xs">Assigned to <%= assigned_product_count %> <%= "Product".pluralize(assigned_product_count) %></span>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about "assigned to" 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just "N products" or "on N products" might be clear enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about this boilerplate being here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for i18n? Or ? If we don't put anything in it I would rather we left it out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's auto-generated by rails generate component ... for i18n. I can remove them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, no sense in checking in blank lines. (Also, I had no idea this .yml file for a component was a thing, #TIL.)

<%- unless tag.products.empty? %>
<h1><%= tag.label %></h1>
<div class="grid lg:grid-cols-3 gap-3">
<%- tag.products.with_all_rich_text.unarchived.each do |product| %>
<%- tag.products.with_all_rich_text.unarchived.sort_alpha.each do |product| %>
Copy link
Contributor Author

@rosschapman rosschapman Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this amount of scope chaining typical in templates? Would you put a helper on the ruby component to reduce logic in the template?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's not too unusual, but it does make for an N+1 query. It may be worth pulling this into the query on line 1; which may be expressed in the view directly, as a helper on MenuComponent, or a scope on Marketplace.

There's also an argument to be made for not doing any queries from within a Component or view; instead performing them at the controller layer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the best way to analyze whether this lookup would produce an n+1 query? Righ now if I render out the sql in a rails console I'm not seeing multiple selects for associative rows.

select
	"marketplace_products"."id" as t0_r0,
	"marketplace_products"."marketplace_id" as t0_r1,
	"marketplace_products"."name" as t0_r2,
	"marketplace_products"."price_cents" as t0_r3,
	"marketplace_products"."price_currency" as t0_r4,
	"marketplace_products"."created_at" as t0_r5,
	"marketplace_products"."updated_at" as t0_r6,
	"marketplace_products"."discarded_at" as t0_r7,
	"marketplace_products"."servings" as t0_r8,
	"action_text_rich_texts"."id" as t1_r0,
	"action_text_rich_texts"."name" as t1_r1,
	"action_text_rich_texts"."body" as t1_r2,
	"action_text_rich_texts"."record_type" as t1_r3,
	"action_text_rich_texts"."record_id" as t1_r4,
	"action_text_rich_texts"."created_at" as t1_r5,
	"action_text_rich_texts"."updated_at" as t1_r6
from
	"marketplace_products"
	inner join "marketplace_product_tags" on "marketplace_products"."id" = "marketplace_product_tags"."product_id"
	left outer join "action_text_rich_texts" on "action_text_rich_texts"."record_type" = 'Marketplace::Product'
		and "action_text_rich_texts"."name" = 'description'
		and "action_text_rich_texts"."record_id" = "marketplace_products"."id"
where
	"marketplace_product_tags"."tag_id" = 'b8d56ff4-8326-4a9b-8576-9e4b677bc4c4'
	and "marketplace_products"."discarded_at" is null
	/* loading for pp */
order by
	"marketplace_products"."name" asc
limit 11;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An N+1 situation requires two separate queries (one that is repeated N times, plus the outer one), so you would not see an N+1 query by looking at the SQL of one query. You would need to have a look at the implementation of the ProductComponent, which is what you are rendering inside the loop, and see if it is going to create any additional queries.

Also, we can add https://github.com/flyerhzm/bullet to the project and help it guide us when it thinks there are N+1 queries (although note that it is not, err, bullet-proof?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh oh oh right, the risk of n+1 occurs with potential queries for each item from this collection as we loop. bullet gem looks useful. Sounds like similar amount of caution/skepticism we reserve for strong_migrations's suggestions 😅.

I'll take a pass in another PR adding the bullet gem and lifting this heavy lifting to a better place for Law of Demeter and n+1 code hazards.

<h3><%= name %></h3>
<div class="mb-2">
<h3><%= name %></h3>
</div>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed some markup where it didn't seem to be doing what it was meant to do. In this case the margin wasn't working as a result of how parent flex/grid containers are set up.

Copy link
Member

@zspencer zspencer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an overall improvement from an ixd perspective, and tidies up some oddities; I'm down.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for i18n? Or ? If we don't put anything in it I would rather we left it out.

@@ -70,6 +70,7 @@ en:
success: "Notification Method '%{contact_location}' Saved!"
destroy:
success: "Notification Method '%{contact_location}' Removed!"
link_to: "Remove Notification Method '%{contact_location}'"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably worth submitting independently so it can be merged without being hung up on feedback for this feature.

@@ -142,6 +143,8 @@ en:
new:
link_to: "Add Product Tag"
edit:
link_to: "Edit Product Tag"
link_to: "Edit Product Tag '%{label}'"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍👍

update:
success: "Product Tag saved!"
destroy:
link_to: "Remove Product Tag '%{label}'"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍👍

<%- unless tag.products.empty? %>
<h1><%= tag.label %></h1>
<div class="grid lg:grid-cols-3 gap-3">
<%- tag.products.with_all_rich_text.unarchived.each do |product| %>
<%- tag.products.with_all_rich_text.unarchived.sort_alpha.each do |product| %>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's not too unusual, but it does make for an N+1 query. It may be worth pulling this into the query on line 1; which may be expressed in the view directly, as a helper on MenuComponent, or a scope on Marketplace.

There's also an argument to be made for not doing any queries from within a Component or view; instead performing them at the controller layer.

Comment on lines 49 to 55
format.turbo_stream do
if mtag.destroyed?
render turbo_stream: turbo_stream.remove(mtag)
else
render turbo_stream: turbo_stream.replace(mtag)
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a turbo stream? I thought we had gotten to the point where we can just render plain html and Turbo will do a diff-and-swap within the marketplace?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right. I'll double check.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be deleted.

@rosschapman
Copy link
Contributor Author

@anaulin I'm going to merge for the dopamine hit but if you're still chewing on anything please leave it here and I'll address it later.

@rosschapman rosschapman merged commit 64d7aa7 into main Jun 3, 2024
3 checks passed
@rosschapman rosschapman deleted the marketplace-tags-cleanup branch June 3, 2024 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants