virtus 0.0.10 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. data/.gitignore +33 -7
  2. data/.travis.yml +4 -74
  3. data/Changelog.md +11 -2
  4. data/Gemfile +10 -9
  5. data/README.md +85 -1
  6. data/TODO +18 -0
  7. data/config/flay.yml +2 -2
  8. data/config/flog.yml +1 -1
  9. data/config/roodi.yml +3 -3
  10. data/config/site.reek +8 -3
  11. data/lib/virtus.rb +5 -0
  12. data/lib/virtus/attribute.rb +137 -30
  13. data/lib/virtus/attribute/array.rb +17 -1
  14. data/lib/virtus/attribute/boolean.rb +8 -13
  15. data/lib/virtus/attribute/collection.rb +96 -0
  16. data/lib/virtus/attribute/default_value.rb +11 -7
  17. data/lib/virtus/attribute/embedded_value.rb +70 -0
  18. data/lib/virtus/attribute/set.rb +25 -0
  19. data/lib/virtus/attribute_set.rb +18 -16
  20. data/lib/virtus/attributes_accessor.rb +66 -0
  21. data/lib/virtus/class_methods.rb +50 -28
  22. data/lib/virtus/coercion/array.rb +23 -0
  23. data/lib/virtus/coercion/string.rb +10 -4
  24. data/lib/virtus/instance_methods.rb +38 -31
  25. data/lib/virtus/support/options.rb +6 -8
  26. data/lib/virtus/support/type_lookup.rb +4 -11
  27. data/lib/virtus/version.rb +1 -1
  28. data/spec/integration/collection_member_coercion_spec.rb +75 -0
  29. data/spec/integration/custom_attributes_spec.rb +49 -0
  30. data/spec/integration/default_values_spec.rb +32 -0
  31. data/spec/integration/defining_attributes_spec.rb +79 -0
  32. data/spec/integration/embedded_value_spec.rb +50 -0
  33. data/spec/integration/overriding_virtus_spec.rb +46 -0
  34. data/spec/integration/virtus/instance_level_attributes_spec.rb +23 -0
  35. data/spec/rcov.opts +1 -0
  36. data/spec/shared/constants_helpers.rb +9 -0
  37. data/spec/shared/options_class_method.rb +19 -0
  38. data/spec/spec_helper.rb +20 -7
  39. data/spec/unit/virtus/attribute/array/coerce_spec.rb +13 -0
  40. data/spec/unit/virtus/attribute/boolean/coerce_spec.rb +85 -0
  41. data/spec/unit/virtus/attribute/boolean/define_reader_method_spec.rb +15 -0
  42. data/spec/unit/virtus/attribute/boolean/value_coerced_spec.rb +97 -0
  43. data/spec/unit/virtus/attribute/boolean_spec.rb +2 -81
  44. data/spec/unit/virtus/attribute/class/coerce_spec.rb +13 -0
  45. data/spec/unit/virtus/attribute/class_methods/accessor_spec.rb +12 -0
  46. data/spec/unit/virtus/attribute/class_methods/build_spec.rb +37 -0
  47. data/spec/unit/virtus/attribute/class_methods/coercion_method_spec.rb +9 -0
  48. data/spec/unit/virtus/attribute/class_methods/default_spec.rb +9 -0
  49. data/spec/unit/virtus/attribute/class_methods/determine_type_spec.rb +31 -1
  50. data/spec/unit/virtus/attribute/class_methods/merge_options_spec.rb +11 -0
  51. data/spec/unit/virtus/attribute/class_methods/primitive_spec.rb +9 -0
  52. data/spec/unit/virtus/attribute/class_methods/reader_spec.rb +9 -0
  53. data/spec/unit/virtus/attribute/class_methods/writer_spec.rb +9 -0
  54. data/spec/unit/virtus/attribute/coerce_spec.rb +30 -0
  55. data/spec/unit/virtus/attribute/coercion_method_spec.rb +12 -0
  56. data/spec/unit/virtus/attribute/collection/class_methods/merge_options_spec.rb +40 -0
  57. data/spec/unit/virtus/attribute/collection/coerce_spec.rb +26 -0
  58. data/spec/unit/virtus/attribute/date/coerce_spec.rb +47 -0
  59. data/spec/unit/virtus/attribute/date/value_coerced_spec.rb +46 -0
  60. data/spec/unit/virtus/attribute/date_time/coerce_spec.rb +68 -0
  61. data/spec/unit/virtus/attribute/decimal/coerce_spec.rb +117 -0
  62. data/spec/unit/virtus/attribute/default_spec.rb +32 -0
  63. data/spec/unit/virtus/attribute/default_value/attribute_spec.rb +11 -0
  64. data/spec/unit/virtus/attribute/default_value/class_methods/new_spec.rb +4 -2
  65. data/spec/unit/virtus/attribute/default_value/evaluate_spec.rb +51 -0
  66. data/spec/unit/virtus/attribute/default_value/instance_methods/evaluate_spec.rb +9 -6
  67. data/spec/unit/virtus/attribute/default_value/value_spec.rb +11 -0
  68. data/spec/unit/virtus/attribute/define_accessor_methods_spec.rb +26 -0
  69. data/spec/unit/virtus/attribute/define_reader_method_spec.rb +24 -0
  70. data/spec/unit/virtus/attribute/define_writer_method_spec.rb +24 -0
  71. data/spec/unit/virtus/attribute/embedded_value/class_methods/merge_options_spec.rb +17 -0
  72. data/spec/unit/virtus/attribute/embedded_value/coerce_spec.rb +50 -0
  73. data/spec/unit/virtus/attribute/float/coerce_spec.rb +117 -0
  74. data/spec/unit/virtus/attribute/get_spec.rb +80 -0
  75. data/spec/unit/virtus/attribute/inspect_spec.rb +27 -0
  76. data/spec/unit/virtus/attribute/instance_variable_name_spec.rb +12 -0
  77. data/spec/unit/virtus/attribute/integer/coerce_spec.rb +105 -0
  78. data/spec/unit/virtus/attribute/name_spec.rb +12 -0
  79. data/spec/unit/virtus/attribute/numeric/class_methods/descendants_spec.rb +1 -1
  80. data/spec/unit/virtus/attribute/numeric/class_methods/max_spec.rb +9 -0
  81. data/spec/unit/virtus/attribute/numeric/class_methods/min_spec.rb +9 -0
  82. data/spec/unit/virtus/attribute/object/class_methods/descendants_spec.rb +9 -7
  83. data/spec/unit/virtus/attribute/options_spec.rb +14 -0
  84. data/spec/unit/virtus/attribute/public_reader_spec.rb +24 -0
  85. data/spec/unit/virtus/attribute/public_writer_spec.rb +24 -0
  86. data/spec/unit/virtus/attribute/reader_visibility_spec.rb +24 -0
  87. data/spec/unit/virtus/attribute/set/coerce_spec.rb +13 -0
  88. data/spec/unit/virtus/attribute/set_spec.rb +49 -0
  89. data/spec/unit/virtus/attribute/string/coerce_spec.rb +11 -0
  90. data/spec/unit/virtus/attribute/time/coerce_spec.rb +67 -0
  91. data/spec/unit/virtus/attribute/value_coerced_spec.rb +19 -0
  92. data/spec/unit/virtus/attribute/writer_visibility_spec.rb +24 -0
  93. data/spec/unit/virtus/attribute_set/append_spec.rb +12 -0
  94. data/spec/unit/virtus/attribute_set/element_reference_spec.rb +4 -0
  95. data/spec/unit/virtus/attribute_set/element_set_spec.rb +29 -9
  96. data/spec/unit/virtus/attributes_accessor/inspect_spec.rb +9 -0
  97. data/spec/unit/virtus/class_methods/attribute_spec.rb +23 -5
  98. data/spec/unit/virtus/class_methods/attributes_spec.rb +3 -5
  99. data/spec/unit/virtus/class_methods/const_missing_spec.rb +27 -0
  100. data/spec/unit/virtus/class_methods/inherited_spec.rb +21 -0
  101. data/spec/unit/virtus/coercion/array/to_set_spec.rb +12 -0
  102. data/spec/unit/virtus/coercion/date/class_methods/to_date_spec.rb +10 -0
  103. data/spec/unit/virtus/coercion/date_time/class_methods/to_datetime_spec.rb +10 -0
  104. data/spec/unit/virtus/coercion/hash/class_methods/to_date_spec.rb +10 -3
  105. data/spec/unit/virtus/coercion/hash/class_methods/to_datetime_spec.rb +10 -3
  106. data/spec/unit/virtus/coercion/hash/class_methods/to_time_spec.rb +10 -3
  107. data/spec/unit/virtus/coercion/object/class_methods/method_missing_spec.rb +8 -8
  108. data/spec/unit/virtus/coercion/string/class_methods/to_boolean_spec.rb +2 -2
  109. data/spec/unit/virtus/coercion/string/class_methods/to_constant_spec.rb +1 -1
  110. data/spec/unit/virtus/coercion/string/class_methods/to_date_spec.rb +1 -1
  111. data/spec/unit/virtus/coercion/string/class_methods/to_datetime_spec.rb +13 -13
  112. data/spec/unit/virtus/coercion/string/class_methods/to_decimal_spec.rb +25 -1
  113. data/spec/unit/virtus/coercion/string/class_methods/to_float_spec.rb +25 -1
  114. data/spec/unit/virtus/coercion/string/class_methods/to_integer_spec.rb +30 -1
  115. data/spec/unit/virtus/coercion/string/class_methods/to_time_spec.rb +13 -13
  116. data/spec/unit/virtus/coercion/time/class_methods/to_time_spec.rb +10 -0
  117. data/spec/unit/virtus/coercion/true_class/class_methods/to_string_spec.rb +1 -1
  118. data/spec/unit/virtus/instance_methods/attributes_spec.rb +77 -20
  119. data/spec/unit/virtus/instance_methods/element_reference_spec.rb +1 -1
  120. data/spec/unit/virtus/instance_methods/element_set_spec.rb +2 -2
  121. data/spec/unit/virtus/instance_methods/to_hash_spec.rb +23 -0
  122. data/spec/unit/virtus/options/accept_options_spec.rb +10 -11
  123. data/spec/unit/virtus/options/accepted_options_spec.rb +1 -1
  124. data/spec/unit/virtus/options/options_spec.rb +27 -4
  125. data/tasks/metrics/ci.rake +2 -1
  126. data/tasks/metrics/heckle.rake +207 -0
  127. data/tasks/spec.rake +14 -7
  128. data/virtus.gemspec +1 -1
  129. metadata +111 -97
  130. data/VERSION +0 -1
  131. data/examples/custom_coercion_spec.rb +0 -50
  132. data/examples/default_values_spec.rb +0 -21
  133. data/examples/override_attribute_methods_spec.rb +0 -40
  134. data/spec/integration/virtus/attributes/attribute/set_spec.rb +0 -36
  135. data/spec/integration/virtus/class_methods/attribute_spec.rb +0 -82
  136. data/spec/integration/virtus/class_methods/attributes_spec.rb +0 -22
  137. data/spec/integration/virtus/class_methods/const_missing_spec.rb +0 -44
  138. data/spec/unit/shared/attribute.rb +0 -7
  139. data/spec/unit/shared/attribute/accept_options.rb +0 -37
  140. data/spec/unit/shared/attribute/accepted_options.rb +0 -5
  141. data/spec/unit/shared/attribute/get.rb +0 -44
  142. data/spec/unit/shared/attribute/inspect.rb +0 -7
  143. data/spec/unit/shared/attribute/set.rb +0 -37
  144. data/spec/unit/virtus/attribute/array_spec.rb +0 -24
  145. data/spec/unit/virtus/attribute/class_spec.rb +0 -24
  146. data/spec/unit/virtus/attribute/date_spec.rb +0 -59
  147. data/spec/unit/virtus/attribute/date_time_spec.rb +0 -87
  148. data/spec/unit/virtus/attribute/decimal_spec.rb +0 -109
  149. data/spec/unit/virtus/attribute/float_spec.rb +0 -109
  150. data/spec/unit/virtus/attribute/hash_spec.rb +0 -11
  151. data/spec/unit/virtus/attribute/integer_spec.rb +0 -99
  152. data/spec/unit/virtus/attribute/string_spec.rb +0 -21
  153. data/spec/unit/virtus/attribute/time_spec.rb +0 -82
  154. data/spec/unit/virtus/class_methods/new_spec.rb +0 -41
