Issues (3)

lib/koine/attributes/attributes.rb (3 issues)

1
module Koine
2
  module Attributes
0 ignored issues
show
module definition in method body
(Using Ruby 2.0 parser; configure using TargetRubyVersion parameter, under AllCops)
Loading history...
3
    class Attributes
0 ignored issues
show
class definition in method body
(Using Ruby 2.0 parser; configure using TargetRubyVersion parameter, under AllCops)
Loading history...
4
      def initialize(object, adapters:, options: {})
0 ignored issues
show
The Ruby parser could not interpret the code. It reported: unexpected token tCOMMA (Using Ruby 2.0 p...meter, under `AllCops`).
Loading history...
5
        @object = object
6
        @adapters = adapters
7
        @values = {}
8
        @initializer = { strict: true, freeze: false, initialize: !options[:initializer].nil? }
9
10
        if options[:initializer].is_a?(Hash)
11
          @initializer = @initializer.merge(options[:initializer])
12
        end
13
      end
14
15
      def initialize_values(values = {})
16
        if !@initializer[:initialize] && !values.empty?
17
          raise InvalidAttributesError, "wrong number of arguments (given #{values.length}, expected 0)"
18
        end
19
20
        return unless @initializer[:initialize]
21
        set_values(values) && @initializer[:freeze] && freeze
22
      end
23
24
      def set_values(values)
25
        invalid_attributes = []
26
27
        if @initializer[:strict]
28
          attributes = values.keys.map(&:to_sym)
29
          invalid_attributes = attributes - valid_attributes
30
        end
31
32
        unless invalid_attributes.empty?
33
          raise InvalidAttributesError, "Invalid attributes (#{invalid_attributes.join(', ')})"
34
        end
35
36
        values.each do |attribute, value|
37
          set(attribute, value) if has_attribute?(attribute)
38
        end
39
      end
40
41
      def set(attribute, value)
42
        @values[attribute.to_sym] = adapter_for(attribute).coerce(value)
43
      end
44
45
      def with_attribute(attribute, value)
46
        new_attributes = to_h.merge(attribute => value)
47
        @object.class.new(new_attributes)
48
      end
49
50
      def get(attribute)
51
        @values[attribute.to_sym] || adapter_for(attribute).default_value
52
      end
53
54
      def ==(other)
55
        other.to_h == to_h
56
      end
57
58
      def to_h
59
        valid_attributes.map do |name|
60
          [name.to_sym, @object.send(name)]
61
        end.to_h
62
      end
63
64
      def respond_to?(method, _include_private = nil)
65
        method = method.to_s
66
67
        # getter
68
        return true if has_attribute?(method)
69
70
        # {attribute_name}=value
71
        matches = method.match(/^(.*)=$/)
72
        return has_attribute?(matches[1]) if matches
73
74
        # with_{attribute}(value)
75
        matches = method.match(/^with_(.*)$/)
76
        return has_attribute?(matches[1]) if matches
77
78
        false
79
      end
80
81
      def method_missing(method_name, *args)
82
        unless respond_to?(method_name)
83
          raise NoMethodError, "Undefined method #{method_name} for attributed object #{@object}"
84
        end
85
86
        method_name = method_name.to_s
87
88
        if method_name.to_s =~ /=$/
89
          attribute = method_name.to_s.delete('=')
90
          return set(attribute, *args)
91
        end
92
93
        matches = method_name.match(/^with_(.*)$/)
94
        return with_attribute(matches[1], *args) if matches
95
96
        get(method_name)
97
      end
98
99
      private
100
101
      def valid_attributes
102
        @adapters.keys
103
      end
104
105
      def has_attribute?(attribute)
106
        @adapters.key?(attribute.to_sym)
107
      end
108
109
      def adapter_for(attribute)
110
        @adapters.fetch(attribute.to_sym)
111
      end
112
113
      def freeze
114
        @object.freeze
115
        @adapters.freeze
116
        @values.freeze
117
        super
118
      end
119
    end
120
  end
121
end
122