Module: TakesMacro

Defined in:
lib/takes_macro.rb,
lib/takes_macro/version.rb

Constant Summary collapse

VERSION =
"1.0.1"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.monkey_patch_objectObject



4
5
6
# File 'lib/takes_macro.rb', line 4

def self.monkey_patch_object
  Object.send(:include, TakesMacro)
end

Instance Method Details

#takes(*args) ⇒ Object



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
# File 'lib/takes_macro.rb', line 8

def takes(*args)
  positional_args = args.reject { |arg| arg.is_a?(Array) }
  keyword_args = if args.last.is_a?(Array)
                   args.last.map(&:to_s)
                 else
                   []
                 end
  all_args = (positional_args + keyword_args).flatten.map do |arg|
    arg.to_s.delete("!")
  end

  args_code = [
    positional_args,
  ]

  if keyword_args.one? && !keyword_args.first.include?("!")
    args_code << "options = {}"
  elsif keyword_args.any?
    args_code << "options"
  end
  args_code = args_code.flatten.compact.join(", ")

  bind_positional_args_code = positional_args.map do |arg|
    "@#{arg} = #{arg}"
  end.join("\n")

  bind_keywords_args_code = keyword_args.map do |arg|
    code = if arg =~ /!$/
      arg = arg.delete("!")
      "@#{arg} = options.fetch(:#{arg})"
    else
      "@#{arg} = options[:#{arg}]"
    end
    [code, "options.delete(:#{arg})"].join("\n")
  end.join("\n")

  define_private_attr_readers_code = all_args.map do |arg|
    <<-RUBY
      attr_reader :#{arg}
      private :#{arg}
    RUBY
  end.join("\n")

  ensure_options_are_empty =
    if keyword_args.any?
      <<-EOS
        unless options == {}
          raise ArgumentError, "Not all initialize args were used: \#{options.keys.inspect}"
        end
      EOS
    else
      ""
    end

  code = <<-RUBY
    def initialize(#{args_code})
      #{bind_positional_args_code}
      #{bind_keywords_args_code}
      #{ensure_options_are_empty}
      after_takes
    end
    #{define_private_attr_readers_code}

    def after_takes; end
  RUBY

  class_eval code
end