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

Sort the gathered controller helper includes in dsl/compilers/action_controller_helpers.rb #2202

Closed
wants to merge 1 commit into from

Conversation

shoffing
Copy link

Motivation

We run tapioca dsl as part of our CI process. We noticed that when we made a change to one Rails controller, we would sometimes get different include orderings being generated in completely unrelated controllers. The only thing that would change is the ordering of the helper include's.

Tapioca should sort the gathered include's so that the output is deterministic here.

I'm not sure about the initial motivation of doing the reverse here, is there any risk to making this change? Like, is there a reason the includes were ordered in this fashion to begin with? I believe the ordering is completely arbitrary; for our project, after making this change, there were a TON of RBI file updates, but srb tc still passed fine. So it seems like the ordering is arbitrary for our project, at least.

Implementation

Call .sort on the array of qualified names at the end of def gather_includes(mod).

Tests

I have included a new test which sorts Bravo/Alpha/Charlie helpers to => Alpha/Bravo/Charlie.


Note: I'm using IntelliJ, and so I've also included a change to .gitignore to omit my editor's files. Please let me know if you need that to go into its own separate PR instead!

@shoffing shoffing requested a review from a team as a code owner February 12, 2025 21:51
@paracycle
Copy link
Member

paracycle commented Feb 12, 2025

I'm not sure about the initial motivation of doing the reverse here, is there any risk to making this change? Like, is there a reason the includes were ordered in this fashion to begin with?

Yes, there very much a reason for doing it this way, since it is the only way so can properly represent module mixing in the right way.

Consider this:

module A
  def foo = "A"
end

module B
  def foo = "B"
end

class C
  include A
  include B
end

class D
  include B
  include A
end

C.new.foo # => "B"
D.new.foo # => "A"

C.ancestors # => [C, B, A, Object, Kernel, BasicObject]
D.ancestors # => [D, A, B, Object, Kernel, BasicObject]

So you need to walk the ancestors up to collect them and serialize the includes in reverse to get the include order correct.

I believe the ordering is completely arbitrary; for our project, after making this change, there were a TON of RBI file updates, but srb tc still passed fine. So it seems like the ordering is arbitrary for our project, at least.

The ordering is definitely not arbitrary. If you are seeing different orderings, then it might be about some load ordering differences in your application that changes how helper modules are loaded.

@shoffing
Copy link
Author

Thank you for the quick response and great explanation! So it seems this is working as intended, happy to close this PR. Tracking down why exactly the load order changed will be difficult with our large Rails app, and not worth it to investigate this slight annoyance. We'll just accept the DSL RBI changes tapioca suggests moving forward.

@shoffing shoffing closed this Feb 12, 2025
@shoffing shoffing deleted the sort-controller-includes branch February 13, 2025 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants