adamantium 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NzMwMWQ3ODI1Y2FlYTlhNTFjZjhlYTM3NWMyOTgwZjk4NmI4ODFjYg==
5
- data.tar.gz: !binary |-
6
- M2RmNzViMTg3YjcxNDdmMDg4ZTBmZTAzMWY5MDYzMDg0Y2U4MGZjZg==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- NjU3MDcxN2UzNzU1ZWZlYzEyY2VkMzgzNWJiNTFhNDc0MmMzNWZhNzJkOGYy
10
- YTRkNjhkMTRiMmIyMzAwZjk0Yjk2NDJlMmZjODY3NTVhNTNlZDcwZDgwMjMx
11
- ODRjYjZmOGE4OTZlODNmNTIwMDJiYzE0N2ViNmE2NmQ5YjFiNTM=
12
- data.tar.gz: !binary |-
13
- ODY0NDUyODM1YTg3OTMwMWJlMTU4YzFhNzUzZmY1NGE1NWE0ZTQzMmRiMDEz
14
- ZWExY2RhY2Y4YWQ3MTI1MjBlODRhODlhNWE2Y2ZlYjMxMmI5YjgzYWNhM2Uy
15
- YTY0NWMwYjNmYzc1ZjcxMWU1OThlMWQyNjgwYWE0NzM2YWZiZjk=
2
+ SHA1:
3
+ metadata.gz: 4675912f9a7cb3eb823638436c1be23e6753d24b
4
+ data.tar.gz: cbf0680ce697e2da134bc86d83582a1928952d8e
5
+ SHA512:
6
+ metadata.gz: 81ab12f754e252929d3074a9a85f53af07a3a93d8db946beac48124f6f03c7528741d1716e221fb07eac9daf95031e9e2847aa72509135fd017a71a1dcfbbb53
7
+ data.tar.gz: 5c7246f7aaab383bd952af49971a6046dc953f96a2553e8c2e7539191bb53408a9fb0ebb71e215714d5250aa8fef426d7330dded7c090b13ba38883e45b84fa0
data/.gitignore CHANGED
@@ -1,4 +1,37 @@
1
- /Gemfile.lock
2
- /coverage
3
- /tmp
4
- /.rbx
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.sw[op]
15
+
16
+ ## Rubinius
17
+ *.rbc
18
+ .rbx
19
+
20
+ ## PROJECT::GENERAL
21
+ *.gem
22
+ coverage
23
+ profiling
24
+ turbulence
25
+ rdoc
26
+ pkg
27
+ tmp
28
+ doc
29
+ log
30
+ .yardoc
31
+ measurements
32
+
33
+ ## BUNDLER
34
+ .bundle
35
+ Gemfile.lock
36
+
37
+ ## PROJECT::SPECIFIC
@@ -0,0 +1,6 @@
1
+ AllCops:
2
+ Includes:
3
+ - 'Gemfile'
4
+ Excludes:
5
+ - 'Gemfile.devtools'
6
+ - 'vendor/**'
@@ -1,23 +1,26 @@
1
1
  language: ruby
2
2
  before_install: gem install bundler
3
3
  bundler_args: --without yard guard benchmarks
4
- script: "bundle exec rake ci"
4
+ script: "bundle exec rake ci:metrics"
5
5
  rvm:
6
6
  - 1.9.3
7
7
  - 2.0.0
8
+ - 2.1.0
8
9
  - ruby-head
9
- - rbx-19mode
10
+ - rbx
10
11
  matrix:
11
12
  include:
12
13
  - rvm: jruby-19mode
13
- env: JRUBY_OPTS="$JRUBY_OPTS --debug"
14
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
15
+ - rvm: jruby-20mode
16
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
17
+ - rvm: jruby-21mode
18
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
14
19
  - rvm: jruby-head
15
- env: JRUBY_OPTS="$JRUBY_OPTS --debug"
20
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
16
21
  allow_failures:
17
- - rvm: 1.9.3 # mutant fails
18
- - rvm: 2.0.0 # mutant fails
19
- - rvm: ruby-head # travis broken
20
- - rvm: rbx-19mode # mutant fails
22
+ - rvm: 2.1.0 # buggy runtime
23
+ fast_finish: true
21
24
  notifications:
22
25
  irc:
23
26
  channels:
@@ -4,21 +4,24 @@ group :development do
4
4
  gem 'rake', '~> 10.1.0'
5
5
  gem 'rspec', '~> 2.14.1'
6
6
  gem 'yard', '~> 0.8.7'
7
+
8
+ platform :rbx do
9
+ gem 'rubysl-singleton', '~> 2.0.0'
10
+ end
7
11
  end
8
12
 
9
13
  group :yard do
10
- gem 'kramdown', '~> 1.1.0'
14
+ gem 'kramdown', '~> 1.3.0'
11
15
  end
12
16
 
13
17
  group :guard do
14
- gem 'guard', '~> 1.8.1'
15
- gem 'guard-bundler', '~> 1.0.0'
16
- gem 'guard-rspec', '~> 3.0.2'
17
- gem 'guard-rubocop', '~> 0.2.0'
18
- # gem 'guard-mutant', '~> 0.0.1'
18
+ gem 'guard', '~> 2.3.0'
19
+ gem 'guard-bundler', '~> 2.0.0'
20
+ gem 'guard-rspec', '~> 4.2.0'
21
+ gem 'guard-rubocop', '~> 1.0.0'
19
22
 
20
23
  # file system change event handling
