naught 0.0.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|