naught 0.0.3 → 1.0.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 +4 -4
- data/.rspec +2 -0
- data/.rubocop.yml +74 -0
- data/.travis.yml +20 -2
- data/Changelog.md +8 -2
- data/Gemfile +24 -2
- data/README.markdown +30 -7
- data/Rakefile +11 -2
- data/lib/naught.rb +1 -1
- data/lib/naught/basic_object.rb +17 -0
- data/lib/naught/conversions.rb +55 -0
- data/lib/naught/null_class_builder.rb +33 -21
- data/lib/naught/null_class_builder/command.rb +3 -3
- data/lib/naught/null_class_builder/commands/define_explicit_conversions.rb +3 -7
- data/lib/naught/null_class_builder/commands/define_implicit_conversions.rb +7 -2
- data/lib/naught/null_class_builder/commands/impersonate.rb +2 -3
- data/lib/naught/null_class_builder/commands/mimic.rb +4 -7
- data/lib/naught/null_class_builder/commands/pebble.rb +3 -5
- data/lib/naught/null_class_builder/commands/predicates_return.rb +1 -2
- data/lib/naught/null_class_builder/commands/singleton.rb +1 -1
- data/lib/naught/null_class_builder/commands/traceable.rb +3 -2
- data/lib/naught/version.rb +1 -1
- data/naught.gemspec +11 -16
- data/spec/base_object_spec.rb +2 -2
- data/spec/basic_null_object_spec.rb +3 -3
- data/spec/blackhole_spec.rb +4 -4
- data/spec/explicit_conversions_spec.rb +23 -0
- data/spec/functions/actual_spec.rb +4 -4
- data/spec/functions/just_spec.rb +7 -7
- data/spec/functions/maybe_spec.rb +7 -7
- data/spec/functions/null_spec.rb +6 -6
- data/spec/implicit_conversions_spec.rb +5 -5
- data/spec/mimic_spec.rb +30 -35
- data/spec/naught/null_object_builder/command_spec.rb +1 -1
- data/spec/naught/null_object_builder_spec.rb +5 -5
- data/spec/naught_spec.rb +29 -23
- data/spec/pebble_spec.rb +13 -11
- data/spec/predicate_spec.rb +18 -14
- data/spec/singleton_null_object_spec.rb +4 -4
- data/spec/spec_helper.rb +4 -4
- data/spec/support/convertable_null.rb +2 -2
- data/spec/support/jruby.rb +3 -0
- data/spec/support/rubinius.rb +3 -0
- data/spec/support/ruby_18.rb +3 -0
- metadata +21 -82
- data/lib/naught/null_class_builder/conversions_module.rb +0 -57
- data/spec/conversions_spec.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 890ad068bee3a49dddd992e4c9b5187d4b8c7f2e
|
4
|
+
data.tar.gz: f2349e58df72fd26f6e00f0d0b70f98e77439cdd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ff56002a0c9051c16852efe538d1799a14eb7480154515e8a907408e380b1717a8fe393b8936f775f1053684e32c41641a075461f09a48f8ef68e3c5e573c06
|
7
|
+
data.tar.gz: 4eb1d18c75d4ac998207152005bd20807a15bd68f24b83213b4842ab5185d4c023fd9e09c441c2a148c5274b000a7b194c383337ce68b2583bca2307f50ae0a5
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
AllCops:
|
2
|
+
Includes:
|
3
|
+
- 'Gemfile'
|
4
|
+
- 'Rakefile'
|
5
|
+
- 'naught.gemspec'
|
6
|
+
|
7
|
+
# Avoid long parameter lists
|
8
|
+
ParameterLists:
|
9
|
+
Max: 4
|
10
|
+
CountKeywordArgs: true
|
11
|
+
|
12
|
+
ClassLength:
|
13
|
+
Max: 144 # TODO: Lower to 100
|
14
|
+
|
15
|
+
MethodLength:
|
16
|
+
CountComments: false
|
17
|
+
Max: 21 # TODO: Lower to 15
|
18
|
+
|
19
|
+
# Avoid more than `Max` levels of nesting.
|
20
|
+
BlockNesting:
|
21
|
+
Max: 2
|
22
|
+
|
23
|
+
# Align with the style guide.
|
24
|
+
CollectionMethods:
|
25
|
+
PreferredMethods:
|
26
|
+
map: 'collect'
|
27
|
+
reduce: 'inject'
|
28
|
+
find: 'detect'
|
29
|
+
find_all: 'select'
|
30
|
+
|
31
|
+
# Limit line length
|
32
|
+
LineLength:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
# Disable documentation checking until a class needs to be documented once
|
36
|
+
Documentation:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
# Enforce Ruby 1.8-compatible hash syntax
|
40
|
+
HashSyntax:
|
41
|
+
EnforcedStyle: hash_rockets
|
42
|
+
|
43
|
+
# No spaces inside hash literals
|
44
|
+
SpaceInsideHashLiteralBraces:
|
45
|
+
EnforcedStyle: no_space
|
46
|
+
|
47
|
+
# Allow dots at the end of lines
|
48
|
+
DotPosition:
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
# Don't require magic comment at the top of every file
|
52
|
+
Encoding:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
EmptyLinesAroundAccessModifier:
|
56
|
+
Enabled: true
|
57
|
+
|
58
|
+
# Align ends correctly
|
59
|
+
EndAlignment:
|
60
|
+
AlignWith: variable
|
61
|
+
|
62
|
+
# Indentation of when/else
|
63
|
+
CaseIndentation:
|
64
|
+
IndentWhenRelativeTo: end
|
65
|
+
IndentOneStep: false
|
66
|
+
|
67
|
+
Lambda:
|
68
|
+
Enabled: false
|
69
|
+
|
70
|
+
MethodName:
|
71
|
+
Enabled: false
|
72
|
+
|
73
|
+
ClassVars:
|
74
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,2 +1,20 @@
|
|
1
|
-
|
2
|
-
-
|
1
|
+
before_install:
|
2
|
+
- gem update --system 2.1.11
|
3
|
+
- gem --version
|
4
|
+
bundler_args: --without development
|
5
|
+
language: ruby
|
6
|
+
rvm:
|
7
|
+
- 1.8.7
|
8
|
+
- 1.9.2
|
9
|
+
- 1.9.3
|
10
|
+
- 2.0.0
|
11
|
+
- 2.1.0
|
12
|
+
- jruby
|
13
|
+
- jruby-head
|
14
|
+
- rbx
|
15
|
+
- ruby-head
|
16
|
+
matrix:
|
17
|
+
allow_failures:
|
18
|
+
- rvm: jruby-head
|
19
|
+
- rvm: ruby-head
|
20
|
+
fast_finish: true
|
data/Changelog.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
## 1.0.0
|
2
|
+
|
3
|
+
- [Replace `::BasicObject` with `Naught::BasicObject`](https://github.com/avdi/naught/commit/8defad0bf9eb65e33054bf0a6e9c625c87c3e6df)
|
4
|
+
- [Delegate explicit conversions to nil instead of defining them explicitly](https://github.com/avdi/naught/commit/85c195de80ed56993b88f47e09112c903a92a167)
|
5
|
+
- Add support for (and run tests on) Ruby 1.8, 1.9, 2.0, 2.1, JRuby, and Rubinius
|
6
|
+
|
1
7
|
## 0.0.3
|
2
8
|
|
3
9
|
Features:
|
4
10
|
|
5
|
-
- New "pebble" mode
|
6
|
-
|
11
|
+
- New "pebble" mode (Guilherme Carvalho)
|
12
|
+
|
data/Gemfile
CHANGED
@@ -3,7 +3,29 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in naught.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
gem 'rake'
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
platforms :ruby_19, :ruby_20, :ruby_21 do
|
10
|
+
gem 'guard'
|
11
|
+
gem 'guard-bundler'
|
12
|
+
gem 'guard-rspec'
|
13
|
+
end
|
14
|
+
gem 'pry'
|
15
|
+
gem 'pry-rescue'
|
16
|
+
end
|
17
|
+
|
6
18
|
group :test do
|
7
|
-
gem
|
8
|
-
gem '
|
19
|
+
gem 'coveralls', :require => false
|
20
|
+
gem 'json', :platforms => [:jruby, :rbx, :ruby_18, :ruby_19]
|
21
|
+
gem 'libnotify'
|
22
|
+
gem 'mime-types', '~> 1.25', :platforms => [:jruby, :ruby_18]
|
23
|
+
gem 'rspec', '>= 2.14'
|
24
|
+
gem 'rubocop', '>= 0.16', :platforms => [:ruby_19, :ruby_20, :ruby_21]
|
25
|
+
end
|
26
|
+
|
27
|
+
platforms :rbx do
|
28
|
+
gem 'racc'
|
29
|
+
gem 'rubinius-coverage', '~> 2.0'
|
30
|
+
gem 'rubysl', '~> 2.0'
|
9
31
|
end
|
data/README.markdown
CHANGED
@@ -107,7 +107,7 @@ null.foo.bar.baz # => <null>
|
|
107
107
|
null << "hello" << "world" # => <null>
|
108
108
|
```
|
109
109
|
|
110
|
-
|
110
|
+
#### What's that "config" thing?
|
111
111
|
|
112
112
|
That's what you use to customize the generated class to your
|
113
113
|
liking. Internally, Naught uses the [Builder
|
@@ -176,8 +176,8 @@ null_io = NullIO.new
|
|
176
176
|
|
177
177
|
null_io << "foo" # => nil
|
178
178
|
null_io.readline # => nil
|
179
|
-
null_io.foobar # =>
|
180
|
-
# ~> -:11:in `<main>': undefined method `foobar' for
|
179
|
+
null_io.foobar # =>
|
180
|
+
# ~> -:11:in `<main>': undefined method `foobar' for
|
181
181
|
# <null:IO>:NullIO (NoMethodError)
|
182
182
|
```
|
183
183
|
|
@@ -205,6 +205,23 @@ end
|
|
205
205
|
# >> Yep, checks out!
|
206
206
|
```
|
207
207
|
|
208
|
+
#### What about predicate methods? You know, the ones that end with question marks? Shouldn't they return `false` instead of `nil`?
|
209
|
+
|
210
|
+
Sure, if you'd like.
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
require 'naught'
|
214
|
+
|
215
|
+
NullObject = Naught.build do |config|
|
216
|
+
config.predicates_return false
|
217
|
+
end
|
218
|
+
|
219
|
+
null = NullObject.new
|
220
|
+
null.foo # => nil
|
221
|
+
null.bar? # => false
|
222
|
+
null.nil? # => false
|
223
|
+
```
|
224
|
+
|
208
225
|
#### Alright smartypants. What if I want to add my own methods?
|
209
226
|
|
210
227
|
Not a problem, just define them in the `.build` block.
|
@@ -214,6 +231,7 @@ require 'naught'
|
|
214
231
|
|
215
232
|
NullObject = Naught.build do |config|
|
216
233
|
config.define_explicit_conversions
|
234
|
+
config.predicates_return false
|
217
235
|
def to_path
|
218
236
|
"/dev/null"
|
219
237
|
end
|
@@ -222,11 +240,16 @@ NullObject = Naught.build do |config|
|
|
222
240
|
def to_s
|
223
241
|
"NOTHING TO SEE HERE MOVE ALONG"
|
224
242
|
end
|
243
|
+
|
244
|
+
def nil?
|
245
|
+
true
|
246
|
+
end
|
225
247
|
end
|
226
248
|
|
227
249
|
null = NullObject.new
|
228
|
-
null.to_s # => "NOTHING TO SEE HERE MOVE ALONG"
|
229
250
|
null.to_path # => "/dev/null"
|
251
|
+
null.to_s # => "NOTHING TO SEE HERE MOVE ALONG"
|
252
|
+
null.nil? # => true
|
230
253
|
```
|
231
254
|
|
232
255
|
#### Got anything else up your sleeve?
|
@@ -245,8 +268,8 @@ null = NullObject.instance
|
|
245
268
|
|
246
269
|
null.__id__ # => 17844080
|
247
270
|
NullObject.instance.__id__ # => 17844080
|
248
|
-
NullObject.new # =>
|
249
|
-
# ~> -:11:in `<main>': private method `new' called for
|
271
|
+
NullObject.new # =>
|
272
|
+
# ~> -:11:in `<main>': private method `new' called for
|
250
273
|
# NullObject:Class (NoMethodError)
|
251
274
|
```
|
252
275
|
|
@@ -280,7 +303,7 @@ NullObject = Naught.build do |config|
|
|
280
303
|
else
|
281
304
|
config.singleton
|
282
305
|
end
|
283
|
-
end
|
306
|
+
end
|
284
307
|
```
|
285
308
|
|
286
309
|
The only caveat is that when swapping between singleton and
|
data/Rakefile
CHANGED
@@ -1,6 +1,15 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
3
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
-
|
6
|
+
begin
|
7
|
+
require 'rubocop/rake_task'
|
8
|
+
Rubocop::RakeTask.new
|
9
|
+
rescue LoadError
|
10
|
+
task :rubocop do
|
11
|
+
$stderr.puts 'Rubocop is disabled'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => [:spec, :rubocop]
|
data/lib/naught.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Naught
|
2
|
+
if defined? ::BasicObject
|
3
|
+
class BasicObject < ::BasicObject
|
4
|
+
end
|
5
|
+
else
|
6
|
+
class BasicObject #:nodoc:
|
7
|
+
keep = %w[
|
8
|
+
! != == __id__ __send__ equal? instance_eval instance_exec
|
9
|
+
method_missing singleton_method_added singleton_method_removed
|
10
|
+
singleton_method_undefined
|
11
|
+
]
|
12
|
+
instance_methods.each do |method_name|
|
13
|
+
undef_method(method_name) unless keep.include?(method_name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Naught
|
2
|
+
module Conversions
|
3
|
+
def self.included(null_class)
|
4
|
+
unless class_variable_defined?(:@@included) && @@included
|
5
|
+
@@null_class = null_class
|
6
|
+
@@null_equivs = null_class::NULL_EQUIVS
|
7
|
+
@@included = true
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def Null(object = :nothing_passed)
|
13
|
+
case object
|
14
|
+
when NullObjectTag
|
15
|
+
object
|
16
|
+
when :nothing_passed, *@@null_equivs
|
17
|
+
@@null_class.get(:caller => caller(1))
|
18
|
+
else
|
19
|
+
fail ArgumentError, "#{object.inspect} is not null!"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def Maybe(object = nil)
|
24
|
+
object = yield if block_given?
|
25
|
+
case object
|
26
|
+
when NullObjectTag
|
27
|
+
object
|
28
|
+
when *@@null_equivs
|
29
|
+
@@null_class.get(:caller => caller(1))
|
30
|
+
else
|
31
|
+
object
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def Just(object = nil)
|
36
|
+
object = yield if block_given?
|
37
|
+
case object
|
38
|
+
when NullObjectTag, *@@null_equivs
|
39
|
+
fail ArgumentError, "Null value: #{object.inspect}"
|
40
|
+
else
|
41
|
+
object
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def Actual(object = nil)
|
46
|
+
object = yield if block_given?
|
47
|
+
case object
|
48
|
+
when NullObjectTag
|
49
|
+
nil
|
50
|
+
else
|
51
|
+
object
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require 'naught/
|
1
|
+
require 'naught/basic_object'
|
2
|
+
require 'naught/conversions'
|
2
3
|
|
3
4
|
module Naught
|
4
5
|
class NullClassBuilder
|
@@ -10,14 +11,14 @@ module Naught
|
|
10
11
|
|
11
12
|
def initialize
|
12
13
|
@interface_defined = false
|
13
|
-
@base_class = BasicObject
|
14
|
-
@inspect_proc =
|
14
|
+
@base_class = Naught::BasicObject
|
15
|
+
@inspect_proc = lambda { '<null>' }
|
15
16
|
@stub_strategy = :stub_method_returning_nil
|
16
17
|
define_basic_methods
|
17
18
|
end
|
18
19
|
|
19
20
|
def interface_defined?
|
20
|
-
|
21
|
+
!!@interface_defined
|
21
22
|
end
|
22
23
|
|
23
24
|
def customize(&customization_block)
|
@@ -33,10 +34,6 @@ module Naught
|
|
33
34
|
@null_equivalents ||= [nil]
|
34
35
|
end
|
35
36
|
|
36
|
-
def generate_conversions_module(null_class)
|
37
|
-
ConversionsModule.new(null_class, null_equivalents)
|
38
|
-
end
|
39
|
-
|
40
37
|
def generate_class
|
41
38
|
respond_to_any_message unless interface_defined?
|
42
39
|
generation_mod = Module.new
|
@@ -48,7 +45,13 @@ module Naught
|
|
48
45
|
null_class = Class.new(@base_class) do
|
49
46
|
const_set :GeneratedMethods, generation_mod
|
50
47
|
const_set :Customizations, customization_mod
|
51
|
-
const_set :
|
48
|
+
const_set :NULL_EQUIVS, builder.null_equivalents
|
49
|
+
include Conversions
|
50
|
+
remove_const :NULL_EQUIVS
|
51
|
+
Conversions.instance_methods.each do |instance_method|
|
52
|
+
undef_method(instance_method)
|
53
|
+
end
|
54
|
+
const_set :Conversions, Conversions
|
52
55
|
|
53
56
|
include NullObjectTag
|
54
57
|
include generation_mod
|
@@ -70,11 +73,20 @@ module Naught
|
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
76
|
+
if RUBY_VERSION >= '1.9'
|
77
|
+
def respond_to_missing?(method_name, include_private = false)
|
78
|
+
command_name = command_name_for_method(method_name)
|
79
|
+
Commands.const_defined?(command_name) || super
|
80
|
+
rescue NameError
|
81
|
+
super
|
82
|
+
end
|
83
|
+
else
|
84
|
+
def respond_to?(method_name, include_private = false)
|
85
|
+
command_name = command_name_for_method(method_name)
|
86
|
+
Commands.const_defined?(command_name) || super
|
87
|
+
rescue NameError
|
88
|
+
super
|
89
|
+
end
|
78
90
|
end
|
79
91
|
|
80
92
|
############################################################################
|
@@ -88,7 +100,7 @@ module Naught
|
|
88
100
|
end
|
89
101
|
|
90
102
|
def respond_to_any_message
|
91
|
-
defer(prepend
|
103
|
+
defer(:prepend => true) do |subject|
|
92
104
|
subject.module_eval do
|
93
105
|
def respond_to?(*)
|
94
106
|
true
|
@@ -99,7 +111,7 @@ module Naught
|
|
99
111
|
@interface_defined = true
|
100
112
|
end
|
101
113
|
|
102
|
-
def defer(options={}, &deferred_operation)
|
114
|
+
def defer(options = {}, &deferred_operation)
|
103
115
|
list = options[:class] ? class_operations : operations
|
104
116
|
if options[:prepend]
|
105
117
|
list.unshift(deferred_operation)
|
@@ -136,10 +148,10 @@ module Naught
|
|
136
148
|
end
|
137
149
|
|
138
150
|
def define_basic_class_methods
|
139
|
-
defer(class
|
151
|
+
defer(:class => true) do |subject|
|
140
152
|
subject.module_eval do
|
141
153
|
class << self
|
142
|
-
|
154
|
+
alias_method :get, :new
|
143
155
|
end
|
144
156
|
klass = self
|
145
157
|
define_method(:class) { klass }
|
@@ -157,18 +169,18 @@ module Naught
|
|
157
169
|
|
158
170
|
def stub_method_returning_nil(subject, name)
|
159
171
|
subject.module_eval do
|
160
|
-
define_method(name) {|*| nil }
|
172
|
+
define_method(name) { |*| nil }
|
161
173
|
end
|
162
174
|
end
|
163
175
|
|
164
176
|
def stub_method_returning_self(subject, name)
|
165
177
|
subject.module_eval do
|
166
|
-
define_method(name) {|*| self }
|
178
|
+
define_method(name) { |*| self }
|
167
179
|
end
|
168
180
|
end
|
169
181
|
|
170
182
|
def command_name_for_method(method_name)
|
171
|
-
method_name.to_s.gsub(/(?:^|_)([a-z])/) {
|
183
|
+
method_name.to_s.gsub(/(?:^|_)([a-z])/) { Regexp.last_match[1].upcase }
|
172
184
|
end
|
173
185
|
end
|
174
186
|
end
|