naught 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 890ad068bee3a49dddd992e4c9b5187d4b8c7f2e
4
- data.tar.gz: f2349e58df72fd26f6e00f0d0b70f98e77439cdd
3
+ metadata.gz: 429858c6dc05004904b5c95c8e536587996175fb
4
+ data.tar.gz: 06ac8cf2ac0868e8b9d12d9cc15ee2c93c30428d
5
5
  SHA512:
6
- metadata.gz: 1ff56002a0c9051c16852efe538d1799a14eb7480154515e8a907408e380b1717a8fe393b8936f775f1053684e32c41641a075461f09a48f8ef68e3c5e573c06
7
- data.tar.gz: 4eb1d18c75d4ac998207152005bd20807a15bd68f24b83213b4842ab5185d4c023fd9e09c441c2a148c5274b000a7b194c383337ce68b2583bca2307f50ae0a5
6
+ metadata.gz: 53cc9f5fc1b17d678163f02c7d61e967895a21afb01a93bcddc68963654e036051cfd303eb492f11da7d1b6e67508ccaf8ebe40ee2b45ec0d3884cec11ce123f
7
+ data.tar.gz: 1bb2ba430a1be17b50394c2ea2f3e035fec669d4b014c61726cfad653f55c1f42217534d1f920bd9d9cb62096ebb574abe8da0f8017e86d6739a5accb1579277
@@ -1,74 +1,65 @@
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
1
+ Lint/NestedMethodDefinition:
2
+ Enabled: false
11
3
 
12
- ClassLength:
13
- Max: 144 # TODO: Lower to 100
4
+ Metrics/BlockNesting:
5
+ Max: 2
14
6
 
15
- MethodLength:
7
+ Metrics/LineLength:
8
+ AllowURI: true
9
+ Max: 93 # TODO: Lower to 80
10
+
11
+ Metrics/MethodLength:
16
12
  CountComments: false
17
- Max: 21 # TODO: Lower to 15
13
+ Max: 21 # TODO: Lower to 15
18
14
 
19
- # Avoid more than `Max` levels of nesting.
20
- BlockNesting:
21
- Max: 2
15
+ Metrics/ParameterLists:
16
+ Max: 4
17
+ CountKeywordArgs: true
18
+
19
+ Style/AccessModifierIndentation:
20
+ EnforcedStyle: outdent
21
+
22
+ Style/ClassVars:
23
+ Enabled: false
22
24
 
23
- # Align with the style guide.
24
- CollectionMethods:
25
+ Style/CollectionMethods:
26
+ Enabled: true
25
27
  PreferredMethods:
26
28
  map: 'collect'
29
+ map!: 'collect!'
27
30
  reduce: 'inject'
28
31
  find: 'detect'
29
32
  find_all: 'select'
30
33
 
31
- # Limit line length
32
- LineLength:
34
+ Style/Documentation:
33
35
  Enabled: false
34
36
 
35
- # Disable documentation checking until a class needs to be documented once
36
- Documentation:
37
- Enabled: false
37
+ Style/DotPosition:
38
+ EnforcedStyle: trailing
38
39
 
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:
40
+ Style/DoubleNegation:
49
41
  Enabled: false
50
42
 
51
- # Don't require magic comment at the top of every file
52
- Encoding:
43
+ Style/EachWithObject:
53
44
  Enabled: false
54
45
 
55
- EmptyLinesAroundAccessModifier:
56
- Enabled: true
57
-
58
- # Align ends correctly
59
- EndAlignment:
60
- AlignWith: variable
46
+ Style/Encoding:
47
+ Enabled: false
61
48
 
62
- # Indentation of when/else
63
- CaseIndentation:
64
- IndentWhenRelativeTo: end
65
- IndentOneStep: false
49
+ Style/HashSyntax:
50
+ EnforcedStyle: hash_rockets
66
51
 
67
- Lambda:
52
+ Style/Lambda:
68
53
  Enabled: false
69
54
 
70
- MethodName:
55
+ Style/MethodName:
71
56
  Enabled: false
72
57
 
73
- ClassVars:
74
- Enabled: false
58
+ Style/RaiseArgs:
59
+ EnforcedStyle: compact
60
+
61
+ Style/SpaceInsideHashLiteralBraces:
62
+ EnforcedStyle: no_space
63
+
64
+ Style/TrailingComma:
65
+ EnforcedStyleForMultiline: 'comma'
@@ -1,20 +1,24 @@
1
- before_install:
2
- - gem update --system 2.1.11
3
- - gem --version
4
- bundler_args: --without development
1
+ before_install: gem update bundler
2
+ bundler_args: --without development --retry=3 --jobs=3
3
+ cache: bundler
4
+ env:
5
+ global:
6
+ - JRUBY_OPTS="$JRUBY_OPTS --debug"
5
7
  language: ruby
6
8
  rvm:
7
9
  - 1.8.7
8
- - 1.9.2
9
10
  - 1.9.3
10
11
  - 2.0.0
11
- - 2.1.0
12
- - jruby
12
+ - 2.1
13
+ - 2.2
14
+ - jruby-9000
13
15
  - jruby-head
14
- - rbx
16
+ - rbx-2
15
17
  - ruby-head
16
18
  matrix:
17
19
  allow_failures:
18
20
  - rvm: jruby-head