@@ -12,10 +12,26 @@ module Virtus
12
12
  #
13
13
  # post = Post.new(:tags => %w(red green blue))
14
14
  #
15
- class Array < Object
15
+ class Array < Collection
16
16
  primitive ::Array
17
17
  coercion_method :to_array
18
18
 
19
+ # Coerce a member of a source collection and append it to the target collection
20
+ #
21
+ # @param [Array, Set] collection
22
+ # target collection to which the coerced member should be appended
23
+ #
24
+ # @param [Object] entry
25
+ # the member that should be coerced and appended
26
+ #
27
+ # @return [Array, Set]
28
+ # collection with the coerced member appended to it
29
+ #
30
+ # @api private
31
+ def coerce_and_append_member(collection, entry)
32
+ collection << @member_type_instance.coerce(entry)
33
+ end
34
+
19
35
  end # class Array
20
36
  end # class Attribute
21
37
  end # module Virtus
@@ -21,19 +21,20 @@ module Virtus
21
21
  # Returns if the given value is either true or false
22
22
  #
23
23
  # @example
24
- # Virtus::Attribute::Boolean.primitive?(true) # => true
25
- # Virtus::Attribute::Boolean.primitive?(false) # => true
26
- # Virtus::Attribute::Boolean.primitive?(1) # => false
27
- # Virtus::Attribute::Boolean.primitive?('true') # => false
24
+ # boolean = Virtus::Attribute::Boolean.new(:bool)
25
+ # boolean.value_coerced?(true) # => true
26
+ # boolean.value_coerced?(false) # => true
27
+ # boolean.value_coerced?(1) # => false
28
+ # boolean.value_coerced?('true') # => false
28
29
  #
29
30
  # @return [Boolean]
30
31
  #
31
32
  # @api public
32
- def self.primitive?(value)
33
+ def value_coerced?(value)
33
34
  value.equal?(true) || value.equal?(false)
34
35
  end
35
36
 
36
- # Creates standard and boolean attribute reader methods
37
+ # Creates an attribute reader method as a query
37
38
  #
38
39
  # @param [Module] mod
39
40
  #
@@ -42,13 +43,7 @@ module Virtus
42
43
  # @api private
43
44
  def define_reader_method(mod)
44
45
  super
45
-
46
- reader_method_name = "#{name}?"
47
- attribute = self
48
-
49
- mod.send(:define_method, reader_method_name) { attribute.get(self) }
50
- mod.send(reader_visibility, reader_method_name)
51
-
46
+ mod.define_reader_method(self, "#{name}?", reader_visibility)
52
47
  self
53
48
  end
54
49
 
@@ -0,0 +1,96 @@
1
+ module Virtus
2
+ class Attribute
3
+
4
+ # Abstract superclass for collection Attributes.
5
+ #
6
+ # Handles coercing members to the designated member type.
7
+ #
8
+ # @abstract
9
+ class Collection < Object
10
+
11
+ # The type to which members of this collection will be coerced
12
+ #
13
+ # @example
14
+ #
15
+ # class Post
16
+ # include Virtus
17
+ #
18
+ # attribute :tags, Array[String]
19
+ # end
20
+ #
21
+ # Post.attributes[:tags].member_type # => Virtus::Attribute::String
22
+ #
23
+ # @return [Virtus::Attribute]
24
+ #
25
+ # @api public
26
+ attr_reader :member_type
27
+
28
+ # Handles collection with member_type syntax
29
+ #
30
+ # @param [Class]
31
+ #
32
+ # @param [Hash]
33
+ #
34
+ # @return [Hash]
35
+ #
36
+ # @api private
37
+ def self.merge_options(type, options)
38
+ if !type.respond_to?(:size)
39
+ options
40
+ elsif type.size > 1
41
+ raise NotImplementedError, "build SumType from list of types (#{type.inspect})"
42
+ else
43
+ options.merge(:member_type => type.first)
44
+ end
45
+ end
46
+
47
+ # Init an instance of Virtus::Attribute::Collection
48
+ #
49
+ # @api private
50
+ def initialize(*)
51
+ super
52
+ @member_type = @options.fetch(:member_type, Virtus::Attribute::Object)
53
+ @member_type_instance = Attribute.build(@name, @member_type)
54
+ end
55
+
56
+ # Coerce a collection with members
57
+ #
58
+ # @param [Object]
59
+ #
60
+ # @return [Object]
61
+ #
62
+ # @api private
63
+ def coerce(value)
64
+ coerced = super
65
+ return coerced unless coerced.respond_to?(:inject)
66
+ coerced.inject(new_collection) do |collection, entry|
67
+ coerce_and_append_member(collection, entry)
68
+ end
69
+ end
70
+
71
+ # Return an instance of the collection
72
+ #
73
+ # @return [Enumerable]
74
+ #
75
+ # @api private
76
+ def new_collection
77
+ self.class.primitive.new
78
+ end
79
+
80
+ # Coerce entry and add it to the collection
81
+ #
82
+ # @abstract
83
+ #
84
+ # @raise NotImplementedError
85
+ #
86
+ # @return [undefined]
87
+ #
88
+ # @api private
89
+ def coerce_and_append_member(collection, entry)
90
+ raise NotImplementedError,
91
+ "#{self.class}#coerce_and_append_member has not been implemented"
92
+ end
93
+
94
+ end # class Array
95
+ end # class Attribute
96
+ end # module Virtus
@@ -3,8 +3,8 @@ module Virtus
3
3
 
4
4
  # Class representing the default value option
5
5
  class DefaultValue
6
- DUP_CLASSES = [ ::NilClass, ::TrueClass, ::FalseClass,
7
- ::Numeric, ::Symbol ].freeze
6
+ SINGLETON_CLASSES = [ ::NilClass, ::TrueClass, ::FalseClass,
7
+ ::Numeric, ::Symbol ].freeze
8
8
 
9
9
  # Returns the attribute associated with this default value instance
10
10
  #
@@ -42,8 +42,8 @@ module Virtus
42
42
  def evaluate(instance)
43
43
  if callable?
44
44
  call(instance)
45
- elsif duplicable?
46
- value.dup
45
+ elsif cloneable?
46
+ value.clone
47
47
  else
48
48
  value
49
49
  end
@@ -71,13 +71,17 @@ module Virtus
71
71
  value.respond_to?(:call)
72
72
  end
73
73
 
74
- # Returns whether or not the value is duplicable
74
+ # Returns whether or not the value is cloneable
75
75
  #
76
76
  # # return [TrueClass, FalseClass]
77
77
  #
78
78
  # @api private
79
- def duplicable?
80
- DUP_CLASSES.none? { |klass| value.kind_of?(klass) }
79
+ def cloneable?
80
+ case value
81
+ when *SINGLETON_CLASSES then false
82
+ else
83
+ true
84
+ end
81
85
  end
82
86
 
83
87
  end # class DefaultValue
@@ -0,0 +1,70 @@
1
+ require 'ostruct'
2
+
3
+ module Virtus
4
+ class Attribute
5
+
6
+ # EmbeddedValue
7
+ #
8
+ # @example
9
+ #
10
+ # class Address
11
+ # include Virtus
12
+ #
13
+ # attribute :street, String
14
+ # attribute :zipcode, String
15
+ # attribute :city, String
16
+ # end
17
+ #
18
+ # class User
19
+ # include Virtus
20
+ #
21
+ # attribute :address, Address
22
+ # end
23
+ #
24
+ # user = User.new(:address => {
25
+ # :street => 'Street 1/2', :zipcode => '12345', :city => 'NYC' })
26
+ #
27
+ class EmbeddedValue < Object
28
+
29
+ # @see Attribute.merge_options
30
+ #
31
+ # @return [Hash]
32
+ # an updated options hash for configuring an EmbeddedValue instance
33
+ #
34
+ # @api private
35
+ def self.merge_options(type, options)
36
+ options.merge(:model => type)
37
+ end
38
+
39
+ # Sets @model ivar
40
+ #
41
+ # @see Virtus::Attribute#initialize
42
+ #
43
+ # @return [undefined]
44
+ #
45
+ # @api private
46
+ def initialize(name, options = {})
47
+ super
48
+ @model = options.fetch(:model, OpenStruct)
49
+ end
50
+
51
+ # Coerce attributes into a virtus object
52
+ #
53
+ # @param [Hash,Virtus]
54
+ #
55
+ # @return [Virtus]
56
+ #
57
+ # @api private
58
+ def coerce(attributes_or_object)
59
+ value = if attributes_or_object.kind_of?(::Hash)
60
+ @model.new(attributes_or_object)
61
+ else
62
+ attributes_or_object
63
+ end
64
+
65
+ super(value)
66
+ end
67
+
68
+ end # class EmbeddedValue
69
+ end # class Attribute
70
+ end # module Virtus
@@ -0,0 +1,25 @@
1
+ module Virtus
2
+ class Attribute
3
+
4
+ # Set
5
+ #
6
+ # @example
7
+ # class Post
8
+ # include Virtus
9
+ #
10
+ # attribute :tags, Set
11
+ # end
12
+ #
13
+ # post = Post.new(:tags => %w(red green blue))
14
+ #
15
+ class Set < Collection
16
+ primitive ::Set
17
+ coercion_method :to_set
18
+
19
+ def coerce_and_append_member(collection, entry)
20
+ collection << @member_type_instance.coerce(entry)
21
+ end
22
+
23
+ end # class Set
24
+ end # class Attribute
25
+ end # module Virtus
@@ -24,9 +24,10 @@ module Virtus
24
24
  #
