adamantium 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/Gemfile +11 -6
- data/README.md +85 -14
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/site.reek +2 -1
- data/lib/adamantium.rb +59 -144
- data/lib/adamantium/class_methods.rb +20 -0
- data/lib/adamantium/freezer.rb +139 -0
- data/lib/adamantium/module_methods.rb +103 -0
- data/lib/adamantium/version.rb +1 -1
- data/spec/integration/adamantium_spec.rb +63 -0
- data/spec/unit/adamantium/dup_spec.rb +1 -1
- data/spec/unit/adamantium/flat/freezer_spec.rb +15 -0
- data/spec/unit/adamantium/freezer/class_methods/get_spec.rb +33 -0
- data/spec/unit/adamantium/freezer/class_methods/parse_spec.rb +31 -0
- data/spec/unit/adamantium/freezer/deep/class_methods/call_spec.rb +81 -0
- data/spec/unit/adamantium/freezer/deep/class_methods/freeze_spec.rb +14 -0
- data/spec/unit/adamantium/{class_methods/freeze_object_spec.rb → freezer/flat/class_methods/call_spec.rb} +10 -2
- data/spec/unit/adamantium/freezer/flat/class_methods/freeze_spec.rb +14 -0
- data/spec/unit/adamantium/memoize_spec.rb +2 -2
- data/spec/unit/adamantium/memoized_spec.rb +3 -3
- data/spec/unit/adamantium/module_methods/freezer_spec.rb +15 -0
- data/spec/unit/adamantium/module_methods/memoize_spec.rb +68 -7
- data/tasks/metrics/ci.rake +1 -1
- data/tasks/metrics/heckle.rake +10 -9
- metadata +25 -6
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -21,12 +21,17 @@ platform :jruby do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
group :metrics do
|
24
|
-
gem 'flay',
|
25
|
-
gem 'flog',
|
26
|
-
gem 'reek',
|
27
|
-
gem 'roodi',
|
28
|
-
gem 'yardstick',
|
29
|
-
gem '
|
24
|
+
gem 'flay', '~> 1.4.2'
|
25
|
+
gem 'flog', '~> 2.5.1'
|
26
|
+
gem 'reek', '~> 1.2.8', :github => 'dkubb/reek'
|
27
|
+
gem 'roodi', '~> 2.1.0'
|
28
|
+
gem 'yardstick', '~> 0.7.0'
|
29
|
+
gem 'simplecov'
|
30
|
+
|
31
|
+
platforms :ruby_18, :ruby_19 do
|
32
|
+
# this indirectly depends on ffi which does not build on ruby-head
|
33
|
+
gem 'yard-spellcheck', '~> 0.1.5'
|
34
|
+
end
|
30
35
|
|
31
36
|
platforms :mri_18 do
|
32
37
|
gem 'arrayfields', '~> 4.7.4' # for metric_fu
|
data/README.md
CHANGED
@@ -26,24 +26,95 @@ Examples
|
|
26
26
|
require 'adamantium'
|
27
27
|
require 'securerandom'
|
28
28
|
|
29
|
-
class
|
29
|
+
class Example
|
30
|
+
# Inclusion of Adamantium defaults to deep freeze behavior
|
31
|
+
# of constructor and memoizer
|
32
|
+
|
30
33
|
include Adamantium
|
31
34
|
|
32
|
-
|
33
|
-
|
35
|
+
# Instance and attributes (ivars) are frozen per default
|
36
|
+
# Example:
|
37
|
+
#
|
38
|
+
# object = Example.new
|
39
|
+
# object.frozen? # => true
|
40
|
+
# object.attribute.frozen? # => true
|
41
|
+
#
|
42
|
+
def initialize
|
43
|
+
@attribute = "foo bar"
|
34
44
|
end
|
35
|
-
|
36
|
-
|
45
|
+
attr_reader :attribute
|
46
|
+
|
47
|
+
# Memoized method with deeply frozen value (default)
|
48
|
+
# Example:
|
49
|
+
#
|
50
|
+
# object = Example.new
|
51
|
+
# object.random => ["abcdef"]
|
52
|
+
# object.random => ["abcdef"]
|
53
|
+
# object.random.frozen? => true
|
54
|
+
# object.random[0].frozen? => true
|
55
|
+
#
|
56
|
+
def random
|
57
|
+
[SecureRandom.hex(6)]
|
58
|
+
end
|
59
|
+
memoize :random
|
60
|
+
|
61
|
+
# Memoized method with non frozen value
|
62
|
+
# Example:
|
63
|
+
#
|
64
|
+
# object = Example.new
|
65
|
+
# object.buffer # => <StringIO:abcdef>
|
66
|
+
# object.buffer # => <StringIO:abcdef>
|
67
|
+
# object.buffer.frozen? # => false
|
68
|
+
#
|
69
|
+
def buffer
|
70
|
+
StringIO.new
|
71
|
+
end
|
72
|
+
memoize :buffer, :freezer => :noop
|
73
|
+
|
74
|
+
# Memoized method with nondeeply frozen value
|
75
|
+
# Example:
|
76
|
+
#
|
77
|
+
# object = Example.new
|
78
|
+
# object.random2 => ["abcdef"]
|
79
|
+
# object.random2 => ["abcdef"]
|
80
|
+
# object.random2.frozen? => true
|
81
|
+
# object.random2[0].frozen? => false
|
82
|
+
#
|
83
|
+
def random2
|
84
|
+
[SecureRandom.hex(6)]
|
85
|
+
end
|
86
|
+
memoize :random2, :freezer => :flat
|
37
87
|
end
|
38
88
|
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
#
|
46
|
-
|
89
|
+
class FlatExample
|
90
|
+
# Inclusion of Adamantium::Flat defaults do non deep frozen behavior
|
91
|
+
# for memoizer and constructor
|
92
|
+
|
93
|
+
include Adamantium::Flat
|
94
|
+
|
95
|
+
# Instace is frozen but attribute is not
|
96
|
+
# object = FlatExample.new
|
97
|
+
# object.frozen? # => true
|
98
|
+
# object.attribute.frozen? # => false
|
99
|
+
def initialize
|
100
|
+
@attribute = "foo bar"
|
101
|
+
end
|
102
|
+
attr_reader :attribute
|
103
|
+
|
104
|
+
# Memoized method with flat frozen value (default)
|
105
|
+
# Example:
|
106
|
+
#
|
107
|
+
# object = Example.new
|
108
|
+
# object.random => ["abcdef"]
|
109
|
+
# object.random => ["abcdef"]
|
110
|
+
# object.random.frozen? => true
|
111
|
+
# object.random[0].frozen? => false
|
112
|
+
#
|
113
|
+
def random
|
114
|
+
[SecureRandom.hex(6)]
|
115
|
+
end
|
116
|
+
memoize :random
|
117
|
+
end
|
47
118
|
```
|
48
119
|
|
49
120
|
Credits
|
@@ -68,7 +139,7 @@ License
|
|
68
139
|
-------
|
69
140
|
|
70
141
|
Copyright (c) 2009-2012 Dan Kubb
|
71
|
-
Copyright (c) 2012 Markus Schirp
|
142
|
+
Copyright (c) 2012 Markus Schirp
|
72
143
|
|
73
144
|
Permission is hereby granted, free of charge, to any person obtaining
|
74
145
|
a copy of this software and associated documentation files (the
|
data/config/flay.yml
CHANGED
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 21.1
|
data/config/site.reek
CHANGED
data/lib/adamantium.rb
CHANGED
@@ -6,6 +6,35 @@ module Adamantium
|
|
6
6
|
# Storage for memoized methods
|
7
7
|
Memory = Class.new(::Hash)
|
8
8
|
|
9
|
+
# Defaults to less strict defaults
|
10
|
+
module Flat
|
11
|
+
|
12
|
+
# Return flat freezer
|
13
|
+
#
|
14
|
+
# @return [Freezer::Flat]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
#
|
18
|
+
def freezer
|
19
|
+
Freezer::Flat
|
20
|
+
end
|
21
|
+
|
22
|
+
# Hook called when module is included
|
23
|
+
#
|
24
|
+
# @param [Class,Module] descendant
|
25
|
+
#
|
26
|
+
# @return [self]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
def self.included(descendant)
|
30
|
+
super
|
31
|
+
descendant.send(:include, Adamantium)
|
32
|
+
descendant.extend(self)
|
33
|
+
|
34
|
+
self
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
9
38
|
# Hook called when module is included
|
10
39
|
#
|
11
40
|
# @param [Module] descendant
|
@@ -15,51 +44,11 @@ module Adamantium
|
|
15
44
|
#
|
16
45
|
# @api private
|
17
46
|
def self.included(descendant)
|
18
|
-
super
|
19
47
|
descendant.extend ModuleMethods if descendant.kind_of?(Module)
|
20
48
|
descendant.extend ClassMethods if descendant.kind_of?(Class)
|
21
49
|
self
|
22
50
|
end
|
23
51
|
|
24
|
-
# Attempt to freeze an object
|
25
|
-
#
|
26
|
-
# @example using a value object
|
27
|
-
# Adamantium.freeze_object(12345) # => noop
|
28
|
-
#
|
29
|
-
# @example using a normal object
|
30
|
-
# Adamantium.freeze_object({}) # => duplicate & freeze object
|
31
|
-
#
|
32
|
-
# @param [Object] object
|
33
|
-
# the object to freeze
|
34
|
-
#
|
35
|
-
# @return [Object]
|
36
|
-
# if supported, the frozen object, otherwise the object directly
|
37
|
-
#
|
38
|
-
# @api public
|
39
|
-
def self.freeze_object(object)
|
40
|
-
case object
|
41
|
-
when Numeric, TrueClass, FalseClass, NilClass, Symbol
|
42
|
-
object
|
43
|
-
else
|
44
|
-
freeze_value(object)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Returns a frozen value
|
49
|
-
#
|
50
|
-
# @param [Object] value
|
51
|
-
# a value to freeze
|
52
|
-
#
|
53
|
-
# @return [Object]
|
54
|
-
# if frozen, the value directly, otherwise a frozen copy of the value
|
55
|
-
#
|
56
|
-
# @api private
|
57
|
-
def self.freeze_value(value)
|
58
|
-
value.frozen? ? value : IceNine.deep_freeze(value.dup)
|
59
|
-
end
|
60
|
-
|
61
|
-
private_class_method :freeze_value
|
62
|
-
|
63
52
|
# Freeze the object
|
64
53
|
#
|
65
54
|
# @example
|
@@ -102,7 +91,10 @@ module Adamantium
|
|
102
91
|
#
|
103
92
|
# @api public
|
104
93
|
def memoize(name, value)
|
105
|
-
|
94
|
+
unless memory.key?(name)
|
95
|
+
store_memory(name, freeze_object(value))
|
96
|
+
end
|
97
|
+
|
106
98
|
self
|
107
99
|
end
|
108
100
|
|
@@ -129,6 +121,27 @@ private
|
|
129
121
|
@__memory ||= Memory.new
|
130
122
|
end
|
131
123
|
|
124
|
+
# Freeze object
|
125
|
+
#
|
126
|
+
# @param [Object] object
|
127
|
+
# an object to be frozen
|
128
|
+
#
|
129
|
+
# @return [Object]
|
130
|
+
#
|
131
|
+
# @api private
|
132
|
+
def freeze_object(object)
|
133
|
+
freezer.call(object)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Return class level freezer
|
137
|
+
#
|
138
|
+
# @return [#call]
|
139
|
+
#
|
140
|
+
# @api private
|
141
|
+
def freezer
|
142
|
+
self.class.freezer
|
143
|
+
end
|
144
|
+
|
132
145
|
# Store the value in memory
|
133
146
|
#
|
134
147
|
# @param [Symbol] name
|
@@ -142,108 +155,10 @@ private
|
|
142
155
|
#
|
143
156
|
# @api private
|
144
157
|
def store_memory(name, value)
|
145
|
-
memory[name] =
|
158
|
+
memory[name] = value
|
146
159
|
end
|
147
|
-
|
148
|
-
# Methods mixed in to adamantium modules
|
149
|
-
module ModuleMethods
|
150
|
-
|
151
|
-
# Hook called when module is included
|
152
|
-
#
|
153
|
-
# @param [Module] mod
|
154
|
-
# the module including ModuleMethods
|
155
|
-
#
|
156
|
-
# @return [self]
|
157
|
-
#
|
158
|
-
# @api private
|
159
|
-
def included(mod)
|
160
|
-
Adamantium.included(mod)
|
161
|
-
self
|
162
|
-
end
|
163
|
-
|
164
|
-
# Memoize a list of methods
|
165
|
-
#
|
166
|
-
# @example
|
167
|
-
# memoize :hash
|
168
|
-
#
|
169
|
-
# @param [Array<#to_s>] methods
|
170
|
-
# a list of methods to memoize
|
171
|
-
#
|
172
|
-
# @return [self]
|
173
|
-
#
|
174
|
-
# @api public
|
175
|
-
def memoize(*methods)
|
176
|
-
methods.each { |method| memoize_method(method) }
|
177
|
-
self
|
178
|
-
end
|
179
|
-
|
180
|
-
private
|
181
|
-
|
182
|
-
# Memoize the named method
|
183
|
-
#
|
184
|
-
# @param [#to_s] method
|
185
|
-
# a method to memoize
|
186
|
-
#
|
187
|
-
# @return [undefined]
|
188
|
-
#
|
189
|
-
# @api private
|
190
|
-
def memoize_method(method)
|
191
|
-
visibility = method_visibility(method)
|
192
|
-
define_memoize_method(method)
|
193
|
-
send(visibility, method)
|
194
|
-
end
|
195
|
-
|
196
|
-
# Define a memoized method that delegates to the original method
|
197
|
-
#
|
198
|
-
# @param [Symbol] method
|
199
|
-
# the name of the method
|
200
|
-
#
|
201
|
-
# @return [undefined]
|
202
|
-
#
|
203
|
-
# @api private
|
204
|
-
def define_memoize_method(method)
|
205
|
-
original = instance_method(method)
|
206
|
-
undef_method(method)
|
207
|
-
define_method(method) do |*args|
|
208
|
-
if memory.key?(method)
|
209
|
-
memoized(method)
|
210
|
-
else
|
211
|
-
store_memory(method, original.bind(self).call(*args))
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
# Return the method visibility of a method
|
217
|
-
#
|
218
|
-
# @param [String, Symbol] method
|
219
|
-
# the name of the method
|
220
|
-
#
|
221
|
-
# @return [String]
|
222
|
-
#
|
223
|
-
# @api private
|
224
|
-
def method_visibility(method)
|
225
|
-
if private_method_defined?(method) then 'private'
|
226
|
-
elsif protected_method_defined?(method) then 'protected'
|
227
|
-
else 'public'
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
end # module ModuleMethods
|
232
|
-
|
233
|
-
# Methods mixed in to adamantium classes
|
234
|
-
module ClassMethods
|
235
|
-
|
236
|
-
# Instantiate a new frozen object
|
237
|
-
#
|
238
|
-
# @example
|
239
|
-
# object = AdamantiumClass.new # object is frozen
|
240
|
-
#
|
241
|
-
# @return [Object]
|
242
|
-
#
|
243
|
-
# @api public
|
244
|
-
def new(*)
|
245
|
-
IceNine.deep_freeze(super)
|
246
|
-
end
|
247
|
-
|
248
|
-
end # module ClassMethods
|
249
160
|
end # module Adamantium
|
161
|
+
|
162
|
+
require 'adamantium/module_methods'
|
163
|
+
require 'adamantium/class_methods'
|
164
|
+
require 'adamantium/freezer'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Adamantium
|
2
|
+
|
3
|
+
# Methods mixed in to adamantium classes
|
4
|
+
module ClassMethods
|
5
|
+
|
6
|
+
# Instantiate a new frozen object
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# object = AdamantiumClass.new # object is frozen
|
10
|
+
#
|
11
|
+
# @return [Object]
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
def new(*)
|
15
|
+
freezer.freeze(super)
|
16
|
+
end
|
17
|
+
|
18
|
+
end # module ClassMethods
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module Adamantium
|
2
|
+
|
3
|
+
# Abstract base class for freezers
|
4
|
+
#
|
5
|
+
# TODO: Use dkubb/abstract_class?
|
6
|
+
#
|
7
|
+
# Better pattern for singleton inheritance/shared code
|
8
|
+
class Freezer
|
9
|
+
|
10
|
+
private_class_method :new
|
11
|
+
|
12
|
+
# Attempt to freeze an object
|
13
|
+
#
|
14
|
+
# @example using a value object
|
15
|
+
# Adamantium.freeze_object(12345) # => noop
|
16
|
+
#
|
17
|
+
# @example using a normal object
|
18
|
+
# Adamantium.freeze_object({}) # => duplicate & freeze object
|
19
|
+
#
|
20
|
+
# @param [Object] object
|
21
|
+
# the object to freeze
|
22
|
+
#
|
23
|
+
# @return [Object]
|
24
|
+
# if supported, the frozen object, otherwise the object directly
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
def self.call(object)
|
28
|
+
case object
|
29
|
+
when Numeric, TrueClass, FalseClass, NilClass, Symbol, Class, Module
|
30
|
+
object
|
31
|
+
else
|
32
|
+
freeze_value(object)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private_class_method :call
|
37
|
+
|
38
|
+
# Returns a frozen value
|
39
|
+
#
|
40
|
+
# @param [Object] value
|
41
|
+
# a value to freeze
|
42
|
+
#
|
43
|
+
# @return [Object]
|
44
|
+
# if frozen, the value directly, otherwise a frozen copy of the value
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
def self.freeze_value(value)
|
48
|
+
value.frozen? ? value : freeze(value.dup)
|
49
|
+
end
|
50
|
+
|
51
|
+
private_class_method :freeze_value
|
52
|
+
|
53
|
+
# Freezer that does not deep freeze
|
54
|
+
class Flat < self
|
55
|
+
|
56
|
+
# Freeze value
|
57
|
+
#
|
58
|
+
# @param [Object] value
|
59
|
+
#
|
60
|
+
# @return [undefined]
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
def self.freeze(value)
|
64
|
+
value.freeze
|
65
|
+
end
|
66
|
+
public_class_method :call
|
67
|
+
end
|
68
|
+
|
69
|
+
# Freezer that does deep freeze
|
70
|
+
class Deep < self
|
71
|
+
|
72
|
+
# Deep freeze value
|
73
|
+
#
|
74
|
+
# @param [Object] value
|
75
|
+
#
|
76
|
+
# @return [undefined]
|
77
|
+
#
|
78
|
+
# @api private
|
79
|
+
def self.freeze(value)
|
80
|
+
IceNine.deep_freeze(value)
|
81
|
+
end
|
82
|
+
public_class_method :call
|
83
|
+
end
|
84
|
+
|
85
|
+
Noop = lambda { |object| object }.freeze
|
86
|
+
|
87
|
+
# Error raised when freezer cannot be found
|
88
|
+
class UnknownFreezerError < RuntimeError; end
|
89
|
+
|
90
|
+
# Error raised when memoizer options contain unknown keys
|
91
|
+
class OptionError < RuntimeError; end
|
92
|
+
|
93
|
+
# Return freezer for name
|
94
|
+
#
|
95
|
+
# @param [Symbol] name
|
96
|
+
# a freezer name
|
97
|
+
#
|
98
|
+
# @return [#call]
|
99
|
+
#
|
100
|
+
# @api private
|
101
|
+
def self.get(name)
|
102
|
+
case name
|
103
|
+
when :noop
|
104
|
+
Noop
|
105
|
+
when :deep
|
106
|
+
Deep
|
107
|
+
when :flat
|
108
|
+
Flat
|
109
|
+
else
|
110
|
+
raise UnknownFreezerError, "Freezer with name #{name.inspect} is unknown"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Parse freezer options
|
115
|
+
#
|
116
|
+
# @param [Hash] options
|
117
|
+
# an options hash
|
118
|
+
#
|
119
|
+
# @return [#call]
|
120
|
+
# if freezer option was present
|
121
|
+
#
|
122
|
+
# @return [nil]
|
123
|
+
# otherwise
|
124
|
+
#
|
125
|
+
# @api private
|
126
|
+
#
|
127
|
+
def self.parse(options)
|
128
|
+
keys = options.keys - [:freezer]
|
129
|
+
|
130
|
+
unless keys.empty?
|
131
|
+
raise OptionError, "Unknown option key(s) for memoizer #{keys.inspect}"
|
132
|
+
end
|
133
|
+
|
134
|
+
return unless options.key?(:freezer)
|
135
|
+
|
136
|
+
get(options.fetch(:freezer))
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Adamantium
|
2
|
+
|
3
|
+
# Methods mixed in to adamantium modules
|
4
|
+
module ModuleMethods
|
5
|
+
|
6
|
+
# Hook called when module is included
|
7
|
+
#
|
8
|
+
# @param [Module] mod
|
9
|
+
# the module including ModuleMethods
|
10
|
+
#
|
11
|
+
# @return [self]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
def included(mod)
|
15
|
+
Adamantium.included(mod)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return default deep freezer
|
20
|
+
#
|
21
|
+
# @return [Freezer::Deep]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
#
|
25
|
+
def freezer
|
26
|
+
Freezer::Deep
|
27
|
+
end
|
28
|
+
|
29
|
+
# Memoize a list of methods
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# memoize :hash
|
33
|
+
#
|
34
|
+
# @param [Array<#to_s>] methods
|
35
|
+
# a list of methods to memoize
|
36
|
+
#
|
37
|
+
# @return [self]
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def memoize(*methods)
|
41
|
+
options = methods.last.kind_of?(Hash) ? methods.pop : {}
|
42
|
+
method_freezer = Freezer.parse(options) || freezer
|
43
|
+
methods.each { |method| memoize_method(method, method_freezer) }
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Memoize the named method
|
50
|
+
#
|
51
|
+
# @param [#to_s] method
|
52
|
+
# a method to memoize
|
53
|
+
# @param [#call] freezer
|
54
|
+
# a freezer for memoized values
|
55
|
+
#
|
56
|
+
# @return [undefined]
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
def memoize_method(method, freezer)
|
60
|
+
visibility = method_visibility(method)
|
61
|
+
define_memoize_method(method, freezer)
|
62
|
+
send(visibility, method)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define a memoized method that delegates to the original method
|
66
|
+
#
|
67
|
+
# @param [Symbol] method
|
68
|
+
# the name of the method
|
69
|
+
# @param [#call] freezer
|
70
|
+
# a freezer for memoized values
|
71
|
+
#
|
72
|
+
# @return [undefined]
|
73
|
+
#
|
74
|
+
# @api private
|
75
|
+
def define_memoize_method(method, freezer)
|
76
|
+
original = instance_method(method)
|
77
|
+
undef_method(method)
|
78
|
+
define_method(method) do |*args|
|
79
|
+
memory.fetch(method) do
|
80
|
+
value = original.bind(self).call(*args)
|
81
|
+
frozen = freezer.call(value)
|
82
|
+
store_memory(method, frozen)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return the method visibility of a method
|
88
|
+
#
|
89
|
+
# @param [String, Symbol] method
|
90
|
+
# the name of the method
|
91
|
+
#
|
92
|
+
# @return [Symbol]
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
def method_visibility(method)
|
96
|
+
if private_method_defined?(method) then :private
|
97
|
+
elsif protected_method_defined?(method) then :protected
|
98
|
+
else :public
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end # module ModuleMethods
|
103
|
+
end # module Adamantium
|
data/lib/adamantium/version.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adamantium do
|
4
|
+
let(:class_under_test) do
|
5
|
+
mixin = self.mixin
|
6
|
+
|
7
|
+
Class.new do
|
8
|
+
include mixin
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@attribute = Object.new
|
12
|
+
end
|
13
|
+
attr_reader :attribute
|
14
|
+
|
15
|
+
def memoized
|
16
|
+
[Object.new]
|
17
|
+
end
|
18
|
+
memoize :memoized
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'inherited' do
|
23
|
+
let(:mixin) { Adamantium::Flat }
|
24
|
+
|
25
|
+
subject { Class.new(class_under_test).new }
|
26
|
+
|
27
|
+
it 'should return memoized value' do
|
28
|
+
subject.memoized
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'default' do
|
33
|
+
let(:mixin) { Adamantium }
|
34
|
+
|
35
|
+
subject { class_under_test.new }
|
36
|
+
|
37
|
+
it 'should deep freeze instance and attributes' do
|
38
|
+
should be_frozen
|
39
|
+
subject.attribute.should be_frozen
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should deep freeze memoized values' do
|
43
|
+
subject.memoized.should be_frozen
|
44
|
+
subject.memoized[0].should be_frozen
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'flat' do
|
49
|
+
let(:mixin) { Adamantium::Flat }
|
50
|
+
|
51
|
+
subject { class_under_test.new }
|
52
|
+
|
53
|
+
it 'should freeze only instance' do
|
54
|
+
should be_frozen
|
55
|
+
subject.attribute.should_not be_frozen
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should flat freeze memoized values' do
|
59
|
+
subject.memoized.should be_frozen
|
60
|
+
subject.memoized[0].should_not be_frozen
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adamantium::ClassMethods, '#freezer' do
|
4
|
+
let(:object) do
|
5
|
+
Class.new do
|
6
|
+
include Adamantium::Flat
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { object.freezer }
|
11
|
+
|
12
|
+
it { should be(Adamantium::Freezer::Flat) }
|
13
|
+
|
14
|
+
it_should_behave_like 'an idempotent method'
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adamantium::Freezer, '.get' do
|
4
|
+
subject { object.get(name) }
|
5
|
+
|
6
|
+
let(:object) { described_class }
|
7
|
+
|
8
|
+
context 'with :deep' do
|
9
|
+
let(:name) { :deep }
|
10
|
+
|
11
|
+
it { should be(Adamantium::Freezer::Deep) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'with :noop' do
|
15
|
+
let(:name) { :noop }
|
16
|
+
|
17
|
+
it { should be(Adamantium::Freezer::Noop) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with :flat' do
|
21
|
+
let(:name) { :flat }
|
22
|
+
|
23
|
+
it { should be(Adamantium::Freezer::Flat) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with unknown name' do
|
27
|
+
let(:name) { :other }
|
28
|
+
|
29
|
+
it 'should raise error' do
|
30
|
+
expect { subject }.to raise_error(described_class::UnknownFreezerError, 'Freezer with name :other is unknown')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adamantium::Freezer, '.parse' do
|
4
|
+
subject { object.parse(options) }
|
5
|
+
|
6
|
+
let(:object) { described_class }
|
7
|
+
let(:freezer) { mock('Freezer') }
|
8
|
+
|
9
|
+
context 'with empty options' do
|
10
|
+
let(:options) { {} }
|
11
|
+
it { should be(nil) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'with :freezer key' do
|
15
|
+
let(:options) { { :freezer => name } }
|
16
|
+
let(:name) { mock('Name') }
|
17
|
+
|
18
|
+
it 'should get freezer' do
|
19
|
+
described_class.should_receive(:get).with(name).and_return(freezer)
|
20
|
+
should be(freezer)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'with any other key' do
|
25
|
+
let(:options) { { :other => :key } }
|
26
|
+
|
27
|
+
it 'should raise error' do
|
28
|
+
expect { subject }.to raise_error(described_class::OptionError, 'Unknown option key(s) for memoizer [:other]')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Adamantium::Freezer::Deep, '.call' do
|
6
|
+
subject { object.call(value) }
|
7
|
+
|
8
|
+
let(:object) { self.class.described_type }
|
9
|
+
|
10
|
+
context 'with a numeric value' do
|
11
|
+
let(:value) { 1 }
|
12
|
+
|
13
|
+
it { should equal(value) }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with a true value' do
|
17
|
+
let(:value) { true }
|
18
|
+
|
19
|
+
it { should equal(value) }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with a false value' do
|
23
|
+
let(:value) { false }
|
24
|
+
|
25
|
+
it { should equal(value) }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with a nil value' do
|
29
|
+
let(:value) { nil }
|
30
|
+
|
31
|
+
it { should equal(value) }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with a symbol value' do
|
35
|
+
let(:value) { :symbol }
|
36
|
+
|
37
|
+
it { should equal(value) }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with a frozen value' do
|
41
|
+
let(:value) { String.new.freeze }
|
42
|
+
|
43
|
+
it { should equal(value) }
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'with a module value' do
|
47
|
+
let(:value) { Module.new }
|
48
|
+
|
49
|
+
it { should equal(value) }
|
50
|
+
|
51
|
+
it { should_not be_frozen }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with a class value' do
|
55
|
+
let(:value) { Class.new }
|
56
|
+
|
57
|
+
it { should equal(value) }
|
58
|
+
|
59
|
+
it { should_not be_frozen }
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with an unfrozen value' do
|
63
|
+
let(:value) { String.new }
|
64
|
+
|
65
|
+
it { should_not equal(value) }
|
66
|
+
|
67
|
+
it { should be_instance_of(String) }
|
68
|
+
|
69
|
+
it { should == value }
|
70
|
+
|
71
|
+
it { should be_frozen }
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'with a composed value' do
|
75
|
+
let(:value) { [String.new] }
|
76
|
+
|
77
|
+
it 'does freeze inner values' do
|
78
|
+
subject.first.should be_frozen
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adamantium::Freezer::Deep, '.freeze' do
|
4
|
+
subject { object.freeze(value) }
|
5
|
+
|
6
|
+
let(:object) { described_class }
|
7
|
+
|
8
|
+
let(:value) { mock('Value') }
|
9
|
+
|
10
|
+
it 'should deep freeze value' do
|
11
|
+
IceNine.should_receive(:deep_freeze).with(value).and_return(value)
|
12
|
+
should be(value)
|
13
|
+
end
|
14
|
+
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Adamantium, '.
|
6
|
-
subject { object.
|
5
|
+
describe Adamantium::Freezer::Flat, '.call' do
|
6
|
+
subject { object.call(value) }
|
7
7
|
|
8
8
|
let(:object) { self.class.described_type }
|
9
9
|
|
@@ -54,4 +54,12 @@ describe Adamantium, '.freeze_object' do
|
|
54
54
|
|
55
55
|
it { should be_frozen }
|
56
56
|
end
|
57
|
+
|
58
|
+
context 'with a composed value' do
|
59
|
+
let(:value) { [String.new] }
|
60
|
+
|
61
|
+
it 'does NOT freeze inner values' do
|
62
|
+
subject.first.should_not be_frozen
|
63
|
+
end
|
64
|
+
end
|
57
65
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adamantium::Freezer::Flat, '.freeze' do
|
4
|
+
subject { object.freeze(value) }
|
5
|
+
|
6
|
+
let(:object) { described_class }
|
7
|
+
|
8
|
+
let(:value) { mock('Value') }
|
9
|
+
|
10
|
+
it 'should freeze value' do
|
11
|
+
value.should_receive(:freeze).and_return(value)
|
12
|
+
should be(value)
|
13
|
+
end
|
14
|
+
end
|
@@ -7,8 +7,8 @@ describe Adamantium, '#memoize' do
|
|
7
7
|
subject { object.memoize(method, value) }
|
8
8
|
|
9
9
|
let(:described_class) { Class.new(AdamantiumSpecs::Object) }
|
10
|
-
let(:object) { described_class.new
|
11
|
-
let(:method) { :test
|
10
|
+
let(:object) { described_class.new }
|
11
|
+
let(:method) { :test }
|
12
12
|
|
13
13
|
before do
|
14
14
|
described_class.memoize(method)
|
@@ -7,9 +7,9 @@ describe Adamantium, '#memoized' do
|
|
7
7
|
subject { object.memoized(method) }
|
8
8
|
|
9
9
|
let(:described_class) { Class.new(AdamantiumSpecs::Object) }
|
10
|
-
let(:method) { :test
|
11
|
-
let(:value) { String.new.freeze
|
12
|
-
let(:object) { described_class.new
|
10
|
+
let(:method) { :test }
|
11
|
+
let(:value) { String.new.freeze }
|
12
|
+
let(:object) { described_class.new }
|
13
13
|
|
14
14
|
before do
|
15
15
|
described_class.memoize(method)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Adamantium::ModuleMethods, '#freezer' do
|
4
|
+
let(:object) do
|
5
|
+
Class.new do
|
6
|
+
include Adamantium
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { object.freezer }
|
11
|
+
|
12
|
+
it { should be(Adamantium::Freezer::Deep) }
|
13
|
+
|
14
|
+
it_should_behave_like 'an idempotent method'
|
15
|
+
end
|
@@ -10,19 +10,29 @@ shared_examples_for 'memoizes method' do
|
|
10
10
|
instance.send(method).should equal(instance.send(method))
|
11
11
|
end
|
12
12
|
|
13
|
-
it 'creates a method that returns a
|
13
|
+
it 'creates a method that returns a same value' do
|
14
14
|
subject
|
15
|
-
object.new
|
15
|
+
instance = object.new
|
16
|
+
first = instance.send(method)
|
17
|
+
second = instance.send(method)
|
18
|
+
first.should be(second)
|
16
19
|
end
|
17
20
|
|
18
21
|
specification = proc do
|
19
22
|
subject
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
if method != :some_state
|
24
|
+
file, line = object.new.send(method).first.split(':')[0, 2]
|
25
|
+
File.expand_path(file).should eql(File.expand_path('../../../../../lib/adamantium/module_methods.rb', __FILE__))
|
26
|
+
line.to_i.should eql(80)
|
27
|
+
end
|
23
28
|
end
|
24
29
|
|
25
30
|
it 'sets the file and line number properly' do
|
31
|
+
# Exclude example for methot that does not return caller
|
32
|
+
if method == :some_method
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
26
36
|
if RUBY_PLATFORM.include?('java')
|
27
37
|
pending('Kernel#caller returns the incorrect line number in JRuby', &specification)
|
28
38
|
else
|
@@ -49,9 +59,45 @@ shared_examples_for 'memoizes method' do
|
|
49
59
|
end
|
50
60
|
|
51
61
|
describe Adamantium::ModuleMethods, '#memoize' do
|
52
|
-
subject { object.memoize(method) }
|
62
|
+
subject { object.memoize(method, options) }
|
63
|
+
let(:options) { {} }
|
64
|
+
|
65
|
+
let(:object) do
|
66
|
+
Class.new(AdamantiumSpecs::Object) do
|
67
|
+
def some_state
|
68
|
+
Object.new
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with :noop freezer option' do
|
74
|
+
let(:method) { :some_state }
|
75
|
+
let(:options) { { :freezer => :noop } }
|
76
|
+
|
77
|
+
it_should_behave_like 'a command method'
|
78
|
+
it_should_behave_like 'memoizes method'
|
79
|
+
|
80
|
+
it 'is still a public method' do
|
81
|
+
should be_public_method_defined(method)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'creates a method that returns a non frozen value' do
|
85
|
+
subject
|
86
|
+
object.new.send(method).should_not be_frozen
|
87
|
+
end
|
88
|
+
end
|
53
89
|
|
54
|
-
|
90
|
+
context 'memoized method that returns generated values' do
|
91
|
+
let(:method) { :some_state }
|
92
|
+
|
93
|
+
it_should_behave_like 'a command method'
|
94
|
+
it_should_behave_like 'memoizes method'
|
95
|
+
|
96
|
+
it 'creates a method that returns a frozen value' do
|
97
|
+
subject
|
98
|
+
object.new.send(method).should be_frozen
|
99
|
+
end
|
100
|
+
end
|
55
101
|
|
56
102
|
context 'public method' do
|
57
103
|
let(:method) { :public_method }
|
@@ -62,6 +108,11 @@ describe Adamantium::ModuleMethods, '#memoize' do
|
|
62
108
|
it 'is still a public method' do
|
63
109
|
should be_public_method_defined(method)
|
64
110
|
end
|
111
|
+
|
112
|
+
it 'creates a method that returns a frozen value' do
|
113
|
+
subject
|
114
|
+
object.new.send(method).should be_frozen
|
115
|
+
end
|
65
116
|
end
|
66
117
|
|
67
118
|
context 'protected method' do
|
@@ -73,6 +124,11 @@ describe Adamantium::ModuleMethods, '#memoize' do
|
|
73
124
|
it 'is still a protected method' do
|
74
125
|
should be_protected_method_defined(method)
|
75
126
|
end
|
127
|
+
|
128
|
+
it 'creates a method that returns a frozen value' do
|
129
|
+
subject
|
130
|
+
object.new.send(method).should be_frozen
|
131
|
+
end
|
76
132
|
end
|
77
133
|
|
78
134
|
context 'private method' do
|
@@ -84,5 +140,10 @@ describe Adamantium::ModuleMethods, '#memoize' do
|
|
84
140
|
it 'is still a private method' do
|
85
141
|
should be_private_method_defined(method)
|
86
142
|
end
|
143
|
+
|
144
|
+
it 'creates a method that returns a frozen value' do
|
145
|
+
subject
|
146
|
+
object.new.send(method).should be_frozen
|
147
|
+
end
|
87
148
|
end
|
88
149
|
end
|
data/tasks/metrics/ci.rake
CHANGED
@@ -5,5 +5,5 @@ task :ci => %w[ ci:metrics metrics:heckle ]
|
|
5
5
|
|
6
6
|
namespace :ci do
|
7
7
|
desc 'Run metrics (except heckle) and spec'
|
8
|
-
task :metrics => %w[ spec metrics:verify_measurements metrics:flog metrics:flay metrics:reek metrics:roodi ]
|
8
|
+
task :metrics => %w[ spec metrics:verify_measurements metrics:flog metrics:flay metrics:reek metrics:roodi metrics:all ]
|
9
9
|
end
|
data/tasks/metrics/heckle.rake
CHANGED
@@ -47,7 +47,7 @@ begin
|
|
47
47
|
map = NameMap.new
|
48
48
|
|
49
49
|
heckle_caught_modules = Hash.new { |hash, key| hash[key] = [] }
|
50
|
-
|
50
|
+
uncovered_methods = 0
|
51
51
|
|
52
52
|
ObjectSpace.each_object(Module) do |mod|
|
53
53
|
next unless mod.name =~ /\A#{root_module_regexp}(?::|\z)/
|
@@ -167,20 +167,19 @@ begin
|
|
167
167
|
case line = line.chomp
|
168
168
|
when "The following mutations didn't cause test failures:"
|
169
169
|
heckle_caught_modules[mod.name] << method
|
170
|
-
|
171
|
-
unhandled_mutations += 1
|
170
|
+
uncovered_methods += 1
|
172
171
|
end
|
173
172
|
end
|
174
173
|
end
|
175
174
|
end
|
176
175
|
end
|
177
176
|
|
178
|
-
if
|
177
|
+
if uncovered_methods > 0
|
179
178
|
error_message_lines = [ "*************\n" ]
|
180
179
|
|
181
|
-
error_message_lines << "Heckle found #{
|
182
|
-
"
|
183
|
-
"
|
180
|
+
error_message_lines << "Heckle found #{uncovered_methods} " \
|
181
|
+
"method#{"s" unless uncovered_methods == 1} " \
|
182
|
+
"where mutations didn't cause spec violations\n"
|
184
183
|
|
185
184
|
heckle_caught_modules.each do |mod, methods|
|
186
185
|
error_message_lines << "#{mod} contains the following " \
|
@@ -201,7 +200,9 @@ begin
|
|
201
200
|
end
|
202
201
|
end
|
203
202
|
rescue LoadError
|
204
|
-
|
205
|
-
|
203
|
+
namespace :metrics do
|
204
|
+
task :heckle => :coverage do
|
205
|
+
$stderr.puts 'Heckle or mspec is not available. In order to run heckle, you must: gem install heckle mspec'
|
206
|
+
end
|
206
207
|
end
|
207
208
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adamantium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dan Kubb
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-11-14 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: backports
|
@@ -128,7 +128,11 @@ files:
|
|
128
128
|
- config/site.reek
|
129
129
|
- config/yardstick.yml
|
130
130
|
- lib/adamantium.rb
|
131
|
+
- lib/adamantium/class_methods.rb
|
132
|
+
- lib/adamantium/freezer.rb
|
133
|
+
- lib/adamantium/module_methods.rb
|
131
134
|
- lib/adamantium/version.rb
|
135
|
+
- spec/integration/adamantium_spec.rb
|
132
136
|
- spec/rcov.opts
|
133
137
|
- spec/shared/command_method_behavior.rb
|
134
138
|
- spec/shared/each_method_behaviour.rb
|
@@ -138,13 +142,20 @@ files:
|
|
138
142
|
- spec/spec.opts
|
139
143
|
- spec/spec_helper.rb
|
140
144
|
- spec/support/config_alias.rb
|
141
|
-
- spec/unit/adamantium/class_methods/freeze_object_spec.rb
|
142
145
|
- spec/unit/adamantium/class_methods/new_spec.rb
|
143
146
|
- spec/unit/adamantium/dup_spec.rb
|
144
147
|
- spec/unit/adamantium/fixtures/classes.rb
|
148
|
+
- spec/unit/adamantium/flat/freezer_spec.rb
|
145
149
|
- spec/unit/adamantium/freeze_spec.rb
|
150
|
+
- spec/unit/adamantium/freezer/class_methods/get_spec.rb
|
151
|
+
- spec/unit/adamantium/freezer/class_methods/parse_spec.rb
|
152
|
+
- spec/unit/adamantium/freezer/deep/class_methods/call_spec.rb
|
153
|
+
- spec/unit/adamantium/freezer/deep/class_methods/freeze_spec.rb
|
154
|
+
- spec/unit/adamantium/freezer/flat/class_methods/call_spec.rb
|
155
|
+
- spec/unit/adamantium/freezer/flat/class_methods/freeze_spec.rb
|
146
156
|
- spec/unit/adamantium/memoize_spec.rb
|
147
157
|
- spec/unit/adamantium/memoized_spec.rb
|
158
|
+
- spec/unit/adamantium/module_methods/freezer_spec.rb
|
148
159
|
- spec/unit/adamantium/module_methods/included_spec.rb
|
149
160
|
- spec/unit/adamantium/module_methods/memoize_spec.rb
|
150
161
|
- tasks/metrics/ci.rake
|
@@ -191,13 +202,21 @@ signing_key:
|
|
191
202
|
specification_version: 3
|
192
203
|
summary: Immutable extensions to objects
|
193
204
|
test_files:
|
194
|
-
- spec/
|
205
|
+
- spec/integration/adamantium_spec.rb
|
195
206
|
- spec/unit/adamantium/class_methods/new_spec.rb
|
196
207
|
- spec/unit/adamantium/dup_spec.rb
|
197
208
|
- spec/unit/adamantium/fixtures/classes.rb
|
209
|
+
- spec/unit/adamantium/flat/freezer_spec.rb
|
198
210
|
- spec/unit/adamantium/freeze_spec.rb
|
211
|
+
- spec/unit/adamantium/freezer/class_methods/get_spec.rb
|
212
|
+
- spec/unit/adamantium/freezer/class_methods/parse_spec.rb
|
213
|
+
- spec/unit/adamantium/freezer/deep/class_methods/call_spec.rb
|
214
|
+
- spec/unit/adamantium/freezer/deep/class_methods/freeze_spec.rb
|
215
|
+
- spec/unit/adamantium/freezer/flat/class_methods/call_spec.rb
|
216
|
+
- spec/unit/adamantium/freezer/flat/class_methods/freeze_spec.rb
|
199
217
|
- spec/unit/adamantium/memoize_spec.rb
|
200
218
|
- spec/unit/adamantium/memoized_spec.rb
|
219
|
+
- spec/unit/adamantium/module_methods/freezer_spec.rb
|
201
220
|
- spec/unit/adamantium/module_methods/included_spec.rb
|
202
221
|
- spec/unit/adamantium/module_methods/memoize_spec.rb
|
203
222
|
has_rdoc:
|