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

Add assocaitions_exclude to exclude files from association inspection #380

Merged
merged 2 commits into from
May 7, 2024

Conversation

gmcgibbon
Copy link
Member

@gmcgibbon gmcgibbon commented Nov 16, 2023

What are you trying to accomplish?

Fixes #370

What approach did you choose and why?

Other gems like ActiveModel::Serializers define association methods that reference serializers. We can ignore these files entirely with an exclude pattern.

What should reviewers focus on?

The exclude pattern breaks public API, and we only get guarantees from Sorbet if the plugin package uses it (and they don't have to). So, I added an ArgumentError check to make sure all we still support the old signatures without relative_file. We could alternatively proceed without this precaution, so I can drop the commit if needed.

Type of Change

  • Bugfix
  • New feature
  • Non-breaking change (a change that doesn't alter functionality - i.e., code refactor, configs, etc.)

Additional Release Notes

  • Breaking change (fix or feature that would cause existing functionality to change)

Include any notes here to include in the release description. For example, if you selected "breaking change" above, leave notes on how users can transition to this version.

If no additional notes are necessary, delete this section or leave it unchanged.

Checklist

  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • It is safe to rollback this change.

@gmcgibbon gmcgibbon requested a review from a team as a code owner November 16, 2023 01:29
@exterm
Copy link
Contributor

exterm commented Nov 16, 2023

Could it be an option to allow users to define a path glob for ignoring associations in? ...I'm not sure which solution I'd prefer... but I am also not sure that it makes sense to take on this complexity in packwerk itself.

Maybe the whole association handling could be moved into a plugin, which could then also handle serializers?


sig { params(node: AST::Node).returns(T.nilable(Symbol)) }
def type(node)
case NodeHelpers.source_location(node).match(%r{\bapp/(.*)/}).to_a.last
Copy link
Member

@rafaelfranca rafaelfranca Nov 17, 2023

Choose a reason for hiding this comment

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

Checking the folder of the file is too brittle. Active Record subclasses can be anywhere, for example in subdirectories of app/models

Copy link
Member Author

Choose a reason for hiding this comment

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

If we don't filter paths somehow the bug still exists for AMS users. Maybe we can pull ignore paths from a configuration file if we think checking for app/models is too brittle?

Copy link
Member

@rafaelfranca rafaelfranca Nov 17, 2023

Choose a reason for hiding this comment

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

Can we check the context where has_many is called? This is tricky because you could make a case that serializers can also be inside app/models.

If we can't check the context, I'm ok with a exclude patter, so people that use AMS can say to not check on app/serializers

Copy link
Member Author

Choose a reason for hiding this comment

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

So from my understanding, we can only check what is statically printed in the file. There's no way to guarantee a superclass if a model without actually running the code or making unsafe assumptions.

Checking the superclass of the context is ActiveRecord::Base or ApplicationRecord is too brittle (because it doesn't account for custom record subclasses), and serializers have the same problem with their immediate subclass. We could check if the superclass or class end with Record, but that is an unsafe assumption for non-abstract models. We could try to resolve superclasses that aren't Active Record default, but if any of them aren't autoloaded with Zeitwerk, we won't be able to see them.

I think an exclude glob option covers all of our bases and avoids taking on this complexity.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated the PR to take this approach.

Copy link
Member

@rafaelfranca rafaelfranca left a comment

Choose a reason for hiding this comment

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

I don't think this gem should know about Active Model Serializers. We can and should limit our checks for ActiveRecord::Base subclasses, but we should not write code to know about others implementations of has_many

@gmcgibbon gmcgibbon force-pushed the support_non_ar_association branch 4 times, most recently from 8d8a79e to 2f19cbe Compare November 28, 2023 21:26
@gmcgibbon gmcgibbon changed the title Support Active Model Serializers in association inspector Add assocaitions_exclude to exclude files from association inspection Nov 28, 2023
USAGE.md Outdated Show resolved Hide resolved
Other libraries (like Active Model Serializers) use has_one / has_many
macros like Active Record does. We don't need to pay attention to this.
Instead of guessing what a node is based on what we can see in the file,
we are using an exclude glob because it is too hard to know if a class
is an Active Record or not without guessing.
@gmcgibbon
Copy link
Member Author

@rafaelfranca does this approach align with your request for changes?

@zumkorn
Copy link

zumkorn commented Apr 29, 2024

@gmcgibbon @rafaelfranca is there any reason why we can't merge this PR?

@gmcgibbon
Copy link
Member Author

@zumkorn no, thanks for the reminder. I'll merge now!

@rafaelfranca if you have any additional feedback let's fix forward.

@gmcgibbon gmcgibbon merged commit 11f86d2 into main May 7, 2024
20 checks passed
@gmcgibbon gmcgibbon deleted the support_non_ar_association branch May 7, 2024 19:13
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.

[Bug Report] has_many relationship for serializers create false positive violations
4 participants