naught 0.0.3 → 1.0.0

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