Module: NRSER::Types::Factory

Included in:
NRSER::Types
Defined in:
lib/nrser/types/factory.rb

Instance Method Summary collapse

Instance Method Details

#def_factory(name, maybe: true, aliases: [], &body) ⇒ NRSER::Types::Type

Define a type factory.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/nrser/types/factory.rb', line 41

def def_factory name, maybe: true, aliases: [], &body
  define_singleton_method name, &body
  
  aliases.each do |alias_name|
    if self.respond_to? alias_name
      alias_name = alias_name + '_'
    end
    
    singleton_class.send :alias_method, alias_name, name
  end
  
  if maybe && !name.to_s.end_with?( '?' )
    maybe_name = "#{ name }?".to_sym
    
    if self.respond_to? maybe_name
      maybe_name = "#{ name }_?".to_sym
    end
    
    # HACK  Ugh maybe I wrote this quick to fix it, not sure if it's a decent
    #       idea.. basically, need to figure out what `options` keys go
    #       to {.maybe} and which ones go to the regular factory... matters
    #       for shit like {.attrs} and {.hash_type} 'cause they use option
    #       keys (whether they *should* is something I've debated... sigh,
    #       it is what it is for now).
    #       
    #       So they options that go to {.maybe} just go strait through to
    #       {Type#initialize}, so just grab that method, see what keys it
    #       takes, and then can slice and dice off that...
    # 
    maybe_option_keys = Set.new \
      NRSER::Types::Type.
        instance_method( :initialize ).
        parameters.
        select { |param_type, name| param_type == :key }.
        map { |param_type, name| name }
    
    define_singleton_method maybe_name do |*args, **options|
      maybe_options = options.slice *maybe_option_keys
      factory_options = options.except *maybe_option_keys
      
      maybe public_send( name, *args, **factory_options ), **maybe_options
    end
    
    aliases.each do |alias_name|
      singleton_class.send :alias_method, "#{ alias_name }?", maybe_name
    end
    
  end
end