Module: Dux

Extended by:
Attempt, Blankness, InspectID
Defined in:
lib/dux.rb,
lib/dux/enum.rb,
lib/dux/attempt.rb,
lib/dux/duckify.rb,
lib/dux/version.rb,
lib/dux/blankness.rb,
lib/dux/predicate.rb,
lib/dux/comparable.rb,
lib/dux/inspect_id.rb,
lib/dux/null_object.rb,
lib/dux/monkey_patch.rb,
lib/dux/flock_methods.rb,
lib/dux/hacks_like_a_duck.rb,
lib/dux/indifferent_string.rb

Overview

Swiss-army duck type matching

Defined Under Namespace

Modules: Attempt, Blankness, Duckify, FlockMethods, HacksLikeADuck, InspectID Classes: Comparable, Enum, IndifferentString, NullObject

Constant Summary collapse

VERSION =

Gem version.

"0.8.0"
FLOCK_TYPES =

Methods for generating "interface" checks against an array of symbols

Dux.enum :all, :any, :none

DSL collapse

Predicates collapse

Core extensions collapse

Class Method Summary collapse

Class Method Details

.[](symbol, include_all: false) ⇒ Proc Also known as: predicate, dux

Create a predicate that checks if the provided object responds to the symbol.

Parameters:

  • symbol (Symbol)
  • include_all (Boolean) (defaults to: false)

Returns:

  • (Proc)


14
15
16
# File 'lib/dux/predicate.rb', line 14

def [](symbol, include_all: false)
  ->(obj) { obj.respond_to? symbol, include_all }
end

.add_flock_methods!void

This method returns an undefined value.

Enhance Array with Dux::FlockMethods#duckify



8
9
10
11
12
# File 'lib/dux/monkey_patch.rb', line 8

def add_flock_methods!
  Array.__send__ :prepend, Dux::FlockMethods

  return nil
end

.all(*methods, include_all: false) ⇒ Proc

Creates a lambda that describes a restrictive interface, wherein the provided object must respond_to? all of the methods.

Parameters:

  • methods (<Symbol, String>)
  • include_all (Boolean) (defaults to: false)

Returns:

  • (Proc)


82
83
84
85
86
# File 'lib/dux/predicate.rb', line 82

def all(*methods, include_all: false)
  ducks = flockify methods, include_all: include_all

  ->(obj) { ducks.all? { |duck| duck.call obj } }
end

.any(*methods, include_all: false) ⇒ Proc

Creates a lambda that describes a permissive interface, wherein the provided object must respond_to? at least one of the methods.

Parameters:

  • methods (<Symbol>)
  • include_all (Boolean) (defaults to: false)

Returns:

  • (Proc)


95
96
97
98
99
# File 'lib/dux/predicate.rb', line 95

def any(*methods, include_all: false)
  ducks = flockify methods, include_all: include_all

  ->(obj) { ducks.any? { |duck| duck.call obj } }
end

.array_shorthand!void

This method returns an undefined value.

Experimental feature to add unary ~ to Arrays for quick usage in case statements.



62
63
64
65
66
67
68
# File 'lib/dux/monkey_patch.rb', line 62

def array_shorthand!
  add_flock_methods!

  Array.__send__ :prepend, Dux::HacksLikeADuck

  nil
end

.attempt(receiver, method, *args, &block) ⇒ Object? Originally defined in module Attempt

Parameters:

  • receiver (Object)
  • method (Symbol)
  • args (<Object>)

Returns:

  • (Object)
  • (nil)

.blankish?(value) ⇒ Boolean Originally defined in module Blankness

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 a provided object is semantically empty.

Parameters:

  • value (Object)

Returns:

  • (Boolean)

.comparable(*attributes, **options) ⇒ Dux::Comparable

Create a comparable module with the provided options.

Returns:

