Skip to content

Add strict helpers #1987

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

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

reeganviljoen
Copy link
Collaborator

closses #1976

What are you trying to accomplish?

Add a config.view_component.strict_helpers_enabled mode to view component which will throw an ViewComponent::StrictHelperError when helpers.<some_helper> is used.

This

What approach did you choose and why?

Anything you want to highlight for special attention from reviewers?

Copy link
Member

@joelhawksley joelhawksley left a comment

Choose a reason for hiding this comment

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

One thought on naming.

As a bigger question: what happens if one turns this on for their app and then wants to use a gem that provides ViewComponents that use helpers?

@@ -224,7 +232,7 @@ def controller
# @return [ActionView::Base]
def helpers
raise HelpersCalledBeforeRenderError if view_context.nil?

raise StrictHelperError if ViewComponent::Base.config.strict_helpers_enabled
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if this feature might be less confusing if we just had it be config.helpers_enabled and defaulting it to true?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@joelhawksley I think that's a good idea, when I have some time I will apply this feedback

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@joelhawksley I have changed the config to this, if you could review it again it would be a massive

@joelhawksley
Copy link
Member

@reeganviljoen thoughts on my comment from my review above?

As a bigger question: what happens if one turns this on for their app and then wants to use a gem that provides ViewComponents that use helpers?

@reeganviljoen
Copy link
Collaborator Author

reeganviljoen commented Mar 6, 2024

One thought on naming.

As a bigger question: what happens if one turns this on for their app and then wants to use a gem that provides ViewComponents that use helpers?

@joelhawksley I don't think this will break any existing gems, unless the user enables the config, however if the user does, it might not work unless the gem documents which helpers are used so the user can add them themselves with the use_helpers method

I do think this is a positive improvement however, as just adding helpers increases coupling to global state, which I feel is bad and is against the whole point of view_component. If a gem wants to add helpers they should let the user decide what helpers and how much coupling to global state they want

@boardfish
Copy link
Collaborator

boardfish commented Mar 7, 2024

If a gem providing ViewComponents uses helpers, I'm not sure we should mandate that it's subject to strict_helpers in the same way as the rest of the app.

Gems providing components that use helpers would need to be updated to use the new syntax, and waiting on providers to do that doesn't feel like an ideal experience for devs using ViewComponent to me. It's absolutely something gem maintainers should do post-haste, but I think configuration could make the transition period easier for consumers of these gems.

I can see us going a few different ways with this:

  1. Gems adhere to their own configuration. I don't think there's a layer of config in place to do this just yet – gems still inherit from app config.
  2. Enabling strict_helpers enforces this for gems too. Making this available as an option would be good, but I don't think it should be the only one.
  3. We expose a lambda for strict_helpers. This could allow folks the flexibility to allowlist on a gem-by-gem basis, or report strict helper violations (e.g. to an error reporting platform/in logs). I'd like to see this become something we do more often potentially. If we introduce configuration that controls a breaking change, this would be good to allow folks to understand (through their test suite or at runtime) where changes need to be made.

I'm sure there are options beyond that, but that's what comes to mind right now. Any thoughts?

@joelhawksley
Copy link
Member

@boardfish thanks for sharing your concerns- I generally agree with you.

I think we might be better off having this be a macro folks can set on a component, likely on their ApplicationComponent.

@reeganviljoen
Copy link
Collaborator Author

reeganviljoen commented Mar 14, 2024

@joelhawksley @boardfish noted, I wills see if I can work on something to macro based system working

@danini-the-panini
Copy link

danini-the-panini commented Jul 4, 2024

I think we might be better off having this be a macro folks can set on a component, likely on their ApplicationComponent.

I am on board with this ☝🏻

Could we also allow it to be optionally a deprecation warning instead of an error, that way it won't break things but it will give devs the tool to migrate their existing components. This could be useful for e.g. very large code bases where it is infeasible to migrate all components at once

@danini-the-panini
Copy link

Another useful feature might be allowing to pass in a block that gets called every time helpers is referenced, so that devs can hook into their error tracker e.g. Sentry

