naught 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/htmldiff ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'htmldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'htmldiff')
data/bin/ldiff ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'ldiff')
data/bin/pry ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'pry' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('pry', 'pry')
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/bin/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
data/bin/thor ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'thor' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('thor', 'thor')
data/lib/naught.rb ADDED
@@ -0,0 +1,16 @@
1
+ require "naught/version"
2
+ require 'naught/null_class_builder'
3
+ require 'naught/null_class_builder/commands/define_explicit_conversions'
4
+
5
+ module Naught
6
+ def self.build(&customization_block)
7
+ builder = NullClassBuilder.new
8
+ builder.customize(&customization_block)
9
+ unless builder.interface_defined?
10
+ builder.respond_to_any_message
11
+ end
12
+ builder.generate_class
13
+ end
14
+ module NullObjectTag
15
+ end
16
+ end
@@ -0,0 +1,274 @@
1
+ module Naught
2
+ class NullClassBuilder
3
+ # make sure this module exists
4
+ module Commands
5
+ end
6
+
7
+ def initialize
8
+ @interface_defined = false
9
+ @base_class = BasicObject
10
+ @inspect_proc = ->{ "<null>" }
11
+ @stub_strategy = :stub_method_returning_nil
12
+ define_basic_methods
13
+ end
14
+
15
+ def interface_defined?
16
+ @interface_defined
17
+ end
18
+
19
+ def customize(&customization_block)
20
+ return unless customization_block
21
+ customization_module.module_exec(self, &customization_block)
22
+ end
23
+
24
+ def customization_module
25
+ @customization_module ||= Module.new
26
+ end
27
+
28
+ def null_equivalents
29
+ @null_equivalents ||= [nil]
30
+ end
31
+
32
+ def generate_conversions_module(null_class)
33
+ null_equivs = null_equivalents # get a local binding
34
+ @conversions_module ||= Module.new do
35
+ define_method(:Null) do |object=:nothing_passed|
36
+ case object
37
+ when NullObjectTag then object
38
+ when :nothing_passed, *null_equivs
39
+ null_class.get(caller: caller(1))
40
+ else raise ArgumentError, "#{object.inspect} is not null!"
41
+ end
42
+ end
43
+
44
+ define_method(:Maybe) do |object=nil, &block|
45
+ object = block ? block.call : object
46
+ case object
47
+ when NullObjectTag then object
48
+ when *null_equivs
49
+ null_class.get(caller: caller(1))
50
+ else
51
+ object
52
+ end
53
+ end
54
+
55
+ define_method(:Just) do |object=nil, &block|
56
+ object = block ? block.call : object
57
+ case object
58
+ when NullObjectTag, *null_equivs
59
+ raise ArgumentError, "Null value: #{object.inspect}"
60
+ else
61
+ object
62
+ end
63
+ end
64
+
65
+ define_method(:Actual) do |object=nil, &block|
66
+ object = block ? block.call : object
67
+ case object
68
+ when NullObjectTag then nil
69
+ else
70
+ object
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ def generate_class
77
+ generation_mod = Module.new
78
+ customization_mod = customization_module # get a local binding
79
+ builder = self
80
+ @operations.each do |operation|
81
+ operation.call(generation_mod)
82
+ end
83
+ null_class = Class.new(@base_class) do
84
+ const_set :GeneratedMethods, generation_mod
85
+ const_set :Customizations, customization_mod
86
+ const_set :Conversions, builder.generate_conversions_module(self)
87
+
88
+ include NullObjectTag
89
+ include generation_mod
90
+ include customization_mod
91
+ end
92
+ class_operations.each do |operation|
93
+ operation.call(null_class)
94
+ end
95
+ null_class
96
+ end
97
+
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
+ def respond_to_missing?(method_name, *args)
109
+ command_name = command_name_for_method(method_name)
110
+ Commands.const_defined?(command_name) || super
111
+ end
112
+
113
+ ############################################################################
114
+ # Builder API
115
+ #
116
+ # See also the contents of lib/naught/null_class_builder/commands
117
+ ############################################################################
118
+ def define_implicit_conversions
119
+ defer do |subject|
120
+ subject.module_eval do
121
+ def to_ary; []; end
122
+ def to_str; ''; end
123
+ end
124
+ end
125
+ end
126
+
127
+ def mimic(class_to_mimic, options={})
128
+ include_super = options.fetch(:include_super) { true }
129
+ @base_class = root_class_of(class_to_mimic)
130
+ @inspect_proc = -> { "<null:#{class_to_mimic}>" }
131
+ defer do |subject|
132
+ subject.module_eval do
133
+ methods = class_to_mimic.instance_methods(include_super) -
134
+ Object.instance_methods
135
+ methods.each do |method_name|
136
+ define_method(method_name) {|*| nil}
137
+ end
138
+ end
139
+ end
140
+ @interface_defined = true
141
+ end
142
+
143
+ def black_hole
144
+ @stub_strategy = :stub_method_returning_self
145
+ end
146
+
147
+ def respond_to_any_message
148
+ defer do |subject|
149
+ subject.module_eval do
150
+ def respond_to?(*)
151
+ true
152
+ end
153
+ end
154
+ stub_method(subject, :method_missing)
155
+ end
156
+ @interface_defined = true
157
+ end
158
+
159
+ def mimic(class_to_mimic, options={})
160
+ include_super = options.fetch(:include_super) { true }
161
+ @base_class = root_class_of(class_to_mimic)
162
+ @inspect_proc = -> { "<null:#{class_to_mimic}>" }
163
+ defer do |subject|
164
+ methods = class_to_mimic.instance_methods(include_super) -
165
+ Object.instance_methods
166
+ methods.each do |method_name|
167
+ stub_method(subject, method_name)
168
+ end
169
+ end
170
+ @interface_defined = true
171
+ end
172
+
173
+ def impersonate(class_to_impersonate, options={})
174
+ mimic(class_to_impersonate, options)
175
+ @base_class = class_to_impersonate
176
+ end
177
+
178
+ def traceable
179
+ defer do |subject|
180
+ subject.module_eval do
181
+ attr_reader :__file__, :__line__
182
+
183
+ def initialize(options={})
184
+ backtrace = options.fetch(:caller) { Kernel.caller(4) }
185
+ @__file__, line, _ = backtrace[0].split(':')
186
+ @__line__ = line.to_i
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ def defer(options={}, &deferred_operation)
193
+ if options[:class]
194
+ class_operations << deferred_operation
195
+ else
196
+ operations << deferred_operation
197
+ end
198
+ end
199
+
200
+ def singleton
201
+ defer(class: true) do |subject|
202
+ require 'singleton'
203
+ subject.module_eval do
204
+ include Singleton
205
+ def self.get(*)
206
+ instance
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ def define_basic_methods
213
+ defer do |subject|
214
+ # make local variable to be accessible to Class.new block
215
+ inspect_proc = @inspect_proc
216
+ subject.module_eval do
217
+ define_method(:inspect, &inspect_proc)
218
+ def initialize(*)
219
+ end
220
+ end
221
+ end
222
+ defer(class: true) do |subject|
223
+ subject.module_eval do
224
+ class << self
225
+ alias get new
226
+ end
227
+ klass = self
228
+ define_method(:class) { klass }
229
+ end
230
+ end
231
+ end
232
+
233
+ private
234
+
235
+ def class_operations
236
+ @class_operations ||= []
237
+ end
238
+
239
+ def operations
240
+ @operations ||= []
241
+ end
242
+
243
+ def stub_method(subject, name)
244
+ send(@stub_strategy, subject, name)
245
+ end
246
+
247
+ def stub_method_returning_nil(subject, name)
248
+ subject.module_eval do
249
+ define_method(name) {|*| nil }
250
+ end
251
+ end
252
+
253
+ def stub_method_returning_self(subject, name)
254
+ subject.module_eval do
255
+ define_method(name) {|*| self }
256
+ end
257
+ end
258
+
259
+ def command_name_for_method(method_name)
260
+ command_name = method_name.to_s.
261
+ gsub(/_(\w)/){ $1.upcase }.
262
+ gsub(/\A(\w)/){ $1.upcase }
263
+ end
264
+
265
+ def root_class_of(klass)
266
+ if klass.ancestors.include?(Object)
267
+ Object
268
+ else
269
+ BasicObject
270
+ end
271
+ end
272
+
273
+ end
274
+ end
@@ -0,0 +1,30 @@
1
+
2
+ module Naught
3
+ class NullClassBuilder
4
+ module Commands
5
+ class DefineExplicitConversions
6
+ def initialize(builder)
7
+ @builder = builder
8
+ end
9
+
10
+ def call
11
+ defer do |subject|
12
+ subject.module_eval do
13
+ def to_s; ""; end
14
+ def to_i; 0; end
15
+ def to_f; 0.0; end
16
+ def to_c; 0.to_c; end
17
+ def to_r; 0.to_r; end
18
+ def to_a; []; end
19
+ def to_h; {}; end
20
+ end
21
+ end
22
+ end
23
+
24
+ def defer(&block)
25
+ @builder.defer(&block)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module Naught
2
+ VERSION = "0.0.1"
3
+ end
data/naught.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'naught/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "naught"
8
+ spec.version = Naught::VERSION
9
+ spec.authors = ["Avdi Grimm"]
10
+ spec.email = ["avdi@avdi.org"]
11
+ spec.description = %q{Naught is a toolkit for building Null Objects}
12
+ spec.summary = %q{Naught is a toolkit for building Null Objects}
13
+ spec.homepage = "https://github.com/avdi/naught"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "guard"
25
+ spec.add_development_dependency "guard-rspec"
26
+ end