-
Notifications
You must be signed in to change notification settings - Fork 67
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
Relax activesupport dependency #236
Relax activesupport dependency #236
Conversation
We're substituting it with dry-inflector, which is a zero deps, stand-alone, imperative inflector. We're also explicitly requiring `i18n` dependency in order to not relay on the indirect dependency through `activesupport`.
This is a great PR! I thank you for the work you put into it, I am going to merge it. You wrote:
I am all for doing this, but we should move LightService under an org, and have the gem, and this other one with Rails generator should be there. What do you think? |
@@ -18,6 +18,9 @@ Gem::Specification.new do |gem| | |||
gem.required_ruby_version = '>= 2.6.0' | |||
|
|||
gem.add_runtime_dependency("activesupport", ">= 4.0.0") | |||
gem.add_runtime_dependency("i18n") | |||
gem.add_runtime_dependency("dry-inflector") | |||
gem.add_runtime_dependency("structured_warnings") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I missed these additions. So instead of having just AS, we are adding 3 more dependencies.
I wish we could achieve the same functionality with no additional gems. But maybe I am just asking too much.
I wonder what ppl think about this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We’re adding only 2 more dependencies, since i18n is already in through AS at the moment.
I explicitly required it as a dep in order to have a functioning gemspec even considering AS removal and without leaving remainders for future work.
Speaking about the balance between AS and the two new gems: my sentiment is that with the two gems we bring less code than with AS alone. We should analyze it more scientifically tho.
For sure we have the achievement of not having a big rails ecosystem’s gem, leaving LS more desirable as cross-framework and franework-less solution.
Speaking of deprecation warnings: I previously tried to implement them using Gem::Deprecate, but it resulted to me as an inadequate tool out of its absolute standard concept. Hard to adapt. I think it would be feasible to write a dedicated Logger and implement some logic inside it in order to achieve a simple custom deprecation warner. This would be intended as a pragmatic and simpler alternative to structured_warning gem.
If you’d like to check a draft implementation I could try to write a separate draft PR in the second half of July.
About the inflector I’m really opinionated: I would not even try to reinvent the wheel on such a matter. Moreover I sincerely invite you to read dry-inflector’s source code: it’s astonishing small, tidy and simple; and it’s a completely standalone gem. Obviously we could copy that few methods we need, but pro and cons considered I think it’s a solid choice to bring it in.
Thanks for the feedback 😊
@gee-forr - what do you think? |
Reading again the code, I’d like to do a couple of little refinements. But I’ll let the discussion go further before to do anything else. I think, consolidated the choice to split the code, the organization would be the more elegant solution and the better guarantee for the community. I don’t think an organization would be that big management complication, but it’s a personal point of view and a matter to think about before going all-in. |
@adomokos - I really appreciate you asking for my opinion ❤️ @pioneerskies - Thank you so much for the PR and the interest. I haven't looked at the actual changes yet, but here are my opinions, off the cuff.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good... one note about the re-requiring of structured_warnings
but everything else looks good.
@@ -1,5 +1,6 @@ | |||
require 'logger' | |||
require 'active_support/core_ext/string' | |||
require 'i18n' | |||
require 'structured_warnings' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're requiring structured_warnings
in light-service.rb
we probably don't need to re-require them again in the rest of the files, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totaly agree: OR in the manifest OR in single files. In both places is just confusing and conceptually wrong.
expect do | ||
class OrganizerIncludingLS | ||
include LightService::Organizer | ||
end | ||
end.to warn_with(StructuredWarnings::DeprecatedMethodWarning, expected_msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are great! We should remember to remove them when the actual removal takes place. 👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given this discussion #236 (comment) it's still to take a decision about the use of that library.
That said and considering that whatever implementation will be it will have a test: remembering to remove deprecation from code will bring a red CI. That should be a good post-it to remove the test too ;)
@adomokos - if you're happy to move forward with this, I am. I think adding two more dependencies is a small and temporary price to pay for what it unlocks for the future. If you want to move forward with the org + separate rails gem, then, @pioneerskies could I ask that you also add deprecation warnings to the rails generators? |
I'd be happy to do, once decisions will be made, but I'd opt to do it in a dedicated PR: current PR opens the question, but it doesn't want to directly move away generators. A new PR using this one as backbone would be clearer and tidier IMO. |
@@ -9,7 +9,7 @@ def self.extended(base_class) | |||
def self.included(base_class) | |||
msg = "including LightService::Action is deprecated. " \ | |||
"Please use `extend LightService::Action` instead" | |||
ActiveSupport::Deprecation.warn(msg) | |||
warn(StructuredWarnings::DeprecatedMethodWarning, msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and wherever we thrown a warn
, if this gem will remain in, I'd like to have a class LightService::Deprecation < StructuredWarnings::Base; end
to use insted of directly expose the gem's built-in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm completely for that course of action.
I am afk, but will pick this up, thoroughly review it, and merge it next week. Thanks for your patience there! |
I'll be on vacation starting from 1st until 19th July. In the mean time feel free to do what it's needed with "my" code. I've already annoted and subscribed desirable updates and expressed all the opinions I had to. So feel free to act w/o my intervention in the coming weeks :) Thank you all so much. |
I like this, will merge this. It's not fixing a critical bug. We'll get this in. |
Hello @pioneerskies! Sorry for keeping this PR open for so long. I thought about this while I was away. How hard would it be not to introduce two (albeit small) gems to light-service, but leverage pure Ruby to accomplish this functionality? I'd love to have LS be outside gem-dependent-free if possible in the future. |
Hi there, AFAIK deprecations could be simplified down to a custom The inflector instead would be different: Conclusion: a custom "deprecation logger" + a savvy copy-paste should result in a quite small and not complex goal to achieve. |
I see adding 3 ruby gems with this PR:
I do like the intent of this PR, but I am now hesitant to merge it. We are adding quite a bit of dependency, and I don't see the path of cutting out What do you think about that? I am happy to create a new repo for |
I like to re-underline that IMO we should be able to avoid I know this i18n-related discourse may seem OT, but I consider part of the "dependent-free" path you are picturing. Coming on the spot of your comment now :)
I'm not only okay with that, but I'm really happy with that. My intention was to open a discussion bringing a practical substrate to it.
I think we're trading dependencies here, more than adding. The biggest fault of this PR, in my opinion, is that it moves from one dep from another w/o layering them with first party wrappers. Wrappers would be a refactoring pattern making possible to plug in/out external deps or first party code w/o touching other parts of code. E.g.: # lib/light-service/inflector.rb
require "dry/inflector"
module LightService
class Inflector
attr_reader :inflector
def initialize
@inflector = Dry::Inflector.new
end
def unerscore(string)
inflector.underscore(string)
end
def pluralize(string)
inflector.underscore(string)
end
end
end # lib/light-service/localization_adapter.rb
module LightService
class LocalizationAdapter
attr_reader :inflector
def initialize
@inflector = LightService::Inflector
end
# [...]
def i18n_scope_from_class(action_class, type)
"#{inflector.underscore(action_class.name)}.light_service.#{inflector.pluralize(type.to_s)}"
end
end
end This way we'd be able to swap in/out different external deps or get rid of them and write our own or anything we'd like to, with a single point of responsibility
That path would be for sure the more profitable one. Current PR had just the goal to make things move forward given the actual code base and to poll the interest around the proposed mid-term goal. Keep this one open as draft and we'll understand if it will be better to update it or to close it for a new one.
|
If and when we go with the route of a separate gem version for |
Closing this, as AS was removed with this PR. |
Given #226 and the bleeding announced in #153 (comment) the goal of this PR is to relax the dependency this gem has on ActiveSupport.
Why not removing it completely?
It turns that the only part of the gem which continues to require ActiveSupport are the Rails generators. They were introduced recently in #194. Thus I cannot afford to remove ActiveSupport with a one-shot PR. Nor I want to take decisions about how to continue from now on w/o including maintainer and community into the discussion.
Is it worth to add more dependencies w/o removing ActiveSupport?
Ideally not, but from a transitional perspective, yes. Now we have a single well scoped feature requiring ActiveSupport instead of having code bites spread all over the code base.
I'm bringing the gem in a more free and easier to manage position in regard of AS dep.
What about the two new dependencies?
I added https://dry-rb.org/gems/dry-inflector/ and https://github.com/schmidt/structured_warnings
Both were choosen because they are small, dependency-free gems with single functionality.
dry-inflector
is from the (beloved by me) dry-rb ecosystem (https://dry-rb.org/). Neat, iper-atomic and well written. It is the Hanami inflector.structured_warnings
is a neat, very small gem; it has not been updated recently, but IMO it doesn't need to be. It works on ruby 3.1 and its approach is simple and far (FAR) less polluting than ActiveSupport's one. I was able to implement a custom matcher forrspec
too, writing expressive tests. Moreover its interface made possible to do a surgical substitution in the actual code base.From my point of view, being the maintainer of the project, I'd think about splitting rails generators into a separate gem. This would enclose ActiveSupport and Rails-only things in cleaner context, easier to maintain. And the test suite of the "core" gem would lose all the complexity inherent to testing against all the possible AS versions.
I thought to open this one as a draft, but I decided to concretely propose something :) No problem turning it into draft or to use this just as a discussion desk and then close it.
Thanks for your attention.