rint 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a88bdceba9428f2c280c4c402720ec1e64339f50
4
+ data.tar.gz: 2c07c6a3ed81db32e97964dbb616581f23f9cd23
5
+ SHA512:
6
+ metadata.gz: 44067cd1e8c048866b797480e638c48dbe5227394b9f12fab6cb24ee5aa4468ecf3fa8abb3eceeba2860d317ba7bfa1c512c4b4fd57201f16adb8910e6aca048
7
+ data.tar.gz: afa0e5e6cce4f038b147f47b98b1fc8efff5a2e1960148d041f1e91be77c7bdf06fed91c5686195642b1265a199324211b7337da953951129110374a24e9af7a
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rint.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) <2015> <James Lopez>
2
+
3
+
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
+
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ THE SOFTWARE.
26
+
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Rint (Ruby Interface)
2
+
3
+ rint provides a way to implement behaviour defined by Interface files, warning when the desired behaviour is missing.
4
+
5
+ ### Example:
6
+
7
+ ```ruby
8
+ require 'interface'
9
+ module Playable
10
+ include Interface
11
+
12
+ def initialize
13
+ must_implement :play, :play_quietly
14
+ end
15
+ end
16
+
17
+ require 'playable'
18
+ class Instrument
19
+ implements Playable
20
+ end
21
+
22
+ Instrument.new #will throw: Interface::Error::NotImplementedError: Expected Instrument to implement play for interface Playable
23
+ ```
24
+
25
+ There is also a CLI to generate the interfaces from the command line:
26
+ ```sh
27
+ $ rint c Playable play play_quietly
28
+ ```
29
+ will generate lib/playable.rb (namespaces are also supported).
30
+
31
+ ### Goals
32
+
33
+ Duck typing can be evil if not used correctly. While Ruby applications can get a good level of confidence about issues arisen by duck typing, the fear of a method missing exception or constant changes to a class may lead the developer to use safety checks such as respond_to? or raise Errors when a method is missing. This implementation of rint wraps what other static languages use and encapsulates the safety check in a common place, also making explicit the behaviour through the word "implements" and expecting the developer to guess the behaviour of a class without looking at docs or partially implemented code. It also provides a centralised way to implement the interface pattern without having the code throwing an error in a hidden method.
34
+
35
+ ### Version
36
+ 0.1.0
37
+
38
+ ### Options
39
+
40
+ The environment variable DISABLE_RUBY_INTERFACE can be set to 1 in order to globally disable the interfaces - this also means that no Exception will get thrown. This might be particularly useful in production for performance reasons if we are confident enough through tests that the interfaces are all implemented.
41
+
42
+ ### Installation
43
+
44
+ Add it to your Gemfile:
45
+
46
+ gem 'rint'
47
+
48
+ and run
49
+
50
+ ```sh
51
+ $ bundle install
52
+ ```
53
+
54
+ ### Contributing
55
+
56
+ Fork it
57
+ Create your feature branch (git checkout -b my-new-feature)
58
+ Commit your changes (git commit -am 'Add some feature')
59
+ Push to the branch (git push origin my-new-feature)
60
+ Create new Pull Request
61
+ Enjoy!
62
+
63
+
64
+ License
65
+ ----
66
+
67
+ MIT
68
+
69
+ **Free Software, Hell Yeah!**
70
+
71
+ Copyright 2015 James Lopez https://github.com/bluegod/rint
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/bin/rint ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'generators/interface_generator.rb'
3
+ InterfaceGenerator.start
@@ -0,0 +1,11 @@
1
+ class Module
2
+ def implements(*args)
3
+ prepend(*args) unless disabled_interface?
4
+ end
5
+
6
+ private
7
+
8
+ def disabled_interface?
9
+ ENV['DISABLE_RUBY_INTERFACE'] == '1'
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ require 'thor'
2
+ class InterfaceGenerator < Thor::Group
3
+ include Thor::Actions
4
+
5
+ def self.source_root
6
+ File.dirname(__FILE__)
7
+ end
8
+
9
+ def check_arguments
10
+ return unless args.size < 3 || command != 'c'
11
+ puts 'Use: rint c <class> <methods>'
12
+ puts 'Example: rint c MyApp::MyClass method_one method_two'
13
+ exit
14
+ end
15
+
16
+ def define_instance_vars
17
+ @name = name
18
+ @file_name = underscore(@name.dup)
19
+ @methods = methods
20
+ end
21
+
22
+ def create_interface_file
23
+ template('templates/generic_interface.tt', "lib/#{@file_name}.rb")
24
+ end
25
+
26
+ private
27
+
28
+ def underscore(word)
29
+ word.gsub!(/::/, '/')
30
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
31
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
32
+ word.tr!('-', '_')
33
+ word.downcase!
34
+ word
35
+ end
36
+
37
+ def methods
38
+ args[2..-1].map { |m| ":#{m}" }.join(', ')
39
+ end
40
+
41
+ def name
42
+ args[1]
43
+ end
44
+
45
+ def command
46
+ args.first
47
+ end
48
+ end
@@ -0,0 +1,8 @@
1
+ require 'interface/interface'
2
+ module <%= @name %>
3
+ include Interface
4
+
5
+ def initialize
6
+ must_implement <%= @methods %>
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module Interface
2
+ module Error
3
+ # Raised when a method has not been implemented by a class that
4
+ # has used the implements <InterfaceName> method.
5
+ class NotImplementedError < NoMethodError
6
+ def initialize(class_name:, method_name:, interface_name:)
7
+ super(error_message(class_name, method_name, interface_name), method_name)
8
+ end
9
+
10
+ private
11
+
12
+ def error_message(class_name, method_name, interface_name)
13
+ "Expected #{class_name} to implement #{method_name} for interface #{interface_name}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require 'interface/error/not_implemented_error'
2
+
3
+ module Interface
4
+ module Helpers
5
+ # Errors raised here identify the class_name that is not implementing
6
+ # the method required by the Interface.
7
+ def must_implement(*args)
8
+ args.each do |method_name|
9
+ next if respond_to? method_name
10
+ raise Interface::Error::NotImplementedError.new(
11
+ class_name: self.class.name,
12
+ method_name: method_name,
13
+ interface_name: self.class.ancestors.first
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Interface
2
+ VERSION = '0.1.0'
3
+ end
data/lib/interface.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "interface/helpers"
2
+ require 'core_ext/module'
3
+
4
+ module Interface
5
+ include Interface::Helpers
6
+ end
data/rint.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
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 = 'rint'
8
+ spec.version = Interface::VERSION
9
+ spec.authors = ['James Lopez']
10
+ spec.email = ['james@jameslopez.es']
11
+ spec.license = 'MIT'
12
+
13
+ spec.summary = 'Ruby interfaces made simple'
14
+ spec.description = 'Provides interface abstraction and implementation to Ruby apps'
15
+ spec.homepage = 'https://github.com/bluegod/rint'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "bin"
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.10'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec', '~> 3.3'
25
+ spec.add_dependency 'thor', '~> 0.19'
26
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rint
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Lopez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-13 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.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.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: '3.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.19'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.19'
69
+ description: Provides interface abstraction and implementation to Ruby apps
70
+ email:
71
+ - james@jameslopez.es
72
+ executables:
73
+ - rint
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".travis.yml"
80
+ - Gemfile
81
+ - LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - bin/rint
85
+ - lib/core_ext/module.rb
86
+ - lib/generators/interface_generator.rb
87
+ - lib/generators/templates/generic_interface.tt
88
+ - lib/interface.rb
89
+ - lib/interface/error/not_implemented_error.rb
90
+ - lib/interface/helpers.rb
91
+ - lib/interface/version.rb
92
+ - rint.gemspec
93
+ homepage: https://github.com/bluegod/rint
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.4.8
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Ruby interfaces made simple
117
+ test_files: []