enhance_module 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3b42420b1bdad023c55ee134a235222b91ef59047beff9400b50c655ae3ce9c5
4
+ data.tar.gz: 5b525c55d013c21f9858a733723ae73d45587c5cb5a2edcdfabddf00d0114b67
5
+ SHA512:
6
+ metadata.gz: fe7feec8977b7f9be052797fd8e7b4fb6fac01bbccab4dbf66bda667f523bd9f443f3e2389bb7828a8965eecf642e7f1cd767d7a8ed83da4314f2a50d52de249
7
+ data.tar.gz: b453a287ead76bf33f44443893b51bcb711f7832ed69879688f7ce0db01354913c540ff8929eda736f141e69b4fea17edb7eb29e10ce863f713506b971e0ca09
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.0
3
+
4
+ Style/StringLiterals:
5
+ EnforcedStyle: double_quotes
6
+
7
+ Style/StringLiteralsInInterpolation:
8
+ EnforcedStyle: double_quotes
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-07-15
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Mateusz Drewniak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # EnhanceModule
2
+
3
+ This gem adds a typed, sorbet-friendly way of extending object instances with modules.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add enhance_module
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install enhance_module
14
+
15
+
16
+ ## Motivation
17
+
18
+ Ruby supports extending objects with methods from modules.
19
+ It's one of the most unique and cool features of Ruby.
20
+
21
+ ```rb
22
+ module Foo
23
+ def foo = "foo!"
24
+ end
25
+
26
+ obj = Object.new
27
+ obj.extend(Foo)
28
+ obj.foo #=> foo!
29
+ ```
30
+
31
+ Unfortunately [sorbet](https://sorbet.org/) does not support this feature.
32
+ Its type system in unable to fathom what is going on when an object is extended.
33
+
34
+ ```rb
35
+ # typed: true
36
+
37
+ module Foo
38
+ extend T::Sig
39
+
40
+ sig { void }
41
+ def foo = "foo!"
42
+ end
43
+
44
+ obj = Object.new
45
+ obj.extend(Foo)
46
+ obj.foo #! Method `foo` does not exist on `Object`
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ This gem adds a new sorbet-friendly way of extending objects.
52
+
53
+ ```rb
54
+ # typed: true
55
+
56
+ require 'enhance_module'
57
+
58
+ module Foo
59
+ extend T::Sig
60
+
61
+ # boilerplate that needs to be added
62
+ # to your module to make it support
63
+ # extending objects
64
+ class << self
65
+ include EnhanceModule
66
+ has_attached_class! { { fixed: Foo } }
67
+ end
68
+
69
+ # define your methods
70
+ sig { void }
71
+ def foo = "foo!"
72
+ end
73
+
74
+ obj = Object.new
75
+ # works the same as `obj.extend(Foo)`
76
+ # but sorbet understands it
77
+ extended_obj = Foo.enhance(obj)
78
+ extended_obj.foo # ok!
79
+
80
+ T.reveal_type(extended_obj) # T.all(Foo, Object)
81
+ ```
82
+
83
+ The new `Foo.enhance` method works like `extend` and
84
+ returns an intersection type that consists of the argument's class
85
+ and the module that is being extended.
86
+
87
+ ## Development
88
+
89
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
90
+
91
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
92
+
93
+ ## Contributing
94
+
95
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Verseth/enhance_module.
96
+
97
+ ## License
98
+
99
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EnhanceModule
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ require "sorbet-runtime"
5
+ require_relative "enhance_module/version"
6
+
7
+ # This module can be included in the singleton class of a module
8
+ # to make it able to extend objects in a typed, sorbet-friendly way.
9
+ #
10
+ # require "enhance_module"
11
+ #
12
+ # module MyModule
13
+ # class << self
14
+ # include EnhanceModule
15
+ # has_attached_class! { { fixed: MyModule } }
16
+ # end
17
+ #
18
+ # sig { void }
19
+ # def my_module_method; end
20
+ # end
21
+ #
22
+ # class MyClass
23
+ # extend T::Sig
24
+ #
25
+ # sig { void }
26
+ # def my_class_method; end
27
+ # end
28
+ #
29
+ # obj = MyClass.new
30
+ # obj.my_class_method # ok!
31
+ #
32
+ # # extend the object with `MyModule`
33
+ # extended_obj = MyModule.enhance(obj)
34
+ # extended_obj.my_class_method # ok!
35
+ # extended_obj.my_module_method # ok!
36
+ #
37
+ module EnhanceModule
38
+ extend T::Sig
39
+ extend T::Generic
40
+ has_attached_class!
41
+
42
+ sig do
43
+ type_parameters(:T)
44
+ .params(obj: T.type_parameter(:T))
45
+ .returns(T.all(T.attached_class, T.type_parameter(:T)))
46
+ end
47
+ def enhance(obj)
48
+ T.unsafe(obj).extend(self)
49
+ end
50
+
51
+ module ClassMethods
52
+ include T::Sig
53
+ include T::Generic
54
+ end
55
+ mixes_in_class_methods(ClassMethods)
56
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enhance_module
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mateusz Drewniak
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-07-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sorbet-runtime
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0.5'
27
+ description: This gem adds a sorbet-friendly way of extending object instances with
28
+ modules.
29
+ email:
30
+ - matmg24@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".rubocop.yml"
36
+ - CHANGELOG.md
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - lib/enhance_module.rb
41
+ - lib/enhance_module/version.rb
42
+ homepage: https://github.com/Verseth/ruby-enhance_module
43
+ licenses:
44
+ - MIT
45
+ metadata:
46
+ homepage_uri: https://github.com/Verseth/ruby-enhance_module
47
+ source_code_uri: https://github.com/Verseth/ruby-enhance_module
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 3.1.0
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.5.15
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: This gem adds a sorbet-friendly way of extending object instances with modules.
67
+ test_files: []