From acea8b21311b6543b4240864d1609d282ec46826 Mon Sep 17 00:00:00 2001 From: armin Date: Sat, 11 Mar 2017 19:31:28 +0100 Subject: [PATCH 1/3] NEW: add dynamic_proxy_object. --- .../dynamic_proxy_object.rb | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 lib/jsonapi-serializers/dynamic_proxy_object.rb diff --git a/lib/jsonapi-serializers/dynamic_proxy_object.rb b/lib/jsonapi-serializers/dynamic_proxy_object.rb new file mode 100644 index 0000000..c0272bf --- /dev/null +++ b/lib/jsonapi-serializers/dynamic_proxy_object.rb @@ -0,0 +1,24 @@ +module JSONAPI + class DynamicProxyObject < BasicObject + + def initialize(target) + @cache = {} + @target = target + end + + def class + @target.class + end + + def cache_key(name, args) + "#{name}_#{args.hash}" + end + + def method_missing(name, *args, &block) + key = cache_key(name, args) + @cache[key] ||= @target.send(name, *args, &block) + @cache[key] + end + + end +end \ No newline at end of file From 20bd27e3713eae12f4dbec98eaacc67dcfb137b5 Mon Sep 17 00:00:00 2001 From: armin Date: Sat, 11 Mar 2017 19:32:38 +0100 Subject: [PATCH 2/3] NEW: make use of dynamic_proxy_object at serializers --- lib/jsonapi-serializers.rb | 1 + lib/jsonapi-serializers/serializer.rb | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/jsonapi-serializers.rb b/lib/jsonapi-serializers.rb index 2979585..5a7b49b 100644 --- a/lib/jsonapi-serializers.rb +++ b/lib/jsonapi-serializers.rb @@ -1,6 +1,7 @@ require "jsonapi-serializers/version" require "jsonapi-serializers/attributes" require "jsonapi-serializers/serializer" +require "jsonapi-serializers/dynamic_proxy_object" module JSONAPI module Serializer diff --git a/lib/jsonapi-serializers/serializer.rb b/lib/jsonapi-serializers/serializer.rb index 47eb874..c2a6a6a 100644 --- a/lib/jsonapi-serializers/serializer.rb +++ b/lib/jsonapi-serializers/serializer.rb @@ -113,7 +113,7 @@ def relationships end if @_include_linkages.include?(formatted_attribute_name) || attr_data[:options][:include_data] - object = has_one_relationship(attribute_name, attr_data) + object = JSONAPI::Serializer.proxy_objects(has_one_relationship(attribute_name, attr_data)) if object.nil? # Spec: Resource linkage MUST be represented as one of the following: # - null for empty to-one relationships. @@ -149,7 +149,7 @@ def relationships # http://jsonapi.org/format/#document-structure-resource-relationships if @_include_linkages.include?(formatted_attribute_name) || attr_data[:options][:include_data] data[formatted_attribute_name]['data'] = [] - objects = has_many_relationship(attribute_name, attr_data) || [] + objects = JSONAPI::Serializer.proxy_objects(has_many_relationship(attribute_name, attr_data) || []) objects.each do |obj| related_object_serializer = JSONAPI::Serializer.find_serializer(obj, @options) data[formatted_attribute_name]['data'] << { @@ -245,7 +245,17 @@ def self.find_serializer(object, options) find_serializer_class(object, options).new(object, options) end + def self.proxy_objects(objects) + return nil unless objects + if objects.respond_to?(:map) + objects.map { |obj| DynamicProxyObject.new(obj) } + else + DynamicProxyObject.new(objects) + end + end + def self.serialize(objects, options = {}) + objects = proxy_objects(objects) # Normalize option strings to symbols. options[:is_collection] = options.delete('is_collection') || options[:is_collection] || false options[:include] = options.delete('include') || options[:include] @@ -455,12 +465,12 @@ def self.find_recursive_relationships(root_object, root_inclusion_tree, results, if serializer.has_one_relationships.has_key?(unformatted_attr_name) is_valid_attr = true attr_data = serializer.has_one_relationships[unformatted_attr_name] - object = serializer.has_one_relationship(unformatted_attr_name, attr_data) + object = proxy_objects(serializer.has_one_relationship(unformatted_attr_name, attr_data)) elsif serializer.has_many_relationships.has_key?(unformatted_attr_name) is_valid_attr = true is_collection = true attr_data = serializer.has_many_relationships[unformatted_attr_name] - object = serializer.has_many_relationship(unformatted_attr_name, attr_data) + object = proxy_objects(serializer.has_many_relationship(unformatted_attr_name, attr_data)) end if !is_valid_attr From dfbe5b991fc581884f07d5b308adb8f6b1859409 Mon Sep 17 00:00:00 2001 From: armin Date: Sat, 7 Oct 2017 19:37:01 +0200 Subject: [PATCH 3/3] NEW: add spec for dynamic_proxy_object --- spec/dynamic_proxy_object_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 spec/dynamic_proxy_object_spec.rb diff --git a/spec/dynamic_proxy_object_spec.rb b/spec/dynamic_proxy_object_spec.rb new file mode 100644 index 0000000..d2ab16b --- /dev/null +++ b/spec/dynamic_proxy_object_spec.rb @@ -0,0 +1,13 @@ +describe JSONAPI::DynamicProxyObject do + it 'should delegate methods to target and cache results' do + target = double('target') + expect(target).to receive(:foo).and_return('bar') + expect(target).to receive(:foo).with(param1: '1', param2: 2).and_return('bar2') + + proxy = JSONAPI::DynamicProxyObject.new(target) + expect(proxy.foo).to eq('bar') + expect(proxy.foo).to eq('bar') + expect(proxy.foo(param1: '1', param2: 2)).to eq('bar2') + expect(proxy.foo(param1: '1', param2: 2)).to eq('bar2') + end +end \ No newline at end of file