oop-interface 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: adcb81e23d62c55d873632321e2337e89782b773
4
+ data.tar.gz: b9ee510a2f6846034b1a2b985112444b16eaaf21
5
+ SHA512:
6
+ metadata.gz: 25d092dee5f35034b820fc3a8a8d62f52750a6f5b8694fdbb70128992473f7022438e9089ff065de69e361def682c34e8cb6792b2188842179e237945b7627b6
7
+ data.tar.gz: 75c1712764d1eea63644652db2ae5359c9455028c25d1fbe761663b03ce70d9a44c8c80699d133e6d3c74f1ebe7a0670e3efdba712f98bf7852af24752aafedd
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.16.0
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in interface.gemspec
6
+ gemspec
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ oop-interface (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.3)
10
+ rake (10.5.0)
11
+ rspec (3.7.0)
12
+ rspec-core (~> 3.7.0)
13
+ rspec-expectations (~> 3.7.0)
14
+ rspec-mocks (~> 3.7.0)
15
+ rspec-core (3.7.0)
16
+ rspec-support (~> 3.7.0)
17
+ rspec-expectations (3.7.0)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.7.0)
20
+ rspec-mocks (3.7.0)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.7.0)
23
+ rspec-support (3.7.0)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ bundler (~> 1.16)
30
+ oop-interface!
31
+ rake (~> 10.0)
32
+ rspec (~> 3.0)
33
+
34
+ BUNDLED WITH
35
+ 1.16.0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Andrzej Sliwa
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.
@@ -0,0 +1,85 @@
1
+ # OOP Interface for Ruby
2
+
3
+ This gem takes inspiration from https://github.com/shuber/interface and
4
+ borrow some implementation details from it, extend it and modify available api.
5
+
6
+ Credits for [Sean Huber](https://github.com/shuber)
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'oop-interface'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install interface
23
+
24
+ ## Usage
25
+
26
+ Example usage:
27
+
28
+ require "interface"
29
+
30
+ module Order
31
+ def submit; end
32
+ def add_position(_position); end
33
+ end
34
+
35
+ module Saver
36
+ def save; end
37
+ end
38
+
39
+ class OrderImpl
40
+ include Interface
41
+ implements Order, Saver
42
+ def submit
43
+ :submitted
44
+ end
45
+
46
+ def save(some: 5)
47
+ "save #{some}"
48
+ end
49
+ end
50
+
51
+ > OrderImpl.interfaces
52
+ => [Order, Saver]
53
+ > OrderImpl.unimplemented_methods
54
+ => {Order=>[:add_position]}
55
+ > saver = OrderImpl.new.as(Saver)
56
+ => #<Saver:70247745038560>
57
+ > saver.submit
58
+ NoMethodError: undefined method `submit' for #<Saver:70247745038560>
59
+ > saver.save(some: 8)
60
+ "save 8"
61
+ > OrderImpl.new.add_position
62
+ NotImplementedError: OrderImpl needs to implement 'add_position' for interface Order
63
+ > OrderImpl.new.is_a? Saver
64
+ => true
65
+ > OrderImpl.new.is_a? Order
66
+ => true
67
+
68
+ The main idea behind of implementation of such gem, was limiting the scope.
69
+ For example when you are implementing Aggregate Root (following Domain Driven Design)
70
+ in ActiveRecord, you would like to expose only public contract methods to ensure that
71
+ Aggregate Root boundaries are not crossed by using directly relations or ActiveRecord methods.
72
+
73
+ ## Development
74
+
75
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
76
+
77
+ 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
78
+
79
+ ## Contributing
80
+
81
+ Bug reports and pull requests are welcome on GitHub at https://github.com/andrzejsliwa/interface.
82
+
83
+ ## License
84
+
85
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "interface"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,36 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "interface/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "oop-interface"
8
+ spec.version = Interface::VERSION
9
+ spec.authors = ["Andrzej Sliwa", "Sean Huber"]
10
+ spec.email = ["andrzej.sliwa@i-tool.eu"]
11
+
12
+ spec.summary = %q{Simple implementation of interfaces in Ruby}
13
+ spec.description = %q{Simple implementation of interfaces in Ruby}
14
+ spec.homepage = "http://github.com/andrzejsliwa/oop-interface"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against " \
23
+ "public gem pushes."
24
+ end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ f.match(%r{^(test|spec|features)/})
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ spec.add_development_dependency "bundler", "~> 1.16"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "rspec", "~> 3.0"
36
+ end
@@ -0,0 +1,87 @@
1
+ require "interface/version"
2
+
3
+ module Interface
4
+ UnknownInterface = Class.new(StandardError)
5
+ module Abstract
6
+ def self.extended(interface)
7
+ interface.class_eval do
8
+ instance_methods(false).each do |method|
9
+ define_method(method) do |*args, &block|
10
+ methods = [:super, :method_missing]
11
+ begin
12
+ send(methods.shift, *args, &block)
13
+ rescue NoMethodError
14
+ if methods.empty?
15
+ raise NotImplementedError.new("#{self.class} needs to implement '#{method}' for interface #{interface}")
16
+ else
17
+ args.unshift(method.to_sym)
18
+ retry
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.included(base)
28
+ base.extend ClassMethods
29
+ end
30
+
31
+ module ClassMethods
32
+ def implements(*modules)
33
+ modules.flatten.reverse!.each { |mod| include mod.extend(Abstract) }
34
+ end
35
+ alias_method :implement, :implements
36
+
37
+ def interfaces
38
+ klass = is_a?(Class) ? self : self.class
39
+ klass.included_modules.select { |mod| mod.is_a?(Abstract) }
40
+ end
41
+
42
+ def unimplemented_methods
43
+ interfaces.inject({}) do |hash, interface|
44
+ methods = unimplemented_methods_for(interface)
45
+ methods.empty? ? hash : hash.merge!(interface => methods)
46
+ end
47
+ end
48
+
49
+ def unimplemented_methods_for(interface)
50
+ interface.instance_methods(false).reject do |method|
51
+ !method_defined?(method.to_sym) || instance_method(method.to_sym).owner != interface
52
+ end.sort.map(&:to_sym)
53
+ end
54
+ end
55
+
56
+ def as(interface)
57
+ raise UnknownInterface.new(interface) unless self.class.interfaces.include?(interface)
58
+ Class.new do
59
+ def initialize(target)
60
+ @target = target
61
+ end
62
+
63
+ interface.instance_methods.select do |method|
64
+ interface.instance_method(method.to_sym).owner == interface
65
+ end.each do |method|
66
+ define_method(method) do |*args, &block|
67
+ @target.public_send(method, *args, &block)
68
+ end
69
+ end
70
+
71
+ [:is_a?, :kind_of?, :instance_of?].each do |type_method|
72
+ define_method(type_method) do |target, &block|
73
+ return true if target == interface
74
+ super
75
+ end
76
+ end
77
+
78
+ define_method(:inspect) do
79
+ "#<#{interface.name}:#{self.object_id}>"
80
+ end
81
+
82
+ def to_s
83
+ inspect
84
+ end
85
+ end.new(self)
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module Interface
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oop-interface
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrzej Sliwa
8
+ - Sean Huber
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2018-01-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.16'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.16'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '10.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.0'
56
+ description: Simple implementation of interfaces in Ruby
57
+ email:
58
+ - andrzej.sliwa@i-tool.eu
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - ".travis.yml"
66
+ - Gemfile
67
+ - Gemfile.lock
68
+ - LICENSE.txt
69
+ - README.md
70
+ - Rakefile
71
+ - bin/console
72
+ - bin/setup
73
+ - interface.gemspec
74
+ - lib/interface.rb
75
+ - lib/interface/version.rb
76
+ homepage: http://github.com/andrzejsliwa/oop-interface
77
+ licenses:
78
+ - MIT
79
+ metadata:
80
+ allowed_push_host: https://rubygems.org
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.6.11
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Simple implementation of interfaces in Ruby
101
+ test_files: []