Class: Naught::NullClassBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/naught/null_class_builder.rb,
lib/naught/null_class_builder/command.rb,
lib/naught/null_class_builder/commands/mimic.rb,
lib/naught/null_class_builder/commands/pebble.rb,
lib/naught/null_class_builder/commands/callstack.rb,
lib/naught/null_class_builder/commands/singleton.rb,
lib/naught/null_class_builder/commands/traceable.rb,
lib/naught/null_class_builder/commands/impersonate.rb,
lib/naught/null_class_builder/commands/null_safe_proxy.rb,
lib/naught/null_class_builder/commands/predicates_return.rb,
lib/naught/null_class_builder/commands/define_explicit_conversions.rb,
lib/naught/null_class_builder/commands/define_implicit_conversions.rb

Overview

Builds customized null object classes via a small DSL

Defined Under Namespace

Modules: Commands Classes: Command

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNullClassBuilder

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Create a new builder with default configuration



44
45
46
47
48
49
50
# File 'lib/naught/null_class_builder.rb', line 44

def initialize
  @interface_defined = false
  @base_class = Naught::BasicObject
  @inspect_proc = -> { "<null>" }
  @stub_strategy = StubStrategy::ReturnNil
  define_basic_methods
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Dispatch builder DSL calls to command classes



158
159
160
161
# File 'lib/naught/null_class_builder.rb', line 158

def method_missing(method_name, *args, &)
  command_class = lookup_command(method_name)
  command_class ? command_class.new(self, *args, &).call : super
end

Instance Attribute Details

#base_classClass

The base class for generated null objects

Examples:

builder.base_class #=> Naught::BasicObject

Returns:

  • (Class)

    base class for generated null objects



19
20
21
# File 'lib/naught/null_class_builder.rb', line 19

def base_class
  @base_class
end

#inspect_procProc

The inspect implementation for generated null objects

Examples:

builder.inspect_proc.call #=> "<null>"

Returns:

  • (Proc)

    inspect implementation for generated null objects



26
27
28
# File 'lib/naught/null_class_builder.rb', line 26

def inspect_proc
  @inspect_proc
end

#interface_definedBoolean Also known as: interface_defined?

Whether a method-missing interface has been defined

Examples:

builder.interface_defined #=> false

Returns:

  • (Boolean)

    whether a method-missing interface has been defined



33
34
35
# File 'lib/naught/null_class_builder.rb', line 33

def interface_defined
  @interface_defined
end

Instance Method Details

#black_holevoid

This method returns an undefined value.

Configure method stubs to return self (black hole behavior)

Examples:

builder.black_hole

See Also:



101
102
103
104
105
106
107
108
# File 'lib/naught/null_class_builder.rb', line 101

def black_hole
  @stub_strategy = StubStrategy::ReturnSelf
  # Prepend marshal methods to avoid infinite recursion with method_missing
  defer_prepend_module do
    define_method(:marshal_dump) { nil }
    define_method(:marshal_load) { |*| nil }
  end
end

#customization_moduleModule

Returns the module that holds customization methods

Examples:

builder.customization_module #=> #<Module:0x...>

Returns:

  • (Module)

    module that holds customization methods



67
# File 'lib/naught/null_class_builder.rb', line 67

def customization_module = @customization_module ||= Module.new

#customize {|builder| ... } ⇒ void

This method returns an undefined value.

Apply a customization block to this builder

Examples:

builder.customize { |b| b.black_hole }

Yield Parameters:



58
59
60
# File 'lib/naught/null_class_builder.rb', line 58

def customize(&)
  customization_module.module_exec(self, &) if block_given?
end

#defer(options = {}) {|subject| ... } ⇒ void

This method returns an undefined value.

Queue a deferred operation to be applied during class generation

Examples:

builder.defer { |subject| subject.define_method(:foo) { "bar" } }

Parameters:

  • options (Hash) (defaults to: {})

    :class for class-level, :prepend to add at front

Yield Parameters:

  • subject (Module, Class)

    target of the operation



130
131
132
133
# File 'lib/naught/null_class_builder.rb', line 130

def defer(options = {}, &operation)
  target = options[:class] ? class_operations : operations
  options[:prepend] ? target.unshift(operation) : target.push(operation)
end

#defer_prepend_modulevoid

This method returns an undefined value.

Prepend a module generated from the given block

Examples:

builder.defer_prepend_module { define_method(:foo) { "bar" } }


140
141
142
# File 'lib/naught/null_class_builder.rb', line 140

def defer_prepend_module(&)
  prepend_modules << Module.new(&)
end

#generate_classClass

Generate the null object class based on queued operations

Examples:

NullClass = builder.generate_class

Returns:

  • (Class)

    generated null class



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/naught/null_class_builder.rb', line 81

def generate_class
  respond_to_any_message unless interface_defined?

  generation_mod = Module.new
  apply_operations(operations, generation_mod)

  null_class = build_null_class(generation_mod)
  apply_operations(class_operations, null_class)

  null_class
end

#null_equivalentsArray<Object>

Returns the list of values treated as null-equivalent

Examples:

builder.null_equivalents #=> [nil]

Returns:

  • (Array<Object>)

    values treated as null-equivalent



74
# File 'lib/naught/null_class_builder.rb', line 74

def null_equivalents = @null_equivalents ||= [nil]

#respond_to_any_messagevoid

This method returns an undefined value.

Make null objects respond to any message

Examples:

builder.respond_to_any_message


115
116
117
118
119
120
121
# File 'lib/naught/null_class_builder.rb', line 115

def respond_to_any_message
  defer(prepend: true) do |subject|
    subject.define_method(:respond_to?) { |*, **| true }
    stub_method(subject, :method_missing)
  end
  @interface_defined = true
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if builder responds to a DSL command

Parameters:

  • method_name (Symbol)

    method name to check

  • include_private (Boolean) (defaults to: false)

    whether to include private methods

Returns:

  • (Boolean)

    true if method_name maps to a known command



169
170
171
172
173
# File 'lib/naught/null_class_builder.rb', line 169

def respond_to_missing?(method_name, include_private = false)
  !lookup_command(method_name).nil? || super
rescue NameError
  super
end

#stub_method(subject, name) ⇒ void

This method returns an undefined value.

Stub a method using the current stub strategy

Examples:

builder.stub_method(some_module, :foo)

Parameters:

  • subject (Module, Class)

    target to define method on

  • name (Symbol)

    method name to stub



151
152
153
# File 'lib/naught/null_class_builder.rb', line 151

def stub_method(subject, name)
  @stub_strategy.apply(subject, name)
end