25
25
  # @api private
26
26
  def initialize(parent = nil, attributes = [])
27
- @parent = parent
28
- @attributes = attributes.dup
29
- @index = {}
27
+ @parent = parent
28
+ @attributes = attributes.dup
29
+ @index = {}
30
+ @string_index = {}
30
31
  reset
31
32
  end
32
33
 
@@ -91,7 +92,7 @@ module Virtus
91
92
  #
92
93
  # @api public
93
94
  def [](name)
94
- @index[name]
95
+ @index.fetch(name) { @string_index[name] }
95
96
  end
96
97
 
97
98
  # Set an attribute by name
@@ -106,9 +107,8 @@ module Virtus
106
107
  #
107
108
  # @api public
108
109
  def []=(name, attribute)
109
- delete(name)
110
110
  @attributes << attribute
111
- @index[name] = attribute
111
+ update_index(name, attribute)
112
112
  end
113
113
 
114
114
  # Reset the index when the parent is updated
@@ -118,33 +118,35 @@ module Virtus
118
118
  # @api private
119
119
  def reset
120
120
  parent = self.parent
121
- merge_index(parent) if parent
122
- merge_index(@attributes)
121
+ merge_attributes(parent) if parent
122
+ merge_attributes(@attributes)
123
123
  self
124
124
  end
125
125
 
126
126
  private
127
127
 
128
- # Delete the Attribute by name
128
+ # Merge the attributes into the index
129
129
  #
130
- # @param [Symbol] name
130
+ # @param [Array<Attribute>] attributes
131
131
  #
132
132
  # @return [undefined]
133
133
  #
134
134
  # @api private
135
- def delete(name)
136
- @attributes.delete(@index.delete(name))
135
+ def merge_attributes(attributes)
136
+ attributes.each { |attribute| update_index(attribute.name, attribute) }
137
137
  end
138
138
 
139
- # Add the attributes to the index
139
+ # Update the symbol and string indexes with the attribute
140
140
  #
141
- # @param [Array<Attribute>] attributes
141
+ # @param [Symbol] name
142
+ #
143
+ # @param [Attribute] attribute
142
144
  #
143
145
  # @return [undefined]
144
146
  #
145
147
  # @api private
146
- def merge_index(attributes)
147
- attributes.each { |attribute| @index[attribute.name] = attribute }
148
+ def update_index(name, attribute)
149
+ @index[name] = @string_index[name.to_s.freeze] = attribute
148
150
  end
149
151
 
150
152
  end # class AttributeSet
@@ -0,0 +1,66 @@
1
+ module Virtus
2
+
3
+ # Host attribute accessor methods
4
+ class AttributesAccessor < Module
5
+
6
+ # The inspect value of this Module
7
+ #
8
+ # This provides meaningful output when inspecting the ancestors
9
+ # of a class/module that includes this module
10
+ #
11
+ # @example
12
+ #
13
+ # class ClassWithAttributes
14
+ # include Virtus
15
+ # end
16
+ #
17
+ # mod = ClassWithAttributes.send(:virtus_setup_attributes_accessor_module)
18
+ # mod.inspect
19
+ #
20
+ # @return [String]
21
+ #
22
+ # @api public
23
+ attr_reader :inspect
24
+
25
+ # Initialize a module for hosting Attribute access methods
26
+ #
27
+ # @param [Symbol, String] name
28
+ #
29
+ # @api private
30
+ def initialize(name)
31
+ super()
32
+ @inspect = "#{name}::AttributesAccessor"
33
+ end
34
+
35
+ # Defines an attribute reader method
36
+ #
37
+ # @param [Attribute] attribute
38
+ # @param [Symbol] method_name
39
+ # @param [Symbol] visibility
40
+ #
41
+ # @return [self]
42
+ #
43
+ # @api private
44
+ def define_reader_method(attribute, method_name, visibility)
45
+ define_method(method_name) { attribute.get(self) }
46
+ send(visibility, method_name)
47
+ self
48
+ end
49
+
50
+ # Defines an attribute writer method
51
+ #
52
+ # @param [Attribute] attribute
53
+ # @param [Symbol] method_name
54
+ # @param [Symbol] visibility
55
+ #
56
+ # @return [self]
57
+ #
58
+ # @api private
59
+ def define_writer_method(attribute, method_name, visibility)
60
+ define_method(method_name) { |value| attribute.set(self, value) }
61
+ send(visibility, method_name)
62
+ self
63
+ end
64
+
65
+ end
66
+ end