1
1
module ActiveModel
2
2
class Serializer
3
3
module Attributes
4
- # @api private
5
- class Attribute
6
- delegate :call , to : :reader
7
-
8
- attr_reader :name , :reader
9
-
10
- def initialize ( name )
11
- @name = name
12
- @reader = :no_reader
13
- end
14
-
15
- def self . build ( name , block )
16
- if block
17
- AttributeBlock . new ( name , block )
18
- else
19
- AttributeReader . new ( name )
20
- end
21
- end
22
- end
23
- # @api private
24
- class AttributeReader < Attribute
25
- def initialize ( name )
26
- super ( name )
27
- @reader = -> ( instance ) { instance . read_attribute_for_serialization ( name ) }
28
- end
29
- end
30
- # @api private
31
- class AttributeBlock < Attribute
32
- def initialize ( name , block )
33
- super ( name )
34
- @reader = -> ( instance ) { instance . instance_eval ( &block ) }
35
- end
36
- end
37
-
38
4
extend ActiveSupport ::Concern
39
5
40
6
included do
41
7
with_options instance_writer : false , instance_reader : false do |serializer |
42
8
serializer . class_attribute :_attribute_mappings # @api private : maps attribute key names to names to names of implementing methods, @see #attribute
43
9
self . _attribute_mappings ||= { }
10
+ serializer . class_attribute :_attribute_keys # @api private : maps attribute names to keys, @see #attribute
11
+ self . _attribute_keys ||= { }
44
12
end
45
13
46
14
# Return the +attributes+ of +object+ as presented
47
15
# by the serializer.
48
16
def attributes ( requested_attrs = nil , reload = false )
49
17
@attributes = nil if reload
50
- @attributes ||= self . class . _attribute_mappings . each_with_object ( { } ) do |( key , attribute_mapping ) , hash |
18
+ @attributes ||= self . class . _attribute_keys . each_with_object ( { } ) do |( name , key ) , hash |
51
19
next unless requested_attrs . nil? || requested_attrs . include? ( key )
52
- hash [ key ] = attribute_mapping . call ( self )
20
+ hash [ key ] = self . class . _attribute_mappings [ name ] . call ( self )
53
21
end
54
22
end
55
23
end
@@ -58,6 +26,7 @@ module ClassMethods
58
26
def inherited ( base )
59
27
super
60
28
base . _attribute_mappings = _attribute_mappings . dup
29
+ base . _attribute_keys = _attribute_keys . dup
61
30
end
62
31
63
32
# @example
@@ -84,26 +53,35 @@ def attributes(*attrs)
84
53
# object.edits.last(5)
85
54
# end
86
55
def attribute ( attr , options = { } , &block )
87
- key = options . fetch ( :key , attr )
88
- _attribute_mappings [ key ] = Attribute . build ( attr , block )
56
+ _attribute_keys [ attr ] = options . fetch ( :key , attr )
57
+ _attribute_mappings [ attr ] = _attribute_mapping ( attr , block )
58
+ end
59
+
60
+ # @api private
61
+ def _attribute_mapping ( name , block )
62
+ if block
63
+ -> ( instance ) { instance . instance_eval ( &block ) }
64
+ else
65
+ -> ( instance ) { instance . read_attribute_for_serialization ( name ) }
66
+ end
89
67
end
90
68
91
69
# @api private
92
- # names of attribute methods
70
+ # keys of attributes
93
71
# @see Serializer::attribute
94
72
def _attributes
95
- _attribute_mappings . keys
73
+ _attribute_keys . values
96
74
end
97
75
98
76
# @api private
99
77
# maps attribute value to explict key name
100
78
# @see Serializer::attribute
101
79
# @see Adapter::FragmentCache#fragment_serializer
102
80
def _attributes_keys
103
- _attribute_mappings
104
- . each_with_object ( { } ) do |( key , attribute_mapping ) , hash |
105
- next if key == attribute_mapping . name
106
- hash [ attribute_mapping . name ] = { key : key }
81
+ _attribute_keys
82
+ . each_with_object ( { } ) do |( name , key ) , hash |
83
+ next if key == name
84
+ hash [ name ] = { key : key }
107
85
end
108
86
end
109
87
end
0 commit comments