Skip to content

Commit 6020450

Browse files
committed
Allow specifying attributes with a block
Adapted from #1262
1 parent 87d18e9 commit 6020450

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

lib/active_model/serializer.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,19 +112,26 @@ def self.attributes(*attrs)
112112
# attributes :id, :recent_edits
113113
# attribute :name, key: :title
114114
#
115+
# attribute :full_name do
116+
# "#{object.first_name} #{object.last_name}"
117+
# end
118+
#
115119
# def recent_edits
116120
# object.edits.last(5)
117121
# end
118-
def self.attribute(attr, options = {})
122+
def self.attribute(attr, options = {}, &block)
119123
key = options.fetch(:key, attr)
120124
_attributes_keys[attr] = { key: key } if key != attr
121-
_attributes << key unless _attributes.include?(key)
122125

123-
serialized_attributes[key] = ->(object) { object.read_attribute_for_serialization(attr) }
126+
if block_given?
127+
serialized_attributes[key] = ->(instance) { instance.instance_eval(&block) }
128+
else
129+
serialized_attributes[key] = ->(instance) { instance.object.read_attribute_for_serialization(attr) }
130+
end
124131

125132
ActiveModelSerializers.silence_warnings do
126133
define_method key do
127-
serialized_attributes[key].call(object)
134+
serialized_attributes[key].call(self)
128135
end unless method_defined?(key) || _fragmented.respond_to?(attr)
129136
end
130137
end

test/serializers/attribute_test.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,21 @@ def id
7171

7272
assert_equal('custom', hash[:blog][:id])
7373
end
74+
75+
PostWithVirtualAttribute = Class.new(::Model)
76+
class PostWithVirtualAttributeSerializer < ActiveModel::Serializer
77+
attribute :name do
78+
"#{object.first_name} #{object.last_name}"
79+
end
80+
end
81+
82+
def test_virtual_attribute_block
83+
post = PostWithVirtualAttribute.new(first_name: 'Lucas', last_name: 'Hosseini')
84+
hash = serializable(post).serializable_hash
85+
expected = { name: 'Lucas Hosseini' }
86+
87+
assert_equal(expected, hash)
88+
end
7489
end
7590
end
7691
end

0 commit comments

Comments
 (0)