ruby_interface 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba848be8e36fb2a53a4c0a80f692d15cacb22771
4
- data.tar.gz: 7ab704e3372b468c2303149c02ae46acd66a8809
3
+ metadata.gz: d9b8ffa291917e451bb903aef5276f566b7294f1
4
+ data.tar.gz: 87b777bdd6a33288a62a1e15675ea6e816fdf3f9
5
5
  SHA512:
6
- metadata.gz: 815bf8051224c890dbf1b54a24746456eff1289a2b5107b44dadd8cfe33193740ab979b31497686f7f4416a34e6318ac4b486ed4dcc7d81de920cd88b57302c5
7
- data.tar.gz: 10392958eaa591e652479e6684672b724f9e25328eefd14553e96afc4f178216c1aaa90b41933344e7d93353b16fb8c18bbc30a149320bdcbfdb48e786dc4da4
6
+ metadata.gz: 1ea17d4036a0ebd057ec6d9d632f8dbcc8f568e94db4ce5cbb152e0bb36ea4626a3cb2e597c260ee48489f99ed34370046b686a5bee762afac3611ff625cfdc7
7
+ data.tar.gz: 1ffdcb7225e371e5cf7300ef7b1e7e88ba50929962a8cfdca61ecde77f6b0be13489cca1dee61c3c7885556443d6ad9550be33ae454fc7fe032c762ab4d52f5e
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # 0.2.0
2
+ - Update handling for anonymous classes:
3
+ - Fix tracepoint never being disabled
4
+ - Create an implementation that uses `class_eval`
5
+ - Make sure that any existing inherited hooks don't get overriden.
6
+
7
+ # 0.1.0
8
+ - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby_interface (0.1.0)
4
+ ruby_interface (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  When a class is interpreted and does not have the required methods, it throws an error.
4
4
 
5
5
  Caveats:
6
- - creating anonymous classes will not work with this gem as they use an alternate mechanism.
6
+ - Creating anonymous classes requires the user to use `class_eval` to define methods.
7
7
 
8
8
  ## Installation
9
9
 
@@ -23,6 +23,8 @@ Or install it yourself as:
23
23
 
24
24
  ## Usage
25
25
 
26
+ ### Named Classes
27
+
26
28
  ```ruby
27
29
  class SpaceShip
28
30
  include RubyInterface
@@ -35,15 +37,31 @@ end
35
37
  # => NotImplementedError, 'Expected Enterprise to define #engine, #computer'
36
38
  ```
37
39
 
40
+ If a class is redefined, the presence of required methods will not be checked.
41
+
42
+ ### Anonymous classes
43
+
44
+ ```ruby
45
+ class SpaceShip
46
+ include RubyInterface
47
+
48
+ defines :engine, :computer
49
+ end
50
+
51
+ space_ship = Class.new(SpaceShip)
52
+ space_ship.class_eval { }
53
+ # => NotImplementedError, 'Expected Enterprise to define #engine, #computer'
54
+ ```
55
+
56
+ After the first `class_eval`, the rest of the calls to it will not check whether methods are defined.
57
+ Unfortunately, right now, `class_eval` has to be called to check whether the methods are defined,
58
+ pending resolution of https://bugs.ruby-lang.org/issues/12696.
59
+
38
60
  ## Development
39
61
 
40
62
  After checking out the repo, run `bin/setup` to install dependencies.
41
63
  You can also run `bin/console` for an interactive prompt that will allow you to experiment.
42
64
 
43
- To install this gem onto your local machine, run `bundle exec rake install`.
44
- To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
45
- 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).
46
-
47
65
  ## Contributing
48
66
 
49
67
  Bug reports and pull requests are welcome on GitHub at https://github.com/kklimuk/ruby_interface.
@@ -1,3 +1,3 @@
1
1
  module RubyInterface
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -4,6 +4,15 @@ require 'awesome_print'
4
4
  module RubyInterface
5
5
  def self.included(klass)
6
6
  klass.extend ClassMethods
7
+
8
+ klass.class_eval do
9
+ singleton_class.send(:alias_method, :_old_inherited, :inherited) if respond_to?(:inherited)
10
+ end
11
+
12
+ def klass.inherited(child)
13
+ child.name.nil? ? anonymous_class_definition(child) : named_class_definition(child)
14
+ _old_inherited(child) if respond_to?(:_old_inherited)
15
+ end
7
16
  end
8
17
 
9
18
  module ClassMethods
@@ -12,17 +21,37 @@ module RubyInterface
12
21
  @methods_to_define += args
13
22
  end
14
23
 
15
- def inherited(klass)
16
- trace = TracePoint.new(:end) do |point|
17
- next unless point.self == klass
18
- missing_methods = @methods_to_define - klass.instance_methods(false)
19
- trace.disable
24
+ def track_required_methods(child)
25
+ missing_methods = @methods_to_define - child.instance_methods(false)
20
26
 
21
- next if missing_methods.empty?
27
+ return if missing_methods.empty?
28
+
29
+ message = "Expected #{child.name || 'anonymous class'} to define "
30
+ message << missing_methods.map { |method| "##{method}" }.join(', ')
31
+ raise NotImplementedError, message
32
+ end
22
33
 
23
- message = "Expected #{klass.name} to define "
24
- message << missing_methods.map { |method| "##{method}" }.join(', ')
25
- raise NotImplementedError, message
34
+ private
35
+
36
+ def anonymous_class_definition(child)
37
+ klass = self
38
+ [:class_exec, :class_eval].each do |method|
39
+ old_method = "_old_#{method}".to_sym
40
+ child.singleton_class.send(:alias_method, old_method, method)
41
+
42
+ child.define_singleton_method method do |*args, &block|
43
+ send old_method, *args, &block
44
+ klass.track_required_methods(child)
45
+ child.singleton_class.send(:alias_method, method, old_method)
46
+ end
47
+ end
48
+ end
49
+
50
+ def named_class_definition(child)
51
+ trace = TracePoint.new(:end) do |point|
52
+ next unless point.self == child
53
+ trace.disable
54
+ track_required_methods child
26
55
  end
27
56
  trace.enable
28
57
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_interface
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Klimuk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-21 00:00:00.000000000 Z
11
+ date: 2016-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -78,6 +78,7 @@ files:
78
78
  - ".ruby-gemset"
79
79
  - ".ruby-version"
80
80
  - ".travis.yml"
81
+ - CHANGELOG.md
81
82
  - Gemfile
82
83
  - Gemfile.lock
83
84
  - LICENSE.txt