21
- gem 'listen', '~> 1.3.0'
24
+ gem 'listen', '~> 2.4.0'
22
25
  gem 'rb-fchange', '~> 0.0.6', require: false
23
26
  gem 'rb-fsevent', '~> 0.9.3', require: false
24
27
  gem 'rb-inotify', '~> 0.9.0', require: false
@@ -30,18 +33,29 @@ group :guard do
30
33
  end
31
34
 
32
35
  group :metrics do
33
- gem 'coveralls', '~> 0.6.7'
36
+ gem 'coveralls', '~> 0.7.0'
34
37
  gem 'flay', '~> 2.4.0'
35
- gem 'flog', '~> 4.1.1'
38
+ gem 'flog', '~> 4.2.0'
36
39
  gem 'reek', '~> 1.3.2'
37
- gem 'rubocop', '~> 0.11.0'
38
- gem 'simplecov', '~> 0.7.1'
39
- gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
40
+ gem 'rubocop', '~> 0.16.0'
41
+ gem 'simplecov', '~> 0.8.2'
42
+ gem 'yardstick', '~> 0.9.9'
43
+
44
+ platforms :mri do
45
+ gem 'mutant', '~> 0.3.4'
46
+ end
40
47
 
41
48
  platforms :ruby_19, :ruby_20 do
42
- # gem 'mutant', git: 'https://github.com/mbj/mutant.git'
43
49
  gem 'yard-spellcheck', '~> 0.1.5'
44
50
  end
51
+
52
+ platform :rbx do
53
+ gem 'json', '~> 1.8.1'
54
+ gem 'racc', '~> 1.4'
55
+ gem 'rubysl-logger', '~> 2.0.0'
56
+ gem 'rubysl-open-uri', '~> 2.0.0'
57
+ gem 'rubysl-prettyprint', '~> 2.0.2'
58
+ end
45
59
  end
46
60
 
47
61
  group :benchmarks do
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  adamantium
2
2
  ==========
3
3
 
4
- Create immutable objects
4
+ Create immutable objects with ease.
5
5
 