@joelhawksley
Copy link
Member

@reeganviljoen just checking in- are you planning to complete this work?

@reeganviljoen
Copy link
Collaborator Author

@joelhawksley Absolutely, just been verry busy

@reeganviljoen
Copy link
Collaborator Author

@joelhawksley what do you think about @danini-the-panini comment, I think its a good idea, I could work that into our current instrumentation setup in a seperate PR

@reeganviljoen
Copy link
Collaborator Author

reeganviljoen commented Aug 7, 2024

@joelhawksley I think that this api is complete as the main concern was gem compatibility but the recent addition to use_helpers provides a path to working. with gems in a strict mode

@joelhawksley
Copy link
Member

@reeganviljoen thanks for cleaning up this PR. For now, I'm going to mark it as blocked on @boardfish's work here: #1945 (comment) ❤️

@boardfish
Copy link
Collaborator

This might actually be ideal as the first component-local config option due to the small scope of the PR. I'll see if I can grab some time this weekend to figure out if I can use this to make a start.

@boardfish
Copy link
Collaborator

Had a very scrappy crack at this in 35017a9 – it looks possible, and we could probably even ship that with a few more tests behind it and some cleanup (still need to document things and get the use of the private variable names vs. public method names straight). Going forward, though, we probably want to make a nice internal DSL that'll support migrating these config options across slowly but surely.

@reeganviljoen
Copy link
Collaborator Author

@boardfish I aprreciate the help, if you want to pair on this issue I be happy to help.

@boardfish
Copy link
Collaborator

There's perhaps an even cleaner solution in ActiveSupport::Configurable that I've now found - we were previously including this but hadn't perhaps used it to its full extent as far as I'm aware. I've got a busy week ahead but I'd like to look at wrapping it up as soon as I can to unblock you - I'd appreciate any early feedback anyone has on the PR.

@boardfish boardfish force-pushed the introduce-component-local-config branch from 3ef2840 to 51e99fb Compare January 27, 2025 18:03
@joelhawksley
Copy link
Member

@reeganviljoen I'm going to move this to draft as it is pretty out of date and remains blocked by @boardfish's work ❤️

@joelhawksley joelhawksley marked this pull request as draft March 13, 2025 18:08
@boardfish
Copy link
Collaborator

Hopefully it should be unblocked soon – I need to extract the component-local config work out of #2210 so that we can introduce this in V3.

@reeganviljoen
Copy link
Collaborator Author

@joelhawksley I am sorry I haven't been too active lately, but I will be taking a look at this shortly

@boardfish I would really appreciate that but no rush, if push comes to shove I will rebase this branch to get something workable

@boardfish
Copy link
Collaborator

@reeganviljoen #2230 is in a position that you now may want to rebase off that branch instead. (Easier said than done by the looks of things – let me know if you need any help, and you can always force this branch back to 51e99fb (its current most recent commit) if things go sideways!)

@joelhawksley
Copy link
Member

@reeganviljoen I believe this PR is no longer blocked. Are you still hoping to land it?

@reeganviljoen
Copy link
Collaborator Author

@joelhawksley Ill get working on it now, thanks

@reeganviljoen reeganviljoen changed the base branch from introduce-component-local-config to main May 8, 2025 15:50
boardfish and others added 18 commits May 8, 2025 17:52
ViewComponent::Base itself will always use the defaults. Any classes inheriting from ViewComponent::Base will cascade config down using InheritableOptions, only specifying any overrides.
Generate options being on their own "layer of config is currently unresolved - it might be that config needs to be a new object inheriting from InheritableOptions that has method accessors for everything in that namespace.

This was initially written to support extracting the incoming strict_helpers_enabled? option, but applies to everything.
No settings actually use it, but this would be the way to introduce it once we come to need it.
@reeganviljoen reeganviljoen force-pushed the rv-add-strict-helpers branch from dbfc516 to 94fa1ed Compare May 8, 2025 16:33
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.

4 participants