subclass_must_implement 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: be7eacd344df936c6557036eed810d353b476445
4
+ data.tar.gz: f7c20318294fc06bb3ff92a2776d81f7cc8fb5d6
5
+ SHA512:
6
+ metadata.gz: 5de082a47ac63d76765acfa7bbb2777c7a067ba91861903862dd4b2430b380fd0addbe3d79bdf809780861b124cbbc8f9d3043dce4b8cc3814cd23925a91ebeb
7
+ data.tar.gz: 3aec63e7c84a7983315504ff8e0fefd81ade0bc02bf4555f2f81891e5b4ee4e97dda9a2a2157b71a36f571c2580b778aa56b80cca191c2e2a1a9ec13567e2af2
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .ruby-version
24
+
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --color
2
+ --profile
3
+ --backtrace
4
+ --format documentation
5
+ --require spec_helper
@@ -0,0 +1 @@
1
+ subclass_must_implement
@@ -0,0 +1,35 @@
1
+ require "simplecov-rcov-text"
2
+ require "colorize"
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
5
+ SimpleCov::Formatter::RcovTextFormatter,
6
+ SimpleCov::Formatter::HTMLFormatter
7
+ ])
8
+
9
+ SimpleCov.start do
10
+ add_filter "/spec/"
11
+
12
+ # Fail the build when coverage is < 100%:
13
+ at_exit do
14
+ SimpleCov.result.format!
15
+ actual = SimpleCov.result.covered_percent
16
+ if actual < 100 then # FAIL
17
+ msg = "\nLow coverage: "
18
+ msg << "#{actual}%".colorize(:red)
19
+ msg << " is " << "under".colorize(:red) << " the threshold: "
20
+ msg << "#{100}%.".colorize(:green)
21
+ msg << "\n"
22
+ $stderr.puts msg
23
+ exit 1
24
+ else # PASS
25
+ # Precision: three decimal places:
26
+ actual_trunc = (actual * 1000).floor / 1000.0
27
+ msg = "\nCoverage: "
28
+ msg << "#{actual}%".colorize(:green)
29
+ msg << " is " << "at".colorize(:green) << " the threshold: "
30
+ msg << "#{100}%.".colorize(:green)
31
+ msg << "\n"
32
+ $stdout.puts msg
33
+ end
34
+ end
35
+ end
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 HornsAndHooves
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 all
13
+ 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 THE
21
+ SOFTWARE.
@@ -0,0 +1,75 @@
1
+ # SubclassMustImplement
2
+
3
+ There are circumstances when it is desirable to specify certain methods as abstract, i.e. it is the responsibility of any subclass to implement them.
4
+ Getting a `MethodMIssing` is not helpful; an error that explicitly explains that the missing method is required by contract will save much time.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'subclass_must_implement'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install yourself as:
17
+
18
+ $ gem install subclass_must_implement
19
+
20
+ ## Usage
21
+
22
+ Either `include SubclassMustImplement` or `extend SubclassMustImplement` in your base class.
23
+ Then call `subclass_must_implement` with a list of required method names as symbols.
24
+ You can optionally pass in a custom error message using the `err_message` named argument.
25
+
26
+ Example 1:
27
+
28
+ ```ruby
29
+ class BaseFoo
30
+ include SubclassMustImplement
31
+
32
+ subclass_must_implement :foo, :bar, :baz
33
+ end
34
+
35
+ class Foo < BaseFoo
36
+ def foo
37
+ :foo
38
+ end
39
+ end
40
+
41
+ f = Foo.new
42
+ f.foo # returns :foo
43
+ f.bar # raises a NotImplementedError that "bar" must be implemented in the subclass
44
+ f.baz # raises a NotImplementedError that "baz" must be implemented in the subclass
45
+ f.qux # raises a MethodMissing
46
+ ```
47
+
48
+ Example 2:
49
+
50
+ ```ruby
51
+ class BaseBar
52
+ extend SubclassMustImplement
53
+
54
+ subclass_must_implement :foo, :bar, err_message: "Version expected!!!"
55
+ end
56
+
57
+ class Bar < BaseBar
58
+ def bar
59
+ :bar
60
+ end
61
+ end
62
+
63
+ b = Bar.new
64
+ b.bar # return :bar
65
+ b.foo # raises a NotImplementedError with the specified error message "Version expected!!!"
66
+ ```
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it ( https://github.com/[my-github-username]/subclass_must_implement/fork )
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create a new Pull Request
75
+ 6. Make sure all the test pass and your changes have test coverage!
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ rescue LoadError
7
+ end
@@ -0,0 +1,74 @@
1
+ # Either `include SubclassMustImplement` or `extend SubclassMustImplement` in your base class.
2
+ # Then call `subclass_must_implement` with a list of required method names as symbols.
3
+ # You can optionally pass in a custom error message using the `err_message` named argument.
4
+ #
5
+ # Example 1:
6
+ #
7
+ # class BaseFoo
8
+ # include SubclassMustImplement
9
+ #
10
+ # subclass_must_implement :foo, :bar, :baz
11
+ # end
12
+ #
13
+ # class Foo < BaseFoo
14
+ # def foo
15
+ # :foo
16
+ # end
17
+ # end
18
+ #
19
+ # f = Foo.new
20
+ # f.foo # returns :foo
21
+ # f.bar # raises a NotImplementedError that "bar" must be implemented in the subclass
22
+ # f.baz # raises a NotImplementedError that "baz" must be implemented in the subclass
23
+ # f.qux # raises a MethodMissing
24
+ #
25
+ # Example 2:
26
+ #
27
+ # class BaseBar
28
+ # extend SubclassMustImplement
29
+ #
30
+ # subclass_must_implement :foo, :bar, err_message: "Version expected!!!"
31
+ # end
32
+ #
33
+ # class Bar < BaseBar
34
+ # def bar
35
+ # :bar
36
+ # end
37
+ # end
38
+ #
39
+ # b = Bar.new
40
+ # b.bar # return :bar
41
+ # b.foo # raises a NotImplementedError with the specified error message "Version expected!!!"
42
+ #
43
+ module SubclassMustImplement
44
+
45
+ # Injects the `subclass_must_implement` macro
46
+ def self.included(base)
47
+ base.extend ClassMethods
48
+ end
49
+
50
+ # Injects the `subclass_must_implement` macro
51
+ def self.extended(base)
52
+ base.extend ClassMethods
53
+ end
54
+
55
+ # Returns the Gem version as a string
56
+ def self.version
57
+ "0.0.1"
58
+ end
59
+
60
+ # The class level macros are defined here.
61
+ module ClassMethods
62
+
63
+ # Defines a method for each method name that raises a NotImplementedError when called.
64
+ # Pass in a custom error message if desired using the err_message named argument.
65
+ def subclass_must_implement(*method_names, err_message: nil)
66
+ method_names.each do |method_name|
67
+ err = err_message.nil? ? "`#{method_name}` must be implemented in a subclass." : "#{err_message}"
68
+ define_method method_name do |*_|
69
+ raise NotImplementedError, err
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,89 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
5
+ RSpec.configure do |config|
6
+ # rspec-expectations config goes here. You can use an alternate
7
+ # assertion/expectation library such as wrong or the stdlib/minitest
8
+ # assertions if you prefer.
9
+ config.expect_with :rspec do |expectations|
10
+ # This option will default to `true` in RSpec 4. It makes the `description`
11
+ # and `failure_message` of custom matchers include text for helper methods
12
+ # defined using `chain`, e.g.:
13
+ # be_bigger_than(2).and_smaller_than(4).description
14
+ # # => "be bigger than 2 and smaller than 4"
15
+ # ...rather than:
16
+ # # => "be bigger than 2"
17
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
18
+ end
19
+
20
+ # rspec-mocks config goes here. You can use an alternate test double
21
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
22
+ config.mock_with :rspec do |mocks|
23
+ # Prevents you from mocking or stubbing a method that does not exist on
24
+ # a real object. This is generally recommended, and will default to
25
+ # `true` in RSpec 4.
26
+ mocks.verify_partial_doubles = true
27
+ end
28
+
29
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
30
+ # have no way to turn it off -- the option exists only for backwards
31
+ # compatibility in RSpec 3). It causes shared context metadata to be
32
+ # inherited by the metadata hash of host groups and examples, rather than
33
+ # triggering implicit auto-inclusion in groups with matching metadata.
34
+ config.shared_context_metadata_behavior = :apply_to_host_groups
35
+
36
+ # The settings below are suggested to provide a good initial experience
37
+ # with RSpec, but feel free to customize to your heart's content.
38
+ =begin
39
+ # This allows you to limit a spec run to individual examples or groups
40
+ # you care about by tagging them with `:focus` metadata. When nothing
41
+ # is tagged with `:focus`, all examples get run. RSpec also provides
42
+ # aliases for `it`, `describe`, and `context` that include `:focus`
43
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
44
+ config.filter_run_when_matching :focus
45
+
46
+ # Allows RSpec to persist some state between runs in order to support
47
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
48
+ # you configure your source control system to ignore this file.
49
+ config.example_status_persistence_file_path = "spec/examples.txt"
50
+
51
+ # Limits the available syntax to the non-monkey patched syntax that is
52
+ # recommended. For more details, see:
53
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
54
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
55
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
56
+ config.disable_monkey_patching!
57
+
58
+ # This setting enables warnings. It's recommended, but in some cases may
59
+ # be too noisy due to issues in dependencies.
60
+ config.warnings = true
61
+
62
+ # Many RSpec users commonly either run the entire suite or an individual
63
+ # file, and it's useful to allow more verbose output when running an
64
+ # individual spec file.
65
+ if config.files_to_run.one?
66
+ # Use the documentation formatter for detailed output,
67
+ # unless a formatter has already been configured
68
+ # (e.g. via a command-line flag).
69
+ config.default_formatter = "doc"
70
+ end
71
+
72
+ # Print the 10 slowest examples and example groups at the
73
+ # end of the spec run, to help surface which specs are running
74
+ # particularly slow.
75
+ config.profile_examples = 10
76
+
77
+ # Run specs in random order to surface order dependencies. If you find an
78
+ # order dependency and want to debug it, you can fix the order by providing
79
+ # the seed, which is printed after each run.
80
+ # --seed 1234
81
+ config.order = :random
82
+
83
+ # Seed global randomization in this process using the `--seed` CLI option.
84
+ # Setting this allows you to use `--seed` to deterministically reproduce
85
+ # test failures related to randomization by passing the same `--seed` value
86
+ # as the one that triggered the failure.
87
+ Kernel.srand config.seed
88
+ =end
89
+ end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe SubclassMustImplement do
4
+
5
+ class BaseFoo
6
+ include SubclassMustImplement
7
+
8
+ subclass_must_implement :foo, :bar, :baz
9
+ end
10
+
11
+ class Foo < BaseFoo
12
+ def foo
13
+ :foo
14
+ end
15
+ end
16
+
17
+ class BaseBar
18
+ extend SubclassMustImplement
19
+
20
+ subclass_must_implement :version, :sub_version, err_message: "Version expected!!!"
21
+ end
22
+
23
+ class Bar < BaseBar
24
+ def version
25
+ SubclassMustImplement.version
26
+ end
27
+ end
28
+
29
+ let(:foo) { Foo.new }
30
+ let(:bar) { Bar.new }
31
+
32
+ context "module included" do
33
+ it "will raise a not implemented error if any required method is not implemented in the subclass" do
34
+ expect { foo.bar }.to raise_error(NotImplementedError, "`bar` must be implemented in a subclass.")
35
+ expect { foo.baz }.to raise_error(NotImplementedError, "`baz` must be implemented in a subclass.")
36
+ end
37
+
38
+ it "will not raise an error if a requred method is implemented by the subclass" do
39
+ expect(foo.foo).to eq(:foo)
40
+ end
41
+ end
42
+
43
+ context "module extended" do
44
+ it "will raise a not implemented error if any required method is not implemented in the subclass" do
45
+ expect { bar.sub_version }.to raise_error(NotImplementedError, "Version expected!!!")
46
+ end
47
+
48
+ it "will not raise an error if a requred method is implemented by the subclass" do
49
+ expect(bar.version).to eq(described_class.version)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'subclass_must_implement'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "subclass_must_implement"
8
+ spec.version = SubclassMustImplement.version
9
+ spec.authors = ["Arthur Shagall"]
10
+ spec.email = ["arthur.shagall@gmail.com"]
11
+ spec.summary = %q{Make abstract methods explicit.}
12
+ spec.description = %q{Auto-generate abstract method stubs to mark them as required to be implemented in subclasses.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.15"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "simplecov"
25
+ spec.add_development_dependency "simplecov-rcov-text"
26
+ spec.add_development_dependency "colorize"
27
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: subclass_must_implement
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Arthur Shagall
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov-rcov-text
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: colorize
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Auto-generate abstract method stubs to mark them as required to be implemented
98
+ in subclasses.
99
+ email:
100
+ - arthur.shagall@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rspec"
107
+ - ".ruby-gemset"
108
+ - ".simplecov"
109
+ - Gemfile
110
+ - LICENSE
111
+ - README.md
112
+ - Rakefile
113
+ - lib/subclass_must_implement.rb
114
+ - spec/spec_helper.rb
115
+ - spec/subclass_must_implement_spec.rb
116
+ - subclass_must_implement.gemspec
117
+ homepage: ''
118
+ licenses:
119
+ - MIT
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 2.6.14
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Make abstract methods explicit.
141
+ test_files:
142
+ - spec/spec_helper.rb
143
+ - spec/subclass_must_implement_spec.rb