ruby_contracts 0.1.1 → 0.2.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.
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
@@ -1,3 +1,3 @@
1
1
  module RubyContracts
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -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 self.extended(base)
13
- base.instance_eval "@__contracts = {:before => [], :after => []}"
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
- if ENV['ENABLE_ASSERTION'] && (!@__contracts[:before].empty? || !@__contracts[:after].empty?)
36
- __contracts_copy = @__contracts
37
- @__contracts = {:before => [], :after => []}
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 = __contracts_copy[:before].reduce("") do |code, contract|
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 = __contracts_copy[:after].reduce("") do |code, contract|
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.1.1
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: 2012-09-03 00:00:00.000000000 Z
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.