6
6
  [![Gem Version](https://badge.fury.io/rb/adamantium.png)][gem]
7
7
  [![Build Status](https://secure.travis-ci.org/dkubb/adamantium.png?branch=master)][travis]
@@ -16,7 +16,7 @@ Create immutable objects
16
16
  [coveralls]: https://coveralls.io/r/dkubb/adamantium
17
17
 
18
18
  This is a small standalone gem featuring a module ripped out from [axiom](https://github.com/dkubb/axiom).
19
- It allows to make objects immutable in an unobtrusive way.
19
+ It allows you to make objects immutable in a simple, unobtrusive way.
20
20
 
21
21
  Examples
22
22
  --------
@@ -70,7 +70,7 @@ class Example
70
70
  end
71
71
  memoize :buffer, freezer: :noop
72
72
 
73
- # Memoized method with nondeeply frozen value
73
+ # Memoized method with shallow frozen value
74
74
  # Example:
75
75
  #
76
76
  # object = Example.new
@@ -86,12 +86,12 @@ class Example
86
86
  end
87
87
 
88
88
  class FlatExample
89
- # Inclusion of Adamantium::Flat defaults do non deep frozen behavior
90
- # for memoizer and constructor
89
+ # Inclusion of Adamantium::Flat defaults to shallow frozen
90
+ # behavior for memoizer and constructor
91
91
 
92
92
  include Adamantium::Flat
93
93
 
94
- # Instace is frozen but attribute is not
94
+ # Instance is frozen but attribute is not
95
95
  # object = FlatExample.new
96
96
  # object.frozen? # => true
97
97
  # object.attribute.frozen? # => false
@@ -100,7 +100,7 @@ class FlatExample
100
100
  end
101
101
  attr_reader :attribute
102
102
 
103
- # Memoized method with flat frozen value (default)
103
+ # Memoized method with flat frozen value (default with Adamantium::Flat)
104
104
  # Example:
105
105
  #
106
106
  # object = Example.new
@@ -10,15 +10,15 @@ Gem::Specification.new do |gem|
10
10
  gem.description = 'Immutable extensions to objects'
11
11
  gem.summary = gem.description
12
12
  gem.homepage = 'https://github.com/dkubb/adamantium'
13
- gem.licenses = 'MIT'
13
+ gem.license = 'MIT'
14
14
 
15
15
  gem.require_paths = %w[lib]
16
16
  gem.files = `git ls-files`.split("\n")
17
17
  gem.test_files = `git ls-files -- spec/{unit,integration}`.split("\n")
18
18
  gem.extra_rdoc_files = %w[LICENSE README.md CONTRIBUTING.md TODO]
19
19
 
20
- gem.add_runtime_dependency('ice_nine', '~> 0.9')
21
- gem.add_runtime_dependency('thread_safe', '~> 0.1.2')
20
+ gem.add_runtime_dependency('ice_nine', '~> 0.11.0')
21
+ gem.add_runtime_dependency('memoizable', '~> 0.4.0')
22
22
 
23
- gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
23
+ gem.add_development_dependency('bundler', '~> 1.5', '>= 1.5.2')
24
24
  end
@@ -1,3 +1,3 @@
1
1
  ---
2
- threshold: 7
3
- total_score: 54
2
+ threshold: 4
3
+ total_score: 28
@@ -1,2 +1,2 @@
1
1
  ---
2
- threshold: 17.5
2
+ threshold: 15.0
@@ -10,7 +10,8 @@ ClassVariable:
10
10
  exclude: []
11
11
  ControlParameter:
12
12
  enabled: true
13
- exclude: []
13
+ exclude:
14
+ - Adamantium#transform_unless
14
15
  DataClump:
15
16
  enabled: true
16
17
  exclude: []
@@ -1,10 +1,4 @@
1
- AllCops:
2
- Includes:
3
- - '**/*.rake'
4
- - 'Gemfile'
5
- - 'Gemfile.devtools'
6
- Excludes:
7
- - '**/vendor/**'
1
+ inherit_from: ../.rubocop.yml
8
2
 
9
3
  # Avoid parameter lists longer than five parameters.
10
4
  ParameterLists:
@@ -29,7 +23,7 @@ CollectionMethods:
29
23
  # sections of code and visually separate them. When the keyword is at the same
30
24
  # level I think it sort of blends in with the def keywords and makes it harder
31
25
  # to scan the code and see where the sections are.
32
- AccessControl:
26
+ AccessModifierIndentation:
33
27
  Enabled: false
34
28
 
35
29
  # Limit line length
@@ -55,3 +49,7 @@ ConstantName:
55
49
  # Not all trivial readers/writers can be defined with attr_* methods
56
50
  TrivialAccessors:
57
51
  Enabled: false
52
+
53
+ # Allow empty lines around body
54
+ EmptyLinesAroundBody:
55
+ Enabled: false
@@ -1,14 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'ice_nine'
4
- require 'thread_safe'
4
+ require 'memoizable'
5
5
 
6
6
  # Allows objects to be made immutable
7
7
  module Adamantium
8
8
 
9
- # Storage for memoized methods
10
- Memory = Class.new(ThreadSafe::Hash)
11
-
12
9
  # Defaults to less strict defaults
13
10
  module Flat
14
11
 
@@ -17,7 +14,6 @@ module Adamantium
17
14
  # @return [Freezer::Flat]
18
15
  #
19
16
  # @api private
20
- #
21
17
  def freezer
22
18
  Freezer::Flat
23
19
  end
@@ -31,8 +27,10 @@ module Adamantium
31
27
  # @api private
32
28
  def self.included(descendant)
33
29
  super
34
- descendant.send(:include, Adamantium)
35
- descendant.extend(self)
30
+ descendant.instance_exec(self) do |mod|
31
+ include Adamantium
32
+ extend mod
33
+ end
36
34
  end
37
35
  private_class_method :included
38
36
 
@@ -47,58 +45,22 @@ module Adamantium
47
45
  #
48
46
  # @api private
49
47
  def self.included(descendant)
50
- descendant.extend ModuleMethods
51
- descendant.extend ClassMethods if descendant.kind_of?(Class)
52
- self
53
- end
54
-
55
- # Freeze the object
56
- #
57
- # @example
58
- # object.freeze # object is now frozen
59
- #
60
- # @return [Object]
61
- #
62
- # @api public
63
- def freeze
64
- memory # initialize memory
65
48
  super
49
+ descendant.class_eval do
50
+ include Memoizable
51
+ extend ModuleMethods
52
+ extend ClassMethods if kind_of?(Class)
53
+ end
66
54
  end
55
+ private_class_method :included
67
56
 
68
- # Get the memoized value for a method
69
- #
70
- # @example
71
- # hash = object.memoized(:hash)
72
- #
73
- # @param [Symbol] name
74
- # the method name
57
+ # Alias to the original dup method
75
58
  #
76
59
  # @return [Object]
77
60
  #
78
- # @api public
79
- def memoized(name)
80
- memory[name]
81
- end
82
-
83
- # Sets a memoized value for a method
84
- #
85
- # @example
86
- # object.memoize(:hash, 12345)
87
- #
88
- # @param [Symbol] name
89
- # the method name
90
- # @param [Object] value
91
- # the value to memoize
92
- #
93
- # @return [self]
94
- #
95
- # @api public
96
- def memoize(name, value)
97
- unless memory.key?(name)
98
- store_memory(name, freeze_object(value))
99
- end
100
- self
101
- end
61
+ # @api private
62
+ alias_method :__adamantium_dup__, :dup
63
+ private :__adamantium_dup__
102
64
 
103
65
  # A noop #dup for immutable objects
104
66
  #
@@ -112,57 +74,34 @@ module Adamantium
112
74
  self
113
75
  end
114
76
 
115
- private
116
-
117
- # The memoized method results
118
- #
119
- # @return [Hash]
120
- #
121
- # @api private
122
- def memory
123
- @__memory ||= Memory.new
124
- end
77
+ protected
125
78
 
126
- # Freeze object
127
- #
128
- # @param [Object] object
129
- # an object to be frozen
79
+ # Transform the object with the provided block
130
80
  #
131
81
  # @return [Object]
132
82
  #
133
- # @api private
134
- def freeze_object(object)
135
- freezer.call(object)
136
- end
137
-
138
- # Return class level freezer
139
- #
140
- # @return [#call]
141
- #
142
- # @api private
143
- def freezer
144
- self.class.freezer
83
+ # @api public
84
+ def transform(&block)
85
+ copy = __adamantium_dup__
86
+ copy.instance_eval(&block)
87
+ self.class.freezer.freeze(copy)
145
88
  end
146
89
 
147
- # Store the value in memory
90
+ # Transform the object with the provided block if the condition is false
148
91
  #
149
- # @param [Symbol] name
150
- # the method name
151
- # @param [Object] value
152
- # the value to memoize
92
+ # @param [Boolean] condition
153
93
  #
154
- # @return [self]
155
- #
156
- # @return [value]
94
+ # @return [Object]
157
95
  #
158
- # @api private
159
- def store_memory(name, value)
160
- memory[name] = value
96
+ # @api public
97
+ def transform_unless(condition, &block)
98
+ condition ? self : transform(&block)
161
99
  end
162
100
 
163
- end # module Adamantium
101
+ end # Adamantium
164
102
 
165
103
  require 'adamantium/module_methods'
166
104
  require 'adamantium/class_methods'
167
105
  require 'adamantium/freezer'
168
106
  require 'adamantium/mutable'
107
+ require 'adamantium/version'
@@ -17,5 +17,5 @@ module Adamantium
17
17
  freezer.freeze(super)
18
18
  end
19
19
 
20
- end # module ClassMethods
21
- end # module Adamantium
20
+ end # ClassMethods
21
+ end # Adamantium
@@ -80,7 +80,7 @@ module Adamantium
80
80
  #
81
81
  # @api private
82
82
  def self.freeze(value)
83
- IceNine.deep_freeze(value)
83
+ IceNine.deep_freeze!(value)
84
84
  end
85
85
 
86
86
  public_class_method :call
@@ -94,6 +94,12 @@ module Adamantium
94
94
  # Error raised when memoizer options contain unknown keys
95
95
  class OptionError < RuntimeError; end
96
96
 
97
+ @freezers = {
98
+ noop: Noop,
99
+ deep: Deep,
100
+ flat: Flat,
101
+ }.freeze
102
+
97
103
  # Return freezer for name
98
104
  #
99
105
  # @param [Symbol] name
@@ -103,12 +109,8 @@ module Adamantium
103
109
  #
104
110
  # @api private
105
111
  def self.get(name)
106
- case name
107
- when :noop then Noop
108
- when :deep then Deep
109
- when :flat then Flat
110
- else
111
- raise UnknownFreezerError, "Freezer with name #{name.inspect} is unknown"
112
+ @freezers.fetch(name) do
113
+ fail UnknownFreezerError, "Freezer with name #{name.inspect} is unknown"
112
114
  end
113
115
  end
114
116
 
@@ -128,7 +130,7 @@ module Adamantium
128
130
  def self.parse(options)
129
131
  keys = options.keys - [:freezer]
130
132
  unless keys.empty?
131
- raise OptionError, "Unknown option key(s) for memoizer #{keys.inspect}"
133
+ fail OptionError, "Unknown option key(s) for memoizer #{keys.inspect}"
132
134
  end
133
135
  get(options.fetch(:freezer)) if options.key?(:freezer)
134
136
  end
@@ -5,25 +5,11 @@ module Adamantium
5
5
  # Methods mixed in to adamantium modules
6
6
  module ModuleMethods
7
7
 
8
- # Hook called when module is included
9
- #
10
- # @param [Module] mod
11
- # the module including ModuleMethods
12
- #
13
- # @return [self]
14
- #
15
- # @api private
16
- def included(mod)
17
- Adamantium.included(mod)
18
- self
19
- end
20
-
21
8
  # Return default deep freezer
22
9
  #
23
10
  # @return [Freezer::Deep]
24
11
  #
25
12
  # @api private
26
- #
27
13
  def freezer
28
14
  Freezer::Deep
29
15
  end
@@ -46,135 +32,35 @@ module Adamantium
46
32
  self
47
33
  end
48
34
 
49
- # Test if an instance method is memoized
50
- #
51
- # @example
52
- # class Foo
53
- # include Adamantium
54
- #
55
- # def bar
56
- # end
57
- # memoize :bar
58
- #
59
- # end
60
- #
61
- # Foo.memoized?(:bar) # true
62
- # Foo.memoized?(:baz) # false, does not care if method acutally exists
63
- #
64
- # @param [Symbol] name
65
- #
66
- # @return [true]
67
- # if method is memoized
68
- #
69
- # @return [false]
70
- # otherwise
71
- #
72
- # @api private
73
- #
74
- def memoized?(name)
75
- memoized_methods.key?(name)
76
- end
35
+ private
77
36
 
78
- # Return original instance method
79
- #
80
- # @example
81
- #
82
- # class Foo
83
- # include Adamantium
84
- #
85
- # def bar
86
- # end
87
- # memoize :bar
88
- #
89
- # end
90
- #
91
- # Foo.original_instance_method(:bar) #=> UnboundMethod, where source_location still points to original!
92
- #
93
- # @param [Symbol] name
94
- #
95
- # @return [UnboundMethod]
96
- # if method was memoized before
37
+ # Hook called when module is included
97
38
  #
98
- # @raise [ArgumentError]
99
- # otherwise
39
+ # @param [Module] descendant
40
+ # the module including ModuleMethods
100
41
  #
101
- # @api public
42
+ # @return [self]
102
43
  #
103
- def original_instance_method(name)
104
- memoized_methods[name]
44
+ # @api private
45
+ def included(descendant)
46
+ super
47
+ descendant.module_eval { include Adamantium }
105
48
  end
106
49
 
107
- private
108
-
109
50
  # Memoize the named method
110
51
  #
111
- # @param [#to_s] method_name
52
+ # @param [Symbol] method_name
112
53
  # a method name to memoize
113
54
  # @param [#call] freezer
114
- # a freezer for memoized values
55
+ # a callable object to freeze the value
115
56
  #
116
57
  # @return [undefined]
117
58
  #
118
59
  # @api private
119
60
  def memoize_method(method_name, freezer)
120
- method = instance_method(method_name)
121
- if method.arity.nonzero?
122
- raise ArgumentError, 'Cannot memoize method with nonzero arity'
123
- end
124
- memoized_methods[method_name] = method
125
- visibility = method_visibility(method_name)
126
- define_memoize_method(method, freezer)
127
- send(visibility, method_name)
128
- end
129
-
130
- # Return original method registry
131
- #
132
- # @return [Hash<Symbol, UnboundMethod>]
133
- #
134
- # @api private
135
- #
136
- def memoized_methods
137
- @memoized_methods ||= ThreadSafe::Hash.new do |_, name|
138
- raise ArgumentError, "No method #{name.inspect} was memoized"
139
- end
140
- end
141
-
142
- # Define a memoized method that delegates to the original method
143
- #
144
- # @param [UnboundMethod] method
145
- # the method to memoize
146
- # @param [#call] freezer
147
- # a freezer for memoized values
148
- #
149
- # @return [undefined]
150
- #
151
- # @api private
152
- def define_memoize_method(method, freezer)
153
- method_name = method.name.to_sym
154
- undef_method(method_name)
155
- define_method(method_name) do ||
156
- memory.fetch(method_name) do
157
- value = method.bind(self).call
158
- frozen = freezer.call(value)
159
- store_memory(method_name, frozen)
160
- end
161
- end
162
- end
163
-
164
- # Return the method visibility of a method
165
- #
166
- # @param [String, Symbol] method
167
- # the name of the method
168
- #
169
- # @return [Symbol]
170
- #
171
- # @api private
172
- def method_visibility(method)
173
- if private_method_defined?(method) then :private
174
- elsif protected_method_defined?(method) then :protected
175
- else :public
176
- end
61
+ memoized_methods[method_name] = Memoizable::MethodBuilder
62
+ .new(self, method_name, freezer).call
177
63
  end
178
64
 
179
- end # module ModuleMethods
180
- end # module Adamantium
65
+ end # ModuleMethods
66
+ end # Adamantium
@@ -3,6 +3,6 @@
3
3
  module Adamantium
4
4
 
5
5
  # Gem version
6
- VERSION = '0.1.0'.freeze
6
+ VERSION = '0.2.0'.freeze
7
7
 
8
- end # module Adamantium
8
+ end # Adamantium
@@ -12,9 +12,12 @@ if ENV['COVERAGE'] == 'true'
12
12
  ]
13
13
 
14
14
  SimpleCov.start do
15
- command_name 'spec:unit'
16
- add_filter 'config'
17
- add_filter 'spec'
15
+ command_name 'spec:unit'
16
+
17
+ add_filter 'config'
18
+ add_filter 'spec'
19
+ add_filter 'vendor'
20
+
18
21
  minimum_coverage 100
19
22
  end
20
23
  end
@@ -4,6 +4,8 @@ module AdamantiumSpecs
4
4
  class Object
5
5
  include Adamantium
6
6
 
7
+ public :transform, :transform_unless
8
+
7
9
  def argumented(foo)
8
10
  end
9
11
 
@@ -15,6 +17,10 @@ module AdamantiumSpecs
15
17
  caller
16
18
  end
17
19
 
20
+ def eql?(other)
21
+ kind_of?(other.class)
22
+ end
23
+
18
24
  protected
19
25
 
20
26
  def protected_method
@@ -22,12 +22,6 @@ describe Adamantium, '#freeze' do
22
22
  .from(false)
23
23
  .to(true)
24
24
  end
25
-
26
- it 'sets a memoization instance variable' do
27
- expect(object).to_not be_instance_variable_defined(:@__memory)
28
- subject
29
- expect(object.instance_variable_get(:@__memory)).to be_instance_of(Adamantium::Memory)
30
- end
31
25
  end
32
26
 
33
27
  context 'with a frozen object' do
@@ -38,14 +32,5 @@ describe Adamantium, '#freeze' do
38
32
  it 'does not change the frozen state of the object' do
39
33
  expect { subject }.to_not change(object, :frozen?)
40
34
  end
41
-
42
- it 'does not change the memoization instance variable' do
43
- expect { subject }.to_not change { object.instance_variable_get(:@__memory) }
44
- end
45
-
46
- it 'does not set an instance variable for memoization' do
47
- expect(object.instance_variable_get(:@__memory)).to be_instance_of(Adamantium::Memory)
48
- subject
49
- end
50
35
  end
51
36
  end
@@ -9,7 +9,7 @@ describe Adamantium::Freezer::Deep, '.freeze' do
9
9
  let(:value) { double('Value') }
10
10
 
11
11
  it 'should deep freeze value' do
12
- IceNine.should_receive(:deep_freeze).with(value).and_return(value)
12
+ IceNine.should_receive(:deep_freeze!).with(value).and_return(value)
13
13
  should be(value)
14
14
  end
15
15
  end
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  require File.expand_path('../fixtures/classes', __FILE__)
5
5
 
6
6
  describe Adamantium, '#memoize' do
7
- subject { object.memoize(method, value) }
7
+ subject { object.memoize(method => value) }
8
8
 
9
9
  let(:described_class) { Class.new(AdamantiumSpecs::Object) }
10
10
  let(:object) { described_class.new }
@@ -14,33 +14,12 @@ describe Adamantium, '#memoize' do
14
14
  described_class.memoize(method)
15
15
  end
16
16
 
17
- context 'when the value is frozen' do
18
- let(:value) { String.new.freeze }
19
-
20
- it 'sets the memoized value for the method to the value' do
21
- subject
22
- expect(object.send(method)).to be(value)
23
- end
24
-
25
- it 'creates a method that returns a frozen value' do
26
- subject
27
- expect(object.send(method)).to be_frozen
28
- end
29
-
30
- it_should_behave_like 'a command method'
31
- end
32
-
33
- context 'when the value is not frozen' do
17
+ context 'when the method is not memoized' do
34
18
  let(:value) { String.new }
35
19
 
36
20
  it 'sets the memoized value for the method to the value' do
37
21
  subject
38
- expect(object.send(method)).to eql(value)
39
- end
40
-
41
- it 'creates a method that returns a frozen value' do
42
- subject
43
- expect(object.send(method)).to be_frozen
22
+ expect(object.send(method)).to be(value)
44
23
  end
45
24
 
46
25
  it_should_behave_like 'a command method'
@@ -51,13 +30,11 @@ describe Adamantium, '#memoize' do
51
30
  let(:original) { nil }
52
31
 
53
32
  before do
54
- object.memoize(method, original)
33
+ object.memoize(method => original)
55
34
  end
56
35
 
57
- it 'does not change the value' do
58
- expect { subject }.to_not change { object.send(method) }
36
+ it 'raises an exception' do
37
+ expect { subject }.to raise_error(ArgumentError)
59
38
  end
60
-
61
- it_should_behave_like 'a command method'
62
39
  end
63
40
  end
@@ -1,16 +1,40 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
- require File.expand_path('../../fixtures/classes', __FILE__)
5
4
 
6
5
  describe Adamantium::ModuleMethods, '#included' do
7
- subject { object.included(object) }
6
+ subject { descendant.instance_exec(object) { |mod| include mod } }
8
7
 
9
- let(:object) { AdamantiumSpecs::Object }
8
+ let(:object) { Module.new.extend(described_class) }
9
+ let(:descendant) { Class.new }
10
+ let(:superclass) { Module }
10
11
 
11
12
  before do
12
- Adamantium.should_receive(:included).with(object).and_return(Adamantium)
13
+ # Prevent Module.included from being called through inheritance
14
+ Adamantium.stub(:included)
13
15
  end
14
16
 
15
- it_should_behave_like 'a command method'
17
+ around do |example|
18
+ # Restore included method after each example
19
+ superclass.class_eval do
20
+ alias_method :original_included, :included
21
+ example.call
22
+ undef_method :included
23
+ alias_method :included, :original_included
24
+ end
25
+ end
26
+
27
+ it 'delegates to the superclass #included method' do
28
+ # This is the most succinct approach I could think of to test whether the
29
+ # superclass#included method is called. All of the built-in rspec helpers
30
+ # did not seem to work for this.
31
+ included = false
32
+ superclass.class_eval { define_method(:included) { |_| included = true } }
33
+ expect { subject }.to change { included }.from(false).to(true)
34
+ end
35
+
36
+ it 'includes Adamantium into the descendant' do
37
+ subject
38
+ expect(descendant.included_modules).to include(Adamantium)
39
+ end
16
40
  end
@@ -9,19 +9,17 @@ shared_examples_for 'memoizes method' do
9
9
  instance = object.new
10
10
  expect(instance.send(method)).to be(instance.send(method))
11
11
  end
12
+ end
12
13
 
13
- it 'creates a method that returns a same value' do
14
- subject
15
- instance = object.new
16
- expect(instance.send(method)).to be(instance.send(method))
17
- end
18
-
14
+ shared_examples_for 'wraps original method' do
19
15
  it 'creates a method with an arity of 0' do
20
16
  subject
21
17
  expect(object.new.method(method).arity).to be_zero
22
18
  end
23
19
 
24
20
  context 'when the initializer calls the memoized method' do
21
+ it_should_behave_like 'memoizes method'
22
+
25
23
  before do
26
24
  method = self.method
27
25
  object.send(:define_method, :initialize) { send(method) }
@@ -31,11 +29,6 @@ shared_examples_for 'memoizes method' do
31
29
  subject
32
30
  expect { object.new }.to_not raise_error
33
31
  end
34
-
35
- it 'memoizes the methdod inside the initializer' do
36
- subject
37
- expect(object.new.memoized(method)).to_not be_nil
38
- end
39
32
  end
40
33
  end
41
34
 
@@ -56,7 +49,7 @@ describe Adamantium::ModuleMethods, '#memoize' do
56
49
  let(:method) { :argumented }
57
50
 
58
51
  it 'should raise error' do
59
- expect { subject }.to raise_error(ArgumentError, 'Cannot memoize method with nonzero arity')
52
+ expect { subject }.to raise_error(ArgumentError, "Cannot memoize #{object}#argumented, its arity is 1")
60
53
  end
61
54
  end
62
55
 
@@ -65,7 +58,7 @@ describe Adamantium::ModuleMethods, '#memoize' do
65
58
  let(:options) { { freezer: :noop } }
66
59
 
67
60
  it_should_behave_like 'a command method'
68
- it_should_behave_like 'memoizes method'
61
+ it_should_behave_like 'wraps original method'
69
62
 
70
63
  it 'is still a public method' do
71
64
  should be_public_method_defined(method)
@@ -82,6 +75,7 @@ describe Adamantium::ModuleMethods, '#memoize' do
82
75
 
83
76
  it_should_behave_like 'a command method'
84
77
  it_should_behave_like 'memoizes method'
78
+ it_should_behave_like 'wraps original method'
85
79
 
86
80
  it 'creates a method that returns a frozen value' do
87
81
  subject
@@ -94,6 +88,7 @@ describe Adamantium::ModuleMethods, '#memoize' do
94
88
 
95
89
  it_should_behave_like 'a command method'
96
90
  it_should_behave_like 'memoizes method'
91
+ it_should_behave_like 'wraps original method'
97
92
 
98
93
  it 'is still a public method' do
99
94
  should be_public_method_defined(method)
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require File.expand_path('../fixtures/classes', __FILE__)
5
+
6
+ describe Adamantium, '#transform' do
7
+ let(:object) { described_class.new }
8
+ let(:described_class) { AdamantiumSpecs::Object }
9
+
10
+ it 'returns a copy of the object' do
11
+ transformed = object.transform {}
12
+ expect(transformed).to_not be(object)
13
+ expect(transformed).to eql(object)
14
+ end
15
+
16
+ it 'freezes the copy' do
17
+ expect(object.transform {}).to be_frozen
18
+ end
19
+
20
+ it 'yields the copy to the block' do
21
+ expect { |block| object.transform(&block) }
22
+ .to yield_with_args(described_class)
23
+ end
24
+
25
+ it 'evaluates the block within the context of the copy' do
26
+ copy = nil
27
+ expect(object.transform { copy = self }).to be(copy)
28
+ end
29
+
30
+ it 'evaluates the block with an unfrozen copy' do
31
+ frozen_in_block = nil
32
+ expect { object.transform { frozen_in_block = frozen? } }
33
+ .to change { frozen_in_block }.from(nil).to(false)
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require File.expand_path('../fixtures/classes', __FILE__)
5
+
6
+ describe Adamantium, '#transform_unless' do
7
+ let(:object) { described_class.new }
8
+ let(:described_class) { AdamantiumSpecs::Object }
9
+
10
+ context 'when the condition is true' do
11
+ let(:condition) { true }
12
+
13
+ it 'does not evaluate the block' do
14
+ expect { |block| object.transform_unless(condition, &block) }
15
+ .not_to yield_control
16
+ end
17
+
18
+ it 'returns the object' do
19
+ expect(object.transform_unless(condition) {}).to be(object)
20
+ end
21
+ end
22
+
23
+ context 'when the condition is false' do
24
+ let(:condition) { false }
25
+
26
+ it 'evaluates the block' do
27
+ expect { |block| object.transform_unless(condition, &block) }
28
+ .to yield_control
29
+ end
30
+
31
+ it 'returns a copy of the object' do
32
+ transformed = object.transform_unless(condition) {}
33
+ expect(transformed).to_not be(object)
34
+ expect(transformed).to eql(object)
35
+ end
36
+ end
37
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: adamantium
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
  - Dan Kubb
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-18 00:00:00.000000000 Z
12
+ date: 2014-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ice_nine
@@ -17,48 +17,48 @@ dependencies:
17
17
  requirements:
18
18
  - - ~>
19
19
  - !ruby/object:Gem::Version
20
- version: '0.9'
20
+ version: 0.11.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ~>
26
26
  - !ruby/object:Gem::Version
27
- version: '0.9'
27
+ version: 0.11.0
28
28
  - !ruby/object:Gem::Dependency
29
- name: thread_safe
29
+ name: memoizable
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ~>
33
33
  - !ruby/object:Gem::Version
34
- version: 0.1.2
34
+ version: 0.4.0
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ~>
40
40
  - !ruby/object:Gem::Version
41
- version: 0.1.2
41
+ version: 0.4.0
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: bundler
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - ~>
47
47
  - !ruby/object:Gem::Version
48
- version: '1.3'
49
- - - ! '>='
48
+ version: '1.5'
49
+ - - '>='
50
50
  - !ruby/object:Gem::Version
51
- version: 1.3.5
51
+ version: 1.5.2
52
52
  type: :development
53
53
  prerelease: false
54
54
  version_requirements: !ruby/object:Gem::Requirement
55
55
  requirements:
56
56
  - - ~>
57
57
  - !ruby/object:Gem::Version
58
- version: '1.3'
59
- - - ! '>='
58
+ version: '1.5'
59
+ - - '>='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.3.5
61
+ version: 1.5.2
62
62
  description: Immutable extensions to objects
63
63
  email:
64
64
  - dan.kubb@gmail.com
@@ -73,6 +73,7 @@ extra_rdoc_files:
73
73
  files:
74
74
  - .gitignore
75
75
  - .rspec
76
+ - .rubocop.yml
76
77
  - .ruby-gemset
77
78
  - .travis.yml
78
79
  - CONTRIBUTING.md
@@ -103,7 +104,6 @@ files:
103
104
  - spec/rcov.opts
104
105
  - spec/spec_helper.rb
105
106
  - spec/support/config_alias.rb
106
- - spec/unit/adamantium/class_methods/included_spec.rb
107
107
  - spec/unit/adamantium/class_methods/new_spec.rb
108
108
  - spec/unit/adamantium/dup_spec.rb
109
109
  - spec/unit/adamantium/fixtures/classes.rb
@@ -117,14 +117,14 @@ files:
117
117
  - spec/unit/adamantium/freezer/flat/class_methods/call_spec.rb
118
118
  - spec/unit/adamantium/freezer/flat/class_methods/freeze_spec.rb
119
119
  - spec/unit/adamantium/memoize_spec.rb
120
- - spec/unit/adamantium/memoized_spec.rb
121
120
  - spec/unit/adamantium/module_methods/freezer_spec.rb
122
121
  - spec/unit/adamantium/module_methods/included_spec.rb
123
122
  - spec/unit/adamantium/module_methods/memoize_spec.rb
124
123
  - spec/unit/adamantium/module_methods/memoized_predicate_spec.rb
125
- - spec/unit/adamantium/module_methods/original_instance_method_spec.rb
126
124
  - spec/unit/adamantium/mutable/freeze_spec.rb
127
125
  - spec/unit/adamantium/mutable/frozen_predicate_spec.rb
126
+ - spec/unit/adamantium/transform_spec.rb
127
+ - spec/unit/adamantium/transform_unless_spec.rb
128
128
  homepage: https://github.com/dkubb/adamantium
129
129
  licenses:
130
130
  - MIT
@@ -135,23 +135,22 @@ require_paths:
135
135
  - lib
136
136
  required_ruby_version: !ruby/object:Gem::Requirement
137
137
  requirements:
138
- - - ! '>='
138
+ - - '>='
139
139
  - !ruby/object:Gem::Version
140
140
  version: '0'
141
141
  required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ! '>='
143
+ - - '>='
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0'
146
146
  requirements: []
147
147
  rubyforge_project:
148
- rubygems_version: 2.0.6
148
+ rubygems_version: 2.1.11
149
149
  signing_key:
150
150
  specification_version: 4
151
151
  summary: Immutable extensions to objects
152
152
  test_files:
153
153
  - spec/integration/adamantium_spec.rb
154
- - spec/unit/adamantium/class_methods/included_spec.rb
155
154
  - spec/unit/adamantium/class_methods/new_spec.rb
156
155
  - spec/unit/adamantium/dup_spec.rb
157
156
  - spec/unit/adamantium/fixtures/classes.rb
@@ -165,12 +164,12 @@ test_files:
165
164
  - spec/unit/adamantium/freezer/flat/class_methods/call_spec.rb
166
165
  - spec/unit/adamantium/freezer/flat/class_methods/freeze_spec.rb
167
166
  - spec/unit/adamantium/memoize_spec.rb
168
- - spec/unit/adamantium/memoized_spec.rb
169
167
  - spec/unit/adamantium/module_methods/freezer_spec.rb
170
168
  - spec/unit/adamantium/module_methods/included_spec.rb
171
169
  - spec/unit/adamantium/module_methods/memoize_spec.rb
172
170
  - spec/unit/adamantium/module_methods/memoized_predicate_spec.rb
173
- - spec/unit/adamantium/module_methods/original_instance_method_spec.rb
174
171
  - spec/unit/adamantium/mutable/freeze_spec.rb
175
172
  - spec/unit/adamantium/mutable/frozen_predicate_spec.rb
173
+ - spec/unit/adamantium/transform_spec.rb
174
+ - spec/unit/adamantium/transform_unless_spec.rb
176
175
  has_rdoc:
@@ -1,40 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- describe Adamantium, '.included' do
6
- let(:object) { described_class }
7
-
8
- subject { object.included(target) }
9
-
10
- let(:included_modules) do
11
- target.singleton_class.included_modules
12
- end
13
-
14
- before { subject }
15
-
16
- context 'when target is a module' do
17
- let(:target) { Module.new }
18
-
19
- it_should_behave_like 'a command method'
20
-
21
- it 'includes Adamantium::ModuleMethods' do
22
- expect(included_modules).to include(Adamantium::ModuleMethods)
23
- end
24
-
25
- it 'does not include Adamantium::ClassMethods' do
26
- expect(included_modules).to_not include(Adamantium::ClassMethods)
27
- end
28
- end
29
-
30
- context 'when target is a class' do
31
- let(:target) { Class.new }
32
-
33
- it 'includes Adamantium::{Class,Module}Methods' do
34
- expect(included_modules).to include(Adamantium::ModuleMethods)
35
- expect(included_modules).to include(Adamantium::ClassMethods)
36
- end
37
-
38
- it_should_behave_like 'a command method'
39
- end
40
- end
@@ -1,29 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
- require File.expand_path('../fixtures/classes', __FILE__)
5
-
6
- describe Adamantium, '#memoized' do
7
- subject { object.memoized(method) }
8
-
9
- let(:described_class) { Class.new(AdamantiumSpecs::Object) }
10
- let(:method) { :test }
11
- let(:value) { String.new.freeze }
12
- let(:object) { described_class.new }
13
-
14
- before do
15
- described_class.memoize(method)
16
- end
17
-
18
- context 'when a method is memoized' do
19
- before do
20
- object.memoize(method, value)
21
- end
22
-
23
- it { should equal(value) }
24
- end
25
-
26
- context 'when a method is not memoized' do
27
- it { should be_nil }
28
- end
29
- end
@@ -1,36 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- describe Adamantium::ModuleMethods, '#original_instance_method' do
6
- subject { object.original_instance_method(name).source_location }
7
-
8
- let(:object) do
9
- Class.new do
10
- include Adamantium
11
-
12
- def foo; end
13
-
14
- const_set(:ORIGINAL, instance_method(:foo).source_location)
15
-
16
- memoize :foo
17
- end
18
- end
19
-
20
- context 'when the method was memoized' do
21
- let(:name) { :foo }
22
-
23
- it 'returns the original method' do
24
- should eql(object::ORIGINAL)
25
- end
26
- end
27
-
28
- context 'when the method was not memoized' do
29
- let(:name) { :bar }
30
-
31
- it 'raises an exception' do
32
- expect { subject }
33
- .to raise_error(ArgumentError, 'No method :bar was memoized')
34
- end
35
- end
36
- end