ruby_contracts 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -0
- data/lib/ruby_contracts/version.rb +1 -1
- data/lib/ruby_contracts.rb +38 -8
- metadata +2 -2
data/README.md
CHANGED
@@ -38,6 +38,14 @@ Run this sample with `ENABLE_ASSERTION=1 bundle exec ruby example.rb`.
|
|
38
38
|
|
39
39
|
Without the environment variable `ENABLE_ASSERTION` you have zero overhead and zero verification.
|
40
40
|
|
41
|
+
## Class inheritance
|
42
|
+
|
43
|
+
When you inherit a class that contains contracts, all contracts must be satified by the subclass.
|
44
|
+
|
45
|
+
If you override a method, you still have to satisfy the existing contracts for this method and you can add some others.
|
46
|
+
|
47
|
+
See the [issue #1](https://github.com/nicoolas25/ruby_contracts/issues/1) for an example.
|
48
|
+
|
41
49
|
## Contributing
|
42
50
|
|
43
51
|
1. Fork it
|
data/lib/ruby_contracts.rb
CHANGED
@@ -3,14 +3,40 @@ require "ruby_contracts/version"
|
|
3
3
|
module Contracts
|
4
4
|
class Error < Exception ; end
|
5
5
|
|
6
|
+
def self.empty_contracts
|
7
|
+
{:before => [], :after => []}
|
8
|
+
end
|
9
|
+
|
6
10
|
module DSL
|
7
11
|
def self.included(base)
|
8
12
|
base.extend Contracts::DSL::ClassMethods
|
13
|
+
base.__contracts_initialize
|
9
14
|
end
|
10
15
|
|
11
16
|
module ClassMethods
|
12
|
-
def
|
13
|
-
|
17
|
+
def inherited(subclass)
|
18
|
+
super
|
19
|
+
subclass.__contracts_initialize
|
20
|
+
end
|
21
|
+
|
22
|
+
def __contracts_initialize
|
23
|
+
@__contracts = Contracts.empty_contracts
|
24
|
+
@__contracts_for = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def __contracts_for(name, current_contracts=nil)
|
28
|
+
inherited_contracts = ancestors[1..-1].reduce(Contracts.empty_contracts) do |c, klass|
|
29
|
+
ancestor_hash = klass.instance_variable_get('@__contracts_for') || {}
|
30
|
+
c[:before] += ancestor_hash.has_key?(name) ? ancestor_hash[name][:before] : []
|
31
|
+
c[:after] += ancestor_hash.has_key?(name) ? ancestor_hash[name][:after] : []
|
32
|
+
c
|
33
|
+
end
|
34
|
+
current_contracts = @__contracts_for[name] || current_contracts || Contracts.empty_contracts
|
35
|
+
|
36
|
+
contracts = Contracts.empty_contracts
|
37
|
+
contracts[:before] = current_contracts[:before] + inherited_contracts[:before]
|
38
|
+
contracts[:after] = current_contracts[:after] + inherited_contracts[:after]
|
39
|
+
contracts
|
14
40
|
end
|
15
41
|
|
16
42
|
def __contract_failure!(name, message, result, *args)
|
@@ -32,16 +58,20 @@ module Contracts
|
|
32
58
|
end
|
33
59
|
|
34
60
|
def method_added(name)
|
35
|
-
|
36
|
-
|
37
|
-
|
61
|
+
super
|
62
|
+
|
63
|
+
return unless ENV['ENABLE_ASSERTION']
|
64
|
+
return if @__contracts_for.has_key?(name)
|
38
65
|
|
66
|
+
__contracts = @__contracts_for[name] ||= __contracts_for(name, @__contracts)
|
67
|
+
@__contracts = Contracts.empty_contracts
|
68
|
+
|
69
|
+
if !__contracts[:before].empty? || !__contracts[:after].empty?
|
39
70
|
original_method_name = "#{name}__with_contracts"
|
40
71
|
define_method(original_method_name, instance_method(name))
|
41
72
|
|
42
|
-
|
43
73
|
count = 0
|
44
|
-
before_contracts =
|
74
|
+
before_contracts = __contracts[:before].reduce("") do |code, contract|
|
45
75
|
type, *args = contract
|
46
76
|
case type
|
47
77
|
when :type
|
@@ -71,7 +101,7 @@ module Contracts
|
|
71
101
|
end
|
72
102
|
end
|
73
103
|
|
74
|
-
after_contracts =
|
104
|
+
after_contracts = __contracts[:after].reduce("") do |code, contract|
|
75
105
|
type, *args = contract
|
76
106
|
case type
|
77
107
|
when :type
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_contracts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-06-11 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Micro DSL to add pre & post condition to methods. It try to bring some
|
15
15
|
design by contract in the Ruby world.
|