See Also:

  • [Dux[Dux::Comparable[Dux::Comparable#initialize]


235
236
237
# File 'lib/dux/comparable.rb', line 235

def comparable(*attributes, **options)
  Dux::Comparable.new(*attributes, **options)
end

.enum(*values, **options) ⇒ Dux::Enum

Create an enum with the provided options.

Returns:

See Also:



275
276
277
# File 'lib/dux/enum.rb', line 275

def enum(*values, **options)
  Dux::Enum.new(*values, **options)
end

.extend_all!(experimental: false) ⇒ void

This method returns an undefined value.

Load all Dux core extensions.

Parameters:

  • experimental (Boolean) (defaults to: false)

    whether to load experimental shorthand methods



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/dux/monkey_patch.rb', line 18

def extend_all!(experimental: false)
  add_flock_methods!

  extend_strings_and_symbols!

  return unless experimental

  array_shorthand!
  string_shorthand!
  symbol_shorthand!
end

.extend_strings!void

This method returns an undefined value.

Enhance String with Duckify



33
34
35
36
37
# File 'lib/dux/monkey_patch.rb', line 33

def extend_strings!
  String.__send__ :prepend, Dux::Duckify

  return nil
end

.extend_strings_and_symbols!void

This method returns an undefined value.

Enhance String and Symbol classes with Dux::Duckify#duckify



51
52
53
54
55
56
# File 'lib/dux/monkey_patch.rb', line 51

def extend_strings_and_symbols!
  extend_strings!
  extend_symbols!

  return nil
end

.extend_symbols!void

This method returns an undefined value.

Enhance Symbol with Duckify



42
43
44
45
46
# File 'lib/dux/monkey_patch.rb', line 42

def extend_symbols!
  Symbol.__send__ :prepend, Dux::Duckify

  return nil
end

.extends(parent) ⇒ Proc

Create a predicate that checks if the provided Class or Module extends a given parent module.

Parameters:

  • parent (Module)

Returns:

  • (Proc)

Raises:

  • (TypeError)

    requires a module to check extension



47
48
49
50
51
# File 'lib/dux/predicate.rb', line 47

def extends(parent)
  raise TypeError, "Must be a module to check if something extends it" unless parent.kind_of?(Module)

  ->(klass) { Dux.inheritable?(klass) && klass.singleton_class < parent }
end

.flock(type, *methods, include_all: false) ⇒ <Proc>

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.

Parameters:

  • type (:all, :any, :none)
  • methods (<Symbol, String>)
  • include_all (Boolean) (defaults to: false)

Returns:

  • (<Proc>)

Raises:

  • (ArgumentError)

    on invalid type



120
121
122
123
124
# File 'lib/dux/predicate.rb', line 120

def flock(type, *methods, include_all: false)
  type = FLOCK_TYPES.fetch(type) { raise ArgumentError, "Invalid flock type: #{type}" }

  __send__ type, methods, include_all: include_all
end

.flockify(methods, include_all: false) ⇒ <Proc> (protected)

Parameters:

  • methods (<Symbol>)
  • include_all (Boolean) (defaults to: false)

Returns:

  • (<Proc>)


131
132
133
134
135
# File 'lib/dux/predicate.rb', line 131

def flockify(methods, include_all: false)
  methods.flatten.map do |sym|
    dux sym, include_all: include_all
  end
end

.inheritable?(klass_or_module) ⇒ 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 the provided thing is a class or a module.

Parameters:

  • klass_or_module (Class, Module)

Returns:

  • (Boolean)


71
72
73
# File 'lib/dux/predicate.rb', line 71

def inheritable?(klass_or_module)
  klass_or_module.kind_of?(Class) || klass_or_module.kind_of?(Module)
end

.inherits(parent, include_self: false) ⇒ Proc Also known as: includes, prepends

Create a predicate that checks if the provided Class or Module inherits from a given class or module.

Parameters:

  • parent (Class, Module)
  • include_self (Boolean) (defaults to: false)

Returns:

  • (Proc)

Raises:

  • (TypeError)

    requires a class or module to serve as parent



28
29
30
31
32
33
34
35
36
# File 'lib/dux/predicate.rb', line 28

def inherits(parent, include_self: false)
  raise TypeError, "Must be a class or module to check inheritance" unless inheritable?(parent)

  if include_self
    ->(klass) { Dux.inheritable?(klass) && klass <= parent }
  else
    ->(klass) { Dux.inheritable?(klass) && klass < parent }
  end
end

.inspect_id(object = self) ⇒ String Originally defined in module InspectID

Note:

This is currently limited to the implementation used in MRI. Rubinius and JRuby have their own implementations that are not currently served by this.

Calculates the id shown in the default version of #inspect methods.

Parameters:

  • object (Object) (defaults to: self)

Returns:

  • (String)

.none(*methods, include_all: false) ⇒ Proc

Creates a lambda that describes a restrictive interface, wherein the provided object must respond_to? none of the methods.

Parameters:

  • methods (<Symbol>)
  • include_all (Boolean) (defaults to: false)

Returns:

  • (Proc)


108
109
110
111
112
# File 'lib/dux/predicate.rb', line 108

def none(*methods, include_all: false)
  ducks = flockify methods, include_all: include_all

  ->(obj) { ducks.none? { |duck| duck.call obj } }
end

.null_object(name = nil, **options) ⇒ Dux::NullObject Also known as: null

Create a null object with the provided options.



69
70
71
# File 'lib/dux/null_object.rb', line 69

def null_object(name = nil, **options)
  Dux::NullObject.new(name, **options)
end

.presentish?(value) ⇒ Boolean Originally defined in module Blankness

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.

Boolean complement of #blankish?

Parameters:

  • value (Object)

Returns:

  • (Boolean)

.string_shorthand!void

This method returns an undefined value.

Experimental feature to add unary ~ to Strings for quick usage in case statements.



74
75
76
77
78
79
80
# File 'lib/dux/monkey_patch.rb', line 74

def string_shorthand!
  extend_strings!

  String.__send__ :prepend, Dux::HacksLikeADuck

  nil
end

.symbol_shorthand!void

This method returns an undefined value.

Experimental feature to add unary ~ to Symbols for quick usage in case statements.



86
87
88
89
90
91
92
# File 'lib/dux/monkey_patch.rb', line 86

def symbol_shorthand!
  extend_symbols!

  Symbol.__send__ :prepend, Dux::HacksLikeADuck

  return nil
end

.yard(pattern) ⇒ Proc

Note:

Some limitations apply because of the underlying gem, e.g. symbol / string literals are not matched and will raise an error

Create a predicate that checks against a specific YARD type description.

Parameters:

  • pattern (String)

Returns:

  • (Proc)

Raises:

  • (SyntaxError)

    when YardTypes fails to parse.

See Also:



61
62
63
64
65
# File 'lib/dux/predicate.rb', line 61

def yard(pattern)
  type = YardTypes.parse pattern

  ->(value) { !type.check(value).nil? }
end