Module: MethodStruct

Defined in:
lib/method_struct.rb,
lib/method_struct/version.rb,
lib/method_struct/defaults.rb,
lib/method_struct/argument_parser.rb,
lib/method_struct/argument_verifier.rb

Defined Under Namespace

Classes: ArgumentParser, ArgumentVerifier, Defaults

Constant Summary collapse

VERSION =
"0.3.0"

Class Method Summary collapse

Class Method Details

.new(*fields, &block) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
# File 'lib/method_struct.rb', line 7

def self.new(*fields, &block)
  if fields.last.is_a?(Hash)
    options = fields.last
    fields = fields.take(fields.size - 1)
  else
    options = {}
  end

  unless fields.all?{ |f| f.is_a?(Symbol) }
    invalid_fields = fields.select{ |f| !f.is_a?(Symbol) }
    raise ArgumentError, "only symbol fields allowed: #{invalid_fields.inspect}"
  end

  method_name = options.fetch(:method_name, Defaults.get[:method_name])
  require_all = options.fetch(:require_all, Defaults.get[:require_all])
  require_presence = options.fetch(:require_presence, Defaults.get[:require_presence])

  Class.new do
    singleton_class = (class << self; self; end)

    singleton_class.instance_eval do
      define_method(method_name) do |*field_values, &blk|
        new(*field_values).send(method_name, &blk)
      end

      define_method(:[]) do |*args|
        send(method_name, *args)
      end

      define_method(:to_proc) do
        Proc.new { |*args| send(method_name, *args) }
      end
    end

    define_method(:[]) do |&blk|
      send(method_name, &blk)
    end

    define_method(:initialize) do |*values|
      arguments = ArgumentParser.new(
        :fields => fields,
        :raw_arguments => values,
        :require_all => require_all,
        :require_presence => require_presence
      ).call

      arguments.each do |field, value|
        instance_variable_set("@#{field}", value)
      end
    end

    define_method(:==) do |other|
      self.class == other.class && fields.all? do |field|
        send(field) == other.send(field)
      end
    end
    alias_method :eql?, :==

    define_method(:hash) do
      fields.map { |field| send(field).hash }.inject(&:^)
    end

    fields.each do |field|
      attr_reader(field)
      protected field
    end

    class_eval(&block) if block_given?
  end
end