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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/.rubocop.yml +74 -0
  4. data/.travis.yml +20 -2
  5. data/Changelog.md +8 -2
  6. data/Gemfile +24 -2
  7. data/README.markdown +30 -7
  8. data/Rakefile +11 -2
  9. data/lib/naught.rb +1 -1
  10. data/lib/naught/basic_object.rb +17 -0
  11. data/lib/naught/conversions.rb +55 -0
  12. data/lib/naught/null_class_builder.rb +33 -21
  13. data/lib/naught/null_class_builder/command.rb +3 -3
  14. data/lib/naught/null_class_builder/commands/define_explicit_conversions.rb +3 -7
  15. data/lib/naught/null_class_builder/commands/define_implicit_conversions.rb +7 -2
  16. data/lib/naught/null_class_builder/commands/impersonate.rb +2 -3
  17. data/lib/naught/null_class_builder/commands/mimic.rb +4 -7
  18. data/lib/naught/null_class_builder/commands/pebble.rb +3 -5
  19. data/lib/naught/null_class_builder/commands/predicates_return.rb +1 -2
  20. data/lib/naught/null_class_builder/commands/singleton.rb +1 -1
  21. data/lib/naught/null_class_builder/commands/traceable.rb +3 -2
  22. data/lib/naught/version.rb +1 -1
  23. data/naught.gemspec +11 -16
  24. data/spec/base_object_spec.rb +2 -2
  25. data/spec/basic_null_object_spec.rb +3 -3
  26. data/spec/blackhole_spec.rb +4 -4
  27. data/spec/explicit_conversions_spec.rb +23 -0
  28. data/spec/functions/actual_spec.rb +4 -4
  29. data/spec/functions/just_spec.rb +7 -7
  30. data/spec/functions/maybe_spec.rb +7 -7
  31. data/spec/functions/null_spec.rb +6 -6
  32. data/spec/implicit_conversions_spec.rb +5 -5
  33. data/spec/mimic_spec.rb +30 -35
  34. data/spec/naught/null_object_builder/command_spec.rb +1 -1
  35. data/spec/naught/null_object_builder_spec.rb +5 -5
  36. data/spec/naught_spec.rb +29 -23
  37. data/spec/pebble_spec.rb +13 -11
  38. data/spec/predicate_spec.rb +18 -14
  39. data/spec/singleton_null_object_spec.rb +4 -4
  40. data/spec/spec_helper.rb +4 -4
  41. data/spec/support/convertable_null.rb +2 -2
  42. data/spec/support/jruby.rb +3 -0
  43. data/spec/support/rubinius.rb +3 -0
  44. data/spec/support/ruby_18.rb +3 -0
  45. metadata +21 -82
  46. data/lib/naught/null_class_builder/conversions_module.rb +0 -57
  47. data/spec/conversions_spec.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 590655f0e3a1d6ace3edabc144bab9b497512816
4
- data.tar.gz: 88d5907481c580e2a725f1078ac84029579a1b8e
3
+ metadata.gz: 890ad068bee3a49dddd992e4c9b5187d4b8c7f2e
4
+ data.tar.gz: f2349e58df72fd26f6e00f0d0b70f98e77439cdd
5
5
  SHA512:
6
- metadata.gz: fb7129d4cef2b7aa3440033c81abf745c094316e44b0ddee3642b73c6208f2f2411d29cce030ba183baa676001204048dcc9510347bfff7aa4c28e4c77dadca5
7
- data.tar.gz: 0552239f6f101b7d21e4c227e34bc4feb17c510c8b57693342934064037de01f6a4c7bfe48eb9eaa9875a8f4ac00fea2caa1a73c0c0788441b416130110057da
6
+ metadata.gz: 1ff56002a0c9051c16852efe538d1799a14eb7480154515e8a907408e380b1717a8fe393b8936f775f1053684e32c41641a075461f09a48f8ef68e3c5e573c06
7
+ data.tar.gz: 4eb1d18c75d4ac998207152005bd20807a15bd68f24b83213b4842ab5185d4c023fd9e09c441c2a148c5274b000a7b194c383337ce68b2583bca2307f50ae0a5
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
@@ -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
@@ -1,2 +1,20 @@
1
- env:
2
- - TRAVIS=true
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
@@ -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 "libnotify"
8
- gem 'coveralls', require: false
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
@@ -107,7 +107,7 @@ null.foo.bar.baz # => <null>
107
107
  null << "hello" << "world" # => <null>
108
108
  ```
109
109
 
110
- ### What's that "config" thing?
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 "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
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]
@@ -1,4 +1,4 @@
1
- require "naught/version"
1
+ require 'naught/version'
2
2
  require 'naught/null_class_builder'
3
3
  require 'naught/null_class_builder/commands'
4
4
 
@@ -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/null_class_builder/conversions_module'
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 = ->{ "<null>" }
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
- @interface_defined
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 :Conversions, builder.generate_conversions_module(self)
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
- def respond_to_missing?(method_name, include_private=false)
74
- command_name = command_name_for_method(method_name)
75
- Commands.const_defined?(command_name) || super
76
- rescue NameError
77
- super
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: true) do |subject|
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: true) do |subject|
151
+ defer(:class => true) do |subject|
140
152
  subject.module_eval do
141
153
  class << self
142
- alias get new
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])/) { $1.upcase }
183
+ method_name.to_s.gsub(/(?:^|_)([a-z])/) { Regexp.last_match[1].upcase }
172
184
  end
173
185
  end
174
186
  end