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

MONGOID-5654 [Monkey Patch Removal] Move Hash#__consolidate__ into Mongoid::Contextual #5689

Closed

Conversation

johnnyshields
Copy link
Contributor

@johnnyshields johnnyshields commented Aug 26, 2023

Fixes MONGOID-5654

Hash#__consolidate__ monkey-patch method is used only once in the entire Mongoid codebase, in a private capacity inside Contextual::Mongo class. There is no reason to monkey-patch the kernel Hash class for this.

This PR does the following:

  • Move the method into Contextual::Mongo as a private method.
  • Move the associated Hash#mongoize_for private method, which is only called once inside __consolidate__
  • Rename and refactor the methods.
  • TODO: Move private method tests to cover a public method behavior.

The method name has __ prefix so we can assume this is an internal only method that is safe to remove.

…codebase, in a private capacity inside Contextual::Mongo class, so there is no reason to monkey-patch Hash for this.

The method name has __ prefix so we can assume this is an internal only method that is safe to remove.
@johnnyshields johnnyshields changed the title Move Hash#__consolidate__ monkey patch Refactor: Move Hash#__consolidate__ monkey patch into Mongoid::Contextual Aug 26, 2023
@johnnyshields johnnyshields changed the title Refactor: Move Hash#__consolidate__ monkey patch into Mongoid::Contextual MONGOID-5654 - Refactor: Move Hash#__consolidate__ monkey patch into Mongoid::Contextual Aug 27, 2023
@johnnyshields
Copy link
Contributor Author

The failing spec for ruby-2.7 is not related to this PR.

Copy link
Contributor

@jamis jamis left a comment

Choose a reason for hiding this comment

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

@johnnyshields - I love the idea of pulling this out of Hash. However, when it comes to testing a private method, it raises a bit of a red flag for me. I think that if the method needs to be tested in isolation, it should probably be pulled out into its own module, much like you did for Embedded.traverse. What do you think?

@johnnyshields
Copy link
Contributor Author

johnnyshields commented Sep 2, 2023

Hmm... I interpret the guideline as "private methods are not required to be tested, but it is ok to test them if we judge it benefits stability." Private methods make future refactoring much easier. Making a method public solely because we'd like to test it would be "the tail wagging the dog." Since we already have the tests, let's keep them.

Re: Embedded.traverse, the method needed to be public because it was called by multiple unrelated classes.

I am all for refactoring Mongoid::Contextual into smaller classes, but it's beyond the scope of this PR.

@johnnyshields johnnyshields changed the title MONGOID-5654 - Refactor: Move Hash#__consolidate__ monkey patch into Mongoid::Contextual MONGOID-5654 - [Monkey Patch Removal] Move Hash#__consolidate__ into Mongoid::Contextual Sep 3, 2023
@johnnyshields johnnyshields changed the title MONGOID-5654 - [Monkey Patch Removal] Move Hash#__consolidate__ into Mongoid::Contextual MONGOID-5654 [Monkey Patch Removal] Move Hash#__consolidate__ into Mongoid::Contextual Sep 3, 2023
@jamis
Copy link
Contributor

jamis commented Sep 5, 2023

I understand your point, but I still am strongly opposed to writing tests for methods with private visibility. I know there are instances of this in the Mongoid codebase, but when I encounter them, I've been rewriting them.

If you feel delegation is too heavy-handed for this feature, there are a couple of other options you might consider:

  1. Make the method public, but prefix the name with an underscore and document it as @api private. The tests can then invoke it without resorting to send.
  2. Instead of testing the method directly, test it indirectly by observing its effects in other, publicly exposed methods.

Also, just to clarify my original point: moving the method to a new module so it can be tested in isolation does not mean the new module and method must be (or even should be) part of Mongoid's public API. In many instances, I think it makes sense to document the new module and/or method with @api private. As you mentioned, it definitely makes refactoring easier.

There are probably other ways to approach this, as well, but adding new tests (or refactoring old tests) that directly invoke private methods is a non-starter for me.

@johnnyshields
Copy link
Contributor Author

johnnyshields commented Sep 5, 2023

@jamis would you accept tests for the public update_documents method which use RSpec's mock expectation syntax instead? Specifically I would be calling update_documents then asserting the view (which is a Mongo Ruby Driver object) is receiving a certain argument hash. I think this is fair game, what do you think?

@johnnyshields johnnyshields marked this pull request as draft September 5, 2023 15:32
@jamis
Copy link
Contributor

jamis commented Sep 5, 2023

@johnnyshields -- yeah, that sounds reasonable. Thanks for meeting me halfway. :)

@johnnyshields
Copy link
Contributor Author

OK cool, will do. By the way, most of the monkey patch PRs do not include private method tests.

@jamis
Copy link
Contributor

jamis commented Nov 6, 2023

@johnnyshields -- I've opened a new PR that builds on your work here (#5740), and I'm going to close this PR in favor of that one. I've described the reasoning for it on that PR. Thanks for your work on this!

@jamis jamis closed this Nov 6, 2023
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.

2 participants