Skip to content

Commit 87d18e9

Browse files
committed
Map attributes to Attribute values when defined in serializer
1 parent b3b9a46 commit 87d18e9

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

lib/active_model/serializer.rb

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ def self.digest_caller_file(caller_line)
4646

4747
with_options instance_writer: false, instance_reader: false do |serializer|
4848
class_attribute :_type, instance_reader: true
49-
class_attribute :_attributes # @api private : names of attribute methods, @see Serializer#attribute
50-
self._attributes ||= []
49+
class_attribute :serialized_attributes, instance_writer: false # @api public: maps attribute name to 'Attribute' function
50+
self.serialized_attributes ||= {}
5151
class_attribute :_attributes_keys # @api private : maps attribute value to explict key name, @see Serializer#attribute
5252
self._attributes_keys ||= {}
5353
class_attribute :_links # @api private : links definitions, @see Serializer#link
@@ -69,11 +69,11 @@ def self.digest_caller_file(caller_line)
6969
serializer.class_attribute :_cache_digest # @api private : Generated
7070
end
7171

72-
# Serializers inherit _attributes and _attributes_keys.
72+
# Serializers inherit serialized_attributes and _attributes_keys.
7373
# Generates a unique digest for each serializer at load.
7474
def self.inherited(base)
7575
caller_line = caller.first
76-
base._attributes = _attributes.dup
76+
base.serialized_attributes = serialized_attributes.dup
7777
base._attributes_keys = _attributes_keys.dup
7878
base._links = _links.dup
7979
base._cache_digest = digest_caller_file(caller_line)
@@ -91,6 +91,10 @@ def self.link(name, value = nil, &block)
9191
_links[name] = block || value
9292
end
9393

94+
def self._attributes
95+
serialized_attributes.keys
96+
end
97+
9498
# @example
9599
# class AdminAuthorSerializer < ActiveModel::Serializer
96100
# attributes :id, :name, :recent_edits
@@ -102,22 +106,25 @@ def self.attributes(*attrs)
102106
end
103107
end
104108

109+
# TODO: remove the dynamic method definition
105110
# @example
106111
# class AdminAuthorSerializer < ActiveModel::Serializer
107112
# attributes :id, :recent_edits
108113
# attribute :name, key: :title
109114
#
110115
# def recent_edits
111116
# object.edits.last(5)
112-
# enr
117+
# end
113118
def self.attribute(attr, options = {})
114119
key = options.fetch(:key, attr)
115120
_attributes_keys[attr] = { key: key } if key != attr
116121
_attributes << key unless _attributes.include?(key)
117122

123+
serialized_attributes[key] = ->(object) { object.read_attribute_for_serialization(attr) }
124+
118125
ActiveModelSerializers.silence_warnings do
119126
define_method key do
120-
object.read_attribute_for_serialization(attr)
127+
serialized_attributes[key].call(object)
121128
end unless method_defined?(key) || _fragmented.respond_to?(attr)
122129
end
123130
end
@@ -249,14 +256,14 @@ def json_key
249256
def attributes(requested_attrs = nil)
250257
self.class._attributes.each_with_object({}) do |name, hash|
251258
next unless requested_attrs.nil? || requested_attrs.include?(name)
252-
if self.class._fragmented
253-
hash[name] = self.class._fragmented.public_send(name)
254-
else
255-
hash[name] = send(name)
256-
end
259+
hash[name] = read_attribute_for_serialization(name)
257260
end
258261
end
259262

263+
def read_attribute_for_serialization(key)
264+
self.class._fragmented ? self.class._fragmented.public_send(key) : send(key)
265+
end
266+
260267
# @api private
261268
# Used by JsonApi adapter to build resource links.
262269
def links

0 commit comments

Comments
 (0)