21
+ - rvm: rbx-2
19
22
  - rvm: ruby-head
20
23
  fast_finish: true
24
+ sudo: false
@@ -1,3 +1,9 @@
1
+ ## 1.1.0
2
+
3
+ - [Make it possible to supply an example object to mimic, with no class.](https://github.com/avdi/naught/commit/df2b62c027812760ce200177ce056929b5aea339)
4
+ - [Define implicit conversion for to_hash](https://github.com/avdi/naught/commit/e20dc472d3bc71ba927d6ddb0fb0032e1646df77)
5
+ - [Define implicit conversion for to_int](https://github.com/avdi/naught/commit/d32d4ea32a9a847bffd6cf18f480bdfaaf7a3641)
6
+
1
7
  ## 1.0.0
2
8
 
3
9
  - [Replace `::BasicObject` with `Naught::BasicObject`](https://github.com/avdi/naught/commit/8defad0bf9eb65e33054bf0a6e9c625c87c3e6df)
data/Gemfile CHANGED
@@ -6,13 +6,12 @@ gemspec
6
6
  gem 'rake'
7
7
 
8
8
  group :development do
9
- platforms :ruby_19, :ruby_20, :ruby_21 do
9
+ platforms :ruby_19, :ruby_20, :ruby_21, :ruby_22 do
10
10
  gem 'guard'
11
11
  gem 'guard-bundler'
12
12
  gem 'guard-rspec'
13
13
  end
14
14
  gem 'pry'
15
- gem 'pry-rescue'
16
15
  end
17
16
 
18
17
  group :test do
@@ -20,12 +19,7 @@ group :test do
20
19
  gem 'json', :platforms => [:jruby, :rbx, :ruby_18, :ruby_19]
21
20
  gem 'libnotify'
22
21
  gem 'mime-types', '~> 1.25', :platforms => [:jruby, :ruby_18]
22
+ gem 'rest-client', '~> 1.6.0', :platforms => [:jruby, :ruby_18]
23
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'
24
+ gem 'rubocop', '~> 0.34.0', :platforms => [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
31
25
  end
data/Guardfile CHANGED
@@ -3,13 +3,13 @@ guard 'bundler' do
3
3
  watch(/^.+\.gemspec/)
4
4
  end
5
5
 
6
- guard :rspec, cli: '-fs --color --order rand' do
6
+ guard :rspec, :cli => '-fs --color --order rand' do
7
7
  watch(%r{^spec/.+_spec\.rb$})
8
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
9
- watch('spec/spec_helper.rb') { "spec" }
8
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
9
+ watch('spec/spec_helper.rb') { 'spec' }
10
10
  end
11
11
 
12
- guard 'ctags-bundler', emacs: true, src_path: ["lib", "spec/support"] do
13
- watch(/^(lib|spec\/support)\/.*\.rb$/)
12
+ guard 'ctags-bundler', :emacs => true, :src_path => ['lib', 'spec/support'] do
13
+ watch(%r{^(lib|spec/support)/.*\.rb$})
14
14
  watch('Gemfile.lock')
15
15
  end
@@ -1,7 +1,16 @@
1
- [![Build Status](https://travis-ci.org/avdi/naught.png?branch=master)](https://travis-ci.org/avdi/naught)
2
- [![Code Climate](https://codeclimate.com/github/avdi/naught.png)](https://codeclimate.com/github/avdi/naught)
3
- [![Coverage Status](https://coveralls.io/repos/avdi/naught/badge.png?branch=master)](https://coveralls.io/r/avdi/naught?branch=master)
4
- [![Gem Version](https://badge.fury.io/rb/naught.png)](http://badge.fury.io/rb/naught)
1
+ [![Gem Version](https://badge.fury.io/rb/naught.svg)][gem]
2
+ [![Build Status](https://travis-ci.org/avdi/naught.svg?branch=master)][travis]
3
+ [![Dependency Status](https://gemnasium.com/avdi/naught.svg)][gemnasium]
4
+ [![Code Climate](https://codeclimate.com/github/avdi/naught/badges/gpa.svg)][codeclimate]
5
+ [![Coverage Status](https://coveralls.io/repos/avdi/naught/badge.svg?branch=master&service=github)][coveralls]
6
+ [![Inline docs](http://inch-ci.org/github/avdi/naught.svg?branch=master)][docs]
7
+
8
+ [gem]: https://rubygems.org/gems/naught
9
+ [travis]: https://travis-ci.org/avdi/naught
10
+ [gemnasium]: https://gemnasium.com/avdi/naught
11
+ [codeclimate]: https://codeclimate.com/github/avdi/naught
12
+ [coveralls]: https://coveralls.io/github/avdi/naught?branch=master
13
+ [docs]: http://inch-ci.org/github/avdi/naught
5
14
 
6
15
  A quick intro to Naught
7
16
  -------------------------
@@ -205,6 +214,25 @@ end
205
214
  # >> Yep, checks out!
206
215
  ```
207
216
 
217
+ #### My objects are unique and special snowflakes, with new methods added to them at runtime. How are you gonna mimic *that*, hotshot?
218
+
219
+ So long as you can create an object to serve as an example, Naught can copy the interface of that object (both the methods defined by its class, and its singleton methods).
220
+
221
+ ```ruby
222
+ require "naught"
223
+ require "logging"
224
+
225
+ log = Logging.logger["test"]
226
+ log.info
227
+
228
+ NullLog = Naught.build do |config|
229
+ config.mimic example: log
230
+ end
231
+
232
+ null_log = NullLog.new
233
+ null_log.info # => nil
234
+ ```
235
+
208
236
  #### What about predicate methods? You know, the ones that end with question marks? Shouldn't they return `false` instead of `nil`?
209
237
 
210
238
  Sure, if you'd like.
@@ -397,7 +425,7 @@ gem install naught
397
425
  Requirements
398
426
  --------------
399
427
 
400
- - Ruby 1.9
428
+ - Ruby
401
429
 
402
430
  Contributing
403
431
  --------------
@@ -417,6 +445,10 @@ This isn't the first Ruby Null Object library. Others to check out include:
417
445
  - [NullAndVoid](https://github.com/jfelchner/null_and_void)
418
446
  - [BlankSlate](https://github.com/saturnflyer/blank_slate)
419
447
 
448
+ The Book
449
+ --------
450
+
451
+ If you've read this far, you might be interested in the short ebook, [*Much Ado About Naught*](https://shiprise.dpdcart.com/cart/add?product_id=64334&method_id=66165), I (Avdi) wrote as I developed this library. It's a fun exploration of Ruby metaprogramming techniques as applied to writing a Ruby gem. You can [read the introduction here](http://devblog.avdi.org/introduction-to-much-ado-about-naught/).
420
452
 
421
453
  Further reading
422
454
  -----------------
@@ -434,3 +466,9 @@ Further reading
434
466
  - [Null Objects and
435
467
  Falsiness](http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/),
436
468
  by Avdi Grimm
469
+
470
+ Libraries Using Naught
471
+ -----------------------
472
+
473
+ - [ActiveNull](https://github.com/Originate/active_null) Null Model support for ActiveRecord.
474
+ - [Twitter](https://github.com/sferik/twitter) A Ruby interface to the Twitter API.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ RSpec::Core::RakeTask.new(:spec)
5
5
 
6
6
  begin
7
7
  require 'rubocop/rake_task'
8
- Rubocop::RakeTask.new
8
+ RuboCop::RakeTask.new
9
9
  rescue LoadError
10
10
  task :rubocop do
11
11
  $stderr.puts 'Rubocop is disabled'
@@ -4,11 +4,11 @@ module Naught
4
4
  end
5
5
  else
6
6
  class BasicObject #:nodoc:
7
- keep = %w[
7
+ keep = %w(
8
8
  ! != == __id__ __send__ equal? instance_eval instance_exec
9
9
  method_missing singleton_method_added singleton_method_removed
10
10
  singleton_method_undefined
11
- ]
11
+ )
12
12
  instance_methods.each do |method_name|
13
13
  undef_method(method_name) unless keep.include?(method_name)
14
14
  end
@@ -16,7 +16,7 @@ module Naught
16
16
  when :nothing_passed, *@@null_equivs
17
17
  @@null_class.get(:caller => caller(1))
18
18
  else
19
- fail ArgumentError, "#{object.inspect} is not null!"
19
+ fail(ArgumentError.new("#{object.inspect} is not null!"))
20
20
  end
21
21
  end
22
22
 
@@ -36,7 +36,7 @@ module Naught
36
36
  object = yield if block_given?
37
37
  case object
38
38
  when NullObjectTag, *@@null_equivs
39
- fail ArgumentError, "Null value: #{object.inspect}"
39
+ fail(ArgumentError.new("Null value: #{object.inspect}"))
40
40
  else
41
41
  object
42
42
  end
@@ -2,12 +2,13 @@ require 'naught/basic_object'
2
2
  require 'naught/conversions'
3
3
 
4
4
  module Naught
5
- class NullClassBuilder
5
+ class NullClassBuilder # rubocop:disable ClassLength
6
6
  # make sure this module exists
7
7
  module Commands
8
8
  end
9
9
 
10
10
  attr_accessor :base_class, :inspect_proc, :interface_defined
11
+ alias_method :interface_defined?, :interface_defined
11
12
 
12
13
  def initialize
13
14
  @interface_defined = false
@@ -17,10 +18,6 @@ module Naught
17
18
  define_basic_methods
18
19
  end
19
20
 
20
- def interface_defined?
21
- !!@interface_defined
22
- end
23
-
24
21
  def customize(&customization_block)
25
22
  return unless customization_block
26
23
  customization_module.module_exec(self, &customization_block)
@@ -34,7 +31,7 @@ module Naught
34
31
  @null_equivalents ||= [nil]
35
32
  end
36
33
 
37
- def generate_class
34
+ def generate_class # rubocop:disable AbcSize
38
35
  respond_to_any_message unless interface_defined?
39
36
  generation_mod = Module.new
40
37
  customization_mod = customization_module # get a local binding
@@ -63,32 +60,6 @@ module Naught
63
60
  null_class
64
61
  end
65
62
 
66
- def method_missing(method_name, *args, &block)
67
- command_name = command_name_for_method(method_name)
68
- if Commands.const_defined?(command_name)
69
- command_class = Commands.const_get(command_name)
70
- command_class.new(self, *args, &block).call
71
- else
72
- super
73
- end
74
- end
75
-
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
90
- end
91
-
92
63
  ############################################################################
93
64
  # Builder API
94
65
  #
@@ -124,7 +95,39 @@ module Naught
124
95
  send(@stub_strategy, subject, name)
125
96
  end
126
97
 
127
- private
98
+ def method_missing(method_name, *args, &block)
99
+ command_name = command_name_for_method(method_name)
100
+ if Commands.const_defined?(command_name)
101
+ command_class = Commands.const_get(command_name)
102
+ command_class.new(self, *args, &block).call
103
+ else
104
+ super
105
+ end
106
+ end
107
+
108
+ if RUBY_VERSION >= '1.9'
109
+ def respond_to_missing?(method_name, include_private = false)
110
+ respond_to_definition(method_name, include_private, :respond_to_missing?)
111
+ end
112
+ else
113
+ def respond_to?(method_name, include_private = false)
114
+ respond_to_definition(method_name, include_private, :respond_to?)
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def respond_to_definition(method_name, include_private, respond_to_method_name)
121
+ command_name = command_name_for_method(method_name)
122
+ Commands.const_defined?(command_name) ||
123
+ super_duper(respond_to_method_name, method_name, include_private)
124
+ rescue NameError
125
+ super_duper(respond_to_method_name, method_name, include_private)
126
+ end
127
+
128
+ def super_duper(method_name, *args)
129
+ self.class.superclass.send(method_name, *args)
130
+ end
128
131
 
129
132
  def define_basic_methods
130
133
  define_basic_instance_methods
@@ -8,8 +8,7 @@ module Naught
8
8
  end
9
9
 
10
10
  def call
11
- fail NotImplementedError,
12
- 'Method #call should be overriden in child classes'
11
+ fail(NotImplementedError.new('Method #call should be overriden in child classes'))
13
12
  end
14
13
 
15
14
  def defer(options = {}, &block)
@@ -1,13 +1,17 @@
1
1
  require 'forwardable'
2
2
  require 'naught/null_class_builder/command'
3
3
 
4
- module Naught::NullClassBuilder::Commands
5
- class DefineExplicitConversions < ::Naught::NullClassBuilder::Command
6
- def call
7
- defer do |subject|
8
- subject.module_eval do
9
- extend Forwardable
10
- def_delegators :nil, :to_a, :to_c, :to_f, :to_h, :to_i, :to_r, :to_s
4
+ module Naught
5
+ class NullClassBuilder
6
+ module Commands
7
+ class DefineExplicitConversions < ::Naught::NullClassBuilder::Command
8
+ def call
9
+ defer do |subject|
10
+ subject.module_eval do
11
+ extend Forwardable
12
+ def_delegators :nil, :to_a, :to_c, :to_f, :to_h, :to_i, :to_r, :to_s
13
+ end
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -1,16 +1,28 @@
1
1
  require 'naught/null_class_builder/command'
2
2
 
3
- module Naught::NullClassBuilder::Commands
4
- class DefineImplicitConversions < ::Naught::NullClassBuilder::Command
5
- def call
6
- defer do |subject|
7
- subject.module_eval do
8
- def to_ary
9
- []
10
- end
3
+ module Naught
4
+ class NullClassBuilder
5
+ module Commands
6
+ class DefineImplicitConversions < ::Naught::NullClassBuilder::Command
7
+ def call
8
+ defer do |subject|
9
+ subject.module_eval do
10
+ def to_ary
11
+ []
12
+ end
13
+
14
+ def to_hash
15
+ {}
16
+ end
17
+
18
+ def to_int
19
+ 0
20
+ end
11
21
 
12
- def to_str
13
- ''
22
+ def to_str
23
+ ''
24
+ end
25
+ end
14
26
  end
15
27
  end
16
28
  end
@@ -1,8 +1,12 @@
1
- module Naught::NullClassBuilder::Commands
2
- class Impersonate < Naught::NullClassBuilder::Commands::Mimic
3
- def initialize(builder, class_to_impersonate, options = {})
4
- super
5
- builder.base_class = class_to_impersonate
1
+ module Naught
2
+ class NullClassBuilder
3
+ module Commands
4
+ class Impersonate < Naught::NullClassBuilder::Commands::Mimic
5
+ def initialize(builder, class_to_impersonate, options = {})
6
+ super
7
+ builder.base_class = class_to_impersonate
8
+ end
9
+ end
6
10
  end
7
11
  end
8
12
  end
@@ -1,37 +1,55 @@
1
1
  require 'naught/basic_object'
2
2
  require 'naught/null_class_builder/command'
3
3
 
4
- module Naught::NullClassBuilder::Commands
5
- class Mimic < Naught::NullClassBuilder::Command
6
- attr_reader :class_to_mimic, :include_super
4
+ module Naught
5
+ class NullClassBuilder
6
+ module Commands
7
+ class Mimic < Naught::NullClassBuilder::Command
8
+ NULL_SINGLETON_CLASS = (class << Object.new; self; end)
9
+
10
+ attr_reader :class_to_mimic, :include_super, :singleton_class
11
+
12
+ def initialize(builder, class_to_mimic_or_options, options = {})
13
+ super(builder)
14
+
15
+ if class_to_mimic_or_options.is_a?(Hash)
16
+ options = class_to_mimic_or_options.merge(options)
17
+ instance = options.fetch(:example)
18
+ @singleton_class = (class << instance; self; end)
19
+ @class_to_mimic = instance.class
20
+ else
21
+ @singleton_class = NULL_SINGLETON_CLASS
22
+ @class_to_mimic = class_to_mimic_or_options
23
+ end
24
+ @include_super = options.fetch(:include_super) { true }
25
+
26
+ builder.base_class = root_class_of(@class_to_mimic)
27
+ class_to_mimic = @class_to_mimic
28
+ builder.inspect_proc = lambda { "<null:#{class_to_mimic}>" }
29
+ builder.interface_defined = true
30
+ end
7
31
 
8
- def initialize(builder, class_to_mimic, options = {})
9
- super(builder)
32
+ def call
33
+ defer do |subject|
34
+ methods_to_stub.each do |method_name|
35
+ builder.stub_method(subject, method_name)
36
+ end
37
+ end
38
+ end
10
39
 
11
- @class_to_mimic = class_to_mimic
12
- @include_super = options.fetch(:include_super) { true }
40
+ private
13
41
 
14
- builder.base_class = root_class_of(class_to_mimic)
15
- builder.inspect_proc = lambda { "<null:#{class_to_mimic}>" }
16
- builder.interface_defined = true
17
- end
42
+ def root_class_of(klass)
43
+ klass.ancestors.include?(Object) ? Object : Naught::BasicObject
44
+ end
18
45
 
19
- def call
20
- defer do |subject|
21
- methods_to_stub.each do |method_name|
22
- builder.stub_method(subject, method_name)
46
+ def methods_to_stub
47
+ methods_to_mimic =
48
+ class_to_mimic.instance_methods(include_super) |
49
+ singleton_class.instance_methods(false)
50
+ methods_to_mimic - Object.instance_methods
23
51
  end
24
52
  end
25
53
  end
26
-
27
- private
28
-
29
- def root_class_of(klass)
30
- klass.ancestors.include?(Object) ? Object : Naught::BasicObject
31
- end
32
-
33
- def methods_to_stub
34
- class_to_mimic.instance_methods(include_super) - Object.instance_methods
35
- end
36
54
  end
37
55
  end
@@ -12,9 +12,8 @@ module Naught
12
12
  def call
13
13
  defer do |subject|
14
14
  subject.module_exec(@output) do |output|
15
-
16
- define_method(:method_missing) do |method_name, *args, &block|
17
- pretty_args = args.collect(&:inspect).join(', ').gsub("\"", "'")
15
+ define_method(:method_missing) do |method_name, *args|
16
+ pretty_args = args.collect(&:inspect).join(', ').tr("\"", "'")
18
17
  output.puts "#{method_name}(#{pretty_args}) from #{parse_caller}"
19
18
  self
20
19
  end
@@ -1,42 +1,44 @@
1
1
  require 'naught/null_class_builder/command'
2
2
 
3
- module Naught::NullClassBuilder::Commands
4
- class PredicatesReturn < Naught::NullClassBuilder::Command
5
- def initialize(builder, return_value)
6
- super(builder)
7
- @predicate_return_value = return_value
8
- end
3
+ module Naught
4
+ class NullClassBuilder
5
+ module Commands
6
+ class PredicatesReturn < Naught::NullClassBuilder::Command
7
+ def initialize(builder, return_value)
8
+ super(builder)
9
+ @predicate_return_value = return_value
10
+ end
9
11
 
10
- def call
11
- defer do |subject|
12
- define_method_missing(subject)
13
- define_predicate_methods(subject)
14
- end
15
- end
12
+ def call
13
+ defer do |subject|
14
+ define_method_missing(subject)
15
+ define_predicate_methods(subject)
16
+ end
17
+ end
16
18
 
17
- private
19
+ private
18
20
 
19
- def define_method_missing(subject)
20
- subject.module_exec(@predicate_return_value) do |return_value|
21
- if subject.method_defined?(:method_missing)
22
- original_method_missing = instance_method(:method_missing)
23
- define_method(:method_missing) do |method_name, *args, &block|
24
- if method_name.to_s.end_with?('?')
25
- return_value
26
- else
27
- original_method_missing.bind(self).call(method_name, *args, &block)
21
+ def define_method_missing(subject)
22
+ subject.module_exec(@predicate_return_value) do |return_value|
23
+ next unless subject.method_defined?(:method_missing)
24
+ original_method_missing = instance_method(:method_missing)
25
+ define_method(:method_missing) do |method_name, *args, &block|
26
+ if method_name.to_s.end_with?('?')
27
+ return_value
28
+ else
29
+ original_method_missing.bind(self).call(method_name, *args, &block)
30
+ end
28
31
  end
29
32
  end
30
33
  end
31
- end
32
- end
33
34
 
34
- def define_predicate_methods(subject)
35
- subject.module_exec(@predicate_return_value) do |return_value|
36
- instance_methods.each do |method_name|
37
- if method_name.to_s.end_with?('?')
38
- define_method(method_name) do |*|
39
- return_value
35
+ def define_predicate_methods(subject)
36
+ subject.module_exec(@predicate_return_value) do |return_value|
37
+ instance_methods.each do |method_name|
38
+ next unless method_name.to_s.end_with?('?')
39
+ define_method(method_name) do |*|
40
+ return_value
41
+ end
40
42
  end
41
43
  end
42
44
  end
@@ -1,20 +1,24 @@
1
1
  require 'naught/null_class_builder/command'
2
2
 
3
- module Naught::NullClassBuilder::Commands
4
- class Singleton < Naught::NullClassBuilder::Command
5
- def call
6
- defer(:class => true) do |subject|
7
- require 'singleton'
8
- subject.module_eval do
9
- include ::Singleton
3
+ module Naught
4
+ class NullClassBuilder
5
+ module Commands
6
+ class Singleton < Naught::NullClassBuilder::Command
7
+ def call
8
+ defer(:class => true) do |subject|
9
+ require 'singleton'
10
+ subject.module_eval do
11
+ include ::Singleton
10
12
 
11
- def self.get(*)
12
- instance
13
- end
13
+ def self.get(*)
14
+ instance
15
+ end
14
16
 
15
- %w(dup clone).each do |method_name|
16
- define_method method_name do
17
- self
17
+ %w(dup clone).each do |method_name|
18
+ define_method method_name do
19
+ self
20
+ end
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -1,17 +1,21 @@
1
1
  require 'naught/null_class_builder/command'
2
2
 
3
- module Naught::NullClassBuilder::Commands
4
- class Traceable < Naught::NullClassBuilder::Command
5
- def call
6
- defer do |subject|
7
- subject.module_eval do
8
- attr_reader :__file__, :__line__
3
+ module Naught
4
+ class NullClassBuilder
5
+ module Commands
6
+ class Traceable < Naught::NullClassBuilder::Command
7
+ def call
8
+ defer do |subject|
9
+ subject.module_eval do
10
+ attr_reader :__file__, :__line__
9
11
 
10
- def initialize(options = {})
11
- range = (RUBY_VERSION.to_f == 1.9 && RUBY_PLATFORM != 'java') ? 4 : 3
12
- backtrace = options.fetch(:caller) { Kernel.caller(range) }
13
- @__file__, line, _ = backtrace[0].split(':')
14
- @__line__ = line.to_i
12
+ def initialize(options = {})
13
+ range = (RUBY_VERSION.to_f == 1.9 && RUBY_PLATFORM != 'java') ? 4 : 3
14
+ backtrace = options.fetch(:caller) { Kernel.caller(range) }
15
+ @__file__, line = backtrace[0].split(':')
16
+ @__line__ = line.to_i
17
+ end
18
+ end
15
19
  end
16
20
  end
17
21
  end
@@ -1,3 +1,3 @@
1
1
  module Naught
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -8,14 +8,14 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Naught::VERSION
9
9
  spec.authors = ['Avdi Grimm']
10
10
  spec.email = ['avdi@avdi.org']
11
- spec.description = %q{Naught is a toolkit for building Null Objects}
11
+ spec.description = 'Naught is a toolkit for building Null Objects'
12
12
  spec.summary = spec.description
13
13
  spec.homepage = 'https://github.com/avdi/naught'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
- spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(/^(test|spec|features)\//)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_development_dependency 'bundler', '~> 1.3'
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'null object with a custom base class' do
4
-
5
4
  subject(:null) { custom_base_null_class.new }
6
5
 
7
6
  let(:custom_base_null_class) do
@@ -10,11 +9,11 @@ describe 'null object with a custom base class' do
10
9
  end
11
10
  end
12
11
 
13
- it 'respond to base class methods' do
12
+ it 'responds to base class methods' do
14
13
  expect(null.methods).to be_an Array
15
14
  end
16
15
 
17
- it 'respond to unknown methods' do
16
+ it 'responds to unknown methods' do
18
17
  expect(null.foo).to be_nil
19
18
  end
20
19
 
@@ -31,5 +31,4 @@ describe 'basic null object' do
31
31
  it 'aliases .new to .get' do
32
32
  expect(null_class.get.class).to be(null_class)
33
33
  end
34
-
35
34
  end
@@ -3,9 +3,7 @@ require 'spec_helper'
3
3
  describe 'black hole null object' do
4
4
  subject(:null) { null_class.new }
5
5
  let(:null_class) do
6
- Naught.build do |b|
7
- b.black_hole
8
- end
6
+ Naught.build(&:black_hole)
9
7
  end
10
8
 
11
9
  it 'returns self from arbitray method calls' do
@@ -2,9 +2,7 @@ require 'spec_helper.rb'
2
2
 
3
3
  describe 'explicitly convertable null object' do
4
4
  let(:null_class) do
5
- Naught.build do |b|
6
- b.define_explicit_conversions
7
- end
5
+ Naught.build(&:define_explicit_conversions)
8
6
  end
9
7
  subject(:null) { null_class.new }
10
8
 
@@ -12,7 +12,7 @@ describe 'Maybe()' do
12
12
  expect(Maybe(null)).to be(null)
13
13
  end
14
14
 
15
- specify 'given anything in null_equivalents, return a null object' do
15
+ specify 'given anything in null_equivalents, returns a null object' do
16
16
  expect(Maybe('').class).to be(ConvertableNull)
17
17
  end
18
18
 
@@ -23,7 +23,7 @@ describe 'Maybe()' do
23
23
  end
24
24
 
25
25
  it 'generates null objects with useful trace info' do
26
- null, line = Maybe(), __LINE__
26
+ null, line = Maybe(), __LINE__ # rubocop:disable ParallelAssignment
27
27
  expect(null.__file__).to eq(__FILE__)
28
28
  expect(null.__line__).to eq(line)
29
29
  end
@@ -16,7 +16,7 @@ describe 'Null()' do
16
16
  expect(Null(null)).to be(null)
17
17
  end
18
18
 
19
- specify 'given anything in null_equivalents, return a null object' do
19
+ specify 'given anything in null_equivalents, returns a null object' do
20
20
  expect(Null('').class).to be(ConvertableNull)
21
21
  end
22
22
 
@@ -26,9 +26,8 @@ describe 'Null()' do
26
26
  end
27
27
 
28
28
  it 'generates null objects with useful trace info' do
29
- null, line = Null(), __LINE__
29
+ null, line = Null(), __LINE__ # rubocop:disable ParallelAssignment
30
30
  expect(null.__file__).to eq(__FILE__)
31
31
  expect(null.__line__).to eq(line)
32
32
  end
33
-
34
33
  end
@@ -3,9 +3,7 @@ require 'spec_helper'
3
3
  describe 'implicitly convertable null object' do
4
4
  subject(:null) { null_class.new }
5
5
  let(:null_class) do
6
- Naught.build do |b|
7
- b.define_implicit_conversions
8
- end
6
+ Naught.build(&:define_implicit_conversions)
9
7
  end
10
8
  it 'implicitly splats the same way an empty array does' do
11
9
  a, b = null
@@ -18,8 +16,13 @@ describe 'implicitly convertable null object' do
18
16
  it 'implicitly converts to an empty array' do
19
17
  expect(null.to_ary).to eq([])
20
18
  end
19
+ it 'implicitly converts to an empty hash' do
20
+ expect(null.to_hash).to eq({})
21
+ end
22
+ it 'implicitly converts to zero' do
23
+ expect(null.to_int).to eq(0)
24
+ end
21
25
  it 'implicitly converts to an empty string' do
22
26
  expect(null.to_str).to eq('')
23
27
  end
24
-
25
28
  end
@@ -3,31 +3,20 @@ require 'logger'
3
3
 
4
4
  describe 'null object mimicking a class' do
5
5
  class User
6
- def login
7
- 'bob'
8
- end
6
+ attr_reader :login
9
7
  end
10
8
 
11
9
  module Authorizable
12
- def authorized_for?(object)
13
- true
14
- end
10
+ def authorized_for?(_); end
15
11
  end
16
12
 
17
13
  class LibraryPatron < User
18
14
  include Authorizable
15
+ attr_reader :name
19
16
 
20
- def member?
21
- true
22
- end
23
-
24
- def name
25
- 'Bob'
26
- end
17
+ def member?; end
27
18
 
28
- def notify_of_overdue_books(titles)
29
- puts 'Notifying...'
30
- end
19
+ def notify_of_overdue_books(_); end
31
20
  end
32
21
 
33
22
  subject(:null) { mimic_class.new }
@@ -78,6 +67,24 @@ describe 'null object mimicking a class' do
78
67
  expect(null).to_not respond_to(:login)
79
68
  end
80
69
  end
70
+
71
+ describe 'with an instance as example' do
72
+ let(:mimic_class) do
73
+ milton = LibraryPatron.new
74
+ def milton.stapler; end
75
+ Naught.build do |b|
76
+ b.mimic :example => milton
77
+ end
78
+ end
79
+
80
+ it 'responds to method defined only on the example instance' do
81
+ expect(null).to respond_to(:stapler)
82
+ end
83
+
84
+ it 'responds to method defined on the class of the instance' do
85
+ expect(null).to respond_to(:member?)
86
+ end
87
+ end
81
88
  end
82
89
 
83
90
  describe 'using mimic with black_hole' do
@@ -89,7 +96,7 @@ describe 'using mimic with black_hole' do
89
96
  end
90
97
  end
91
98
 
92
- def self.it_behaves_like_a_black_hole_mimic
99
+ shared_examples_for 'a black hole mimic' do
93
100
  it 'returns self from mimicked methods' do
94
101
  expect(null.info).to equal(null)
95
102
  expect(null.error).to equal(null)
@@ -101,7 +108,7 @@ describe 'using mimic with black_hole' do
101
108
  end
102
109
  end
103
110
 
104
- it_behaves_like_a_black_hole_mimic
111
+ it_should_behave_like 'a black hole mimic'
105
112
 
106
113
  describe '(reverse order)' do
107
114
  let(:mimic_class) do
@@ -111,7 +118,6 @@ describe 'using mimic with black_hole' do
111
118
  end
112
119
  end
113
120
 
114
- it_behaves_like_a_black_hole_mimic
121
+ it_should_behave_like 'a black hole mimic'
115
122
  end
116
-
117
123
  end
@@ -2,13 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe 'null object impersonating another type' do
4
4
  class Point
5
- def x
6
- 23
7
- end
8
-
9
- def y
10
- 42
11
- end
5
+ attr_reader :x, :y
12
6
  end
13
7
 
14
8
  subject(:null) { impersonation_class.new }
@@ -37,14 +31,12 @@ describe 'traceable null object' do
37
31
  null_object_and_line.first
38
32
  end
39
33
  let(:null_object_and_line) do
40
- obj, line = trace_null_class.new, __LINE__
34
+ obj, line = trace_null_class.new, __LINE__ # rubocop:disable ParallelAssignment
41
35
  [obj, line]
42
36
  end
43
37
  let(:instantiation_line) { null_object_and_line.last }
44
38
  let(:trace_null_class) do
45
- Naught.build do |b|
46
- b.traceable
47
- end
39
+ Naught.build(&:traceable)
48
40
  end
49
41
 
50
42
  it 'remembers the file it was instantiated from' do
@@ -60,7 +52,7 @@ describe 'traceable null object' do
60
52
  end
61
53
 
62
54
  it 'can accept custom backtrace info' do
63
- obj, line = make_null, __LINE__
55
+ obj, line = make_null, __LINE__ # rubocop:disable ParallelAssignment
64
56
  expect(obj.__line__).to eq(line)
65
57
  end
66
58
  end
@@ -91,11 +83,11 @@ end
91
83
  TestNull = Naught.build
92
84
 
93
85
  describe 'a named null object class' do
94
- it 'has named ancestor modules', :pending => rubinius? do
86
+ it 'has named ancestor modules' do
95
87
  expect(TestNull.ancestors[0..2].collect(&:name)).to eq([
96
- 'TestNull',
97
- 'TestNull::Customizations',
98
- 'TestNull::GeneratedMethods'
99
- ])
88
+ 'TestNull',
89
+ 'TestNull::Customizations',
90
+ 'TestNull::GeneratedMethods',
91
+ ])
100
92
  end
101
93
  end
@@ -9,11 +9,11 @@ describe 'a null object with predicates_return(false)' do
9
9
  end
10
10
 
11
11
  it 'responds to predicate-style methods with false' do
12
- expect(null.too_much_coffee?).to eq(false)
12
+ expect(null.too_much_coffee?).to be(false)
13
13
  end
14
14
 
15
15
  it 'responds to other methods with nil' do
16
- expect(null.foobar).to eq(nil)
16
+ expect(null.foobar).to be(nil)
17
17
  end
18
18
 
19
19
  describe '(black hole)' do
@@ -25,7 +25,7 @@ describe 'a null object with predicates_return(false)' do
25
25
  end
26
26
 
27
27
  it 'responds to predicate-style methods with false' do
28
- expect(null.too_much_coffee?).to eq(false)
28
+ expect(null.too_much_coffee?).to be(false)
29
29
  end
30
30
 
31
31
  it 'responds to other methods with self' do
@@ -42,7 +42,7 @@ describe 'a null object with predicates_return(false)' do
42
42
  end
43
43
 
44
44
  it 'responds to predicate-style methods with false' do
45
- expect(null.too_much_coffee?).to eq(false)
45
+ expect(null.too_much_coffee?).to be(false)
46
46
  end
47
47
 
48
48
  it 'responds to other methods with self' do
@@ -51,13 +51,8 @@ describe 'a null object with predicates_return(false)' do
51
51
  end
52
52
 
53
53
  class Coffee
54
- def black?
55
- true
56
- end
57
-
58
- def origin
59
- 'Ethiopia'
60
- end
54
+ attr_reader :origin
55
+ def black?; end
61
56
  end
62
57
 
63
58
  describe '(mimic)' do
@@ -69,7 +64,7 @@ describe 'a null object with predicates_return(false)' do
69
64
  end
70
65
 
71
66
  it 'responds to predicate-style methods with false' do
72
- expect(null.black?).to eq(false)
67
+ expect(null.black?).to be(false)
73
68
  end
74
69
 
75
70
  it 'responds to other methods with nil' do
@@ -2,13 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe 'singleton null object' do
4
4
  subject(:null_class) do
5
- Naught.build do |b|
6
- b.singleton
7
- end
5
+ Naught.build(&:singleton)
8
6
  end
9
7
 
10
8
  it 'does not respond to .new' do
11
- expect { null_class.new }.to raise_error
9
+ expect { null_class.new }.to raise_error(NoMethodError)
12
10
  end
13
11
 
14
12
  it 'has only one instance' do
@@ -1,12 +1,14 @@
1
1
  GEM_ROOT = File.expand_path('../../', __FILE__)
2
2
  $LOAD_PATH.unshift File.join(GEM_ROOT, 'lib')
3
3
 
4
- if ENV['TRAVIS']
5
- require 'coveralls'
6
- Coveralls.wear!
7
- else
8
- require 'simplecov'
9
- SimpleCov.start
4
+ require 'simplecov'
5
+ require 'coveralls'
6
+
7
+ SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
8
+
9
+ SimpleCov.start do
10
+ add_filter '/spec/'
11
+ minimum_coverage(97.7)
10
12
  end
11
13
 
12
14
  require 'naught'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: naught
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Avdi Grimm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-26 00:00:00.000000000 Z
11
+ date: 2015-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
98
  version: '0'
99
99
  requirements: []
100
100
  rubyforge_project:
101
- rubygems_version: 2.2.1
101
+ rubygems_version: 2.4.5.1
102
102
  signing_key:
103
103
  specification_version: 4
104
104
  summary: Naught is a toolkit for building Null Objects