From 6020450fe4e1a3a947de36e233bdfeccafe81a33 Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Mon, 30 Nov 2015 16:45:17 -0600 Subject: [PATCH] Allow specifying attributes with a block Adapted from https://github.com/rails-api/active_model_serializers/pull/1262 --- lib/active_model/serializer.rb | 15 +++++++++++---- test/serializers/attribute_test.rb | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index f7e7b435..25d50848 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -112,19 +112,26 @@ module ActiveModel # attributes :id, :recent_edits # attribute :name, key: :title # + # attribute :full_name do + # "#{object.first_name} #{object.last_name}" + # end + # # def recent_edits # object.edits.last(5) # end - def self.attribute(attr, options = {}) + def self.attribute(attr, options = {}, &block) key = options.fetch(:key, attr) _attributes_keys[attr] = { key: key } if key != attr - _attributes << key unless _attributes.include?(key) - serialized_attributes[key] = ->(object) { object.read_attribute_for_serialization(attr) } + if block_given? + serialized_attributes[key] = ->(instance) { instance.instance_eval(&block) } + else + serialized_attributes[key] = ->(instance) { instance.object.read_attribute_for_serialization(attr) } + end ActiveModelSerializers.silence_warnings do define_method key do - serialized_attributes[key].call(object) + serialized_attributes[key].call(self) end unless method_defined?(key) || _fragmented.respond_to?(attr) end end diff --git a/test/serializers/attribute_test.rb b/test/serializers/attribute_test.rb index 99452e53..e1368c27 100644 --- a/test/serializers/attribute_test.rb +++ b/test/serializers/attribute_test.rb @@ -71,6 +71,21 @@ module ActiveModel assert_equal('custom', hash[:blog][:id]) end + + PostWithVirtualAttribute = Class.new(::Model) + class PostWithVirtualAttributeSerializer < ActiveModel::Serializer + attribute :name do + "#{object.first_name} #{object.last_name}" + end + end + + def test_virtual_attribute_block + post = PostWithVirtualAttribute.new(first_name: 'Lucas', last_name: 'Hosseini') + hash = serializable(post).serializable_hash + expected = { name: 'Lucas Hosseini' } + + assert_equal(expected, hash) + end end end end