From 9c659839e425f76da6364d41991b944a55bbd98a Mon Sep 17 00:00:00 2001 From: Manoj M J Date: Wed, 18 Jul 2018 11:11:47 +0530 Subject: [PATCH 1/2] =?UTF-8?q?Evaluate=20ids=20via=20the=20specified=20?= =?UTF-8?q?=E2=80=98id=5Fmethod=5Fname=E2=80=99=20when=20relationships=20a?= =?UTF-8?q?re=20evaluated=20via=20a=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/fast_jsonapi/object_serializer.rb | 7 +++++- lib/fast_jsonapi/relationship.rb | 14 +++++------ .../object_serializer_class_methods_spec.rb | 25 +++++++++++++++++++ spec/shared/contexts/movie_context.rb | 3 ++- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index 7f740c8..2d83d3b 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -240,10 +240,15 @@ module FastJsonapi relationship_type: relationship_type, cached: options[:cached], polymorphic: fetch_polymorphic_option(options), - conditional_proc: options[:if] + conditional_proc: options[:if], + id_method_name_for_inferred_objects: compute_object_method_name_for_inferred_objects(options[:id_method_name], block) ) end + def compute_object_method_name_for_inferred_objects(id_method_name, block) + (id_method_name.present? && block.present?) ? id_method_name : :id + end + def compute_serializer_name(serializer_key) return serializer_key unless serializer_key.is_a? Symbol namespace = self.name.gsub(/()?\w+Serializer$/, '') diff --git a/lib/fast_jsonapi/relationship.rb b/lib/fast_jsonapi/relationship.rb index 0b3a101..797e489 100644 --- a/lib/fast_jsonapi/relationship.rb +++ b/lib/fast_jsonapi/relationship.rb @@ -1,6 +1,6 @@ module FastJsonapi class Relationship - attr_reader :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc + attr_reader :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc, :id_method_name_for_inferred_objects def initialize( key:, @@ -13,7 +13,8 @@ module FastJsonapi relationship_type:, cached: false, polymorphic:, - conditional_proc: + conditional_proc:, + id_method_name_for_inferred_objects: ) @key = key @name = name @@ -26,6 +27,7 @@ module FastJsonapi @cached = cached @polymorphic = polymorphic @conditional_proc = conditional_proc + @id_method_name_for_inferred_objects = id_method_name_for_inferred_objects end def serialize(record, serialization_params, output_hash) @@ -86,13 +88,11 @@ module FastJsonapi end def fetch_id(record, params) - unless object_block.nil? + if object_block.present? object = object_block.call(record, params) - - return object.map(&:id) if object.respond_to? :map - return object.try(:id) + return object.map { |item| item.public_send(id_method_name_for_inferred_objects) } if object.respond_to? :map + return object.try(id_method_name_for_inferred_objects) end - record.public_send(id_method_name) end end diff --git a/spec/lib/object_serializer_class_methods_spec.rb b/spec/lib/object_serializer_class_methods_spec.rb index 3c477c3..33138d5 100644 --- a/spec/lib/object_serializer_class_methods_spec.rb +++ b/spec/lib/object_serializer_class_methods_spec.rb @@ -87,6 +87,31 @@ describe FastJsonapi::ObjectSerializer do end end + describe '#has_many with block and id_method_name' do + before do + MovieSerializer.has_many(:awards, id_method_name: :imdb_award_id) do |movie| + movie.actors.map(&:awards).flatten + end + end + + after do + MovieSerializer.relationships_to_serialize.delete(:awards) + end + + context 'awards is not included' do + subject(:hash) { MovieSerializer.new(movie).serializable_hash } + + it 'returns correct hash where id is obtained from the method specified via `id_method_name`' do + expected_award_data = movie.actors.map(&:awards).flatten.map do |actor| + { id: actor.imdb_award_id.to_s, type: actor.class.name.downcase.to_sym } + end + serialized_award_data = hash[:data][:relationships][:awards][:data] + + expect(serialized_award_data).to eq(expected_award_data) + end + end + end + describe '#belongs_to' do subject(:relationship) { MovieSerializer.relationships_to_serialize[:area] } diff --git a/spec/shared/contexts/movie_context.rb b/spec/shared/contexts/movie_context.rb index 9061226..5c5c102 100644 --- a/spec/shared/contexts/movie_context.rb +++ b/spec/shared/contexts/movie_context.rb @@ -80,6 +80,7 @@ RSpec.shared_context 'movie class' do a.id = i a.title = "Test Award #{i}" a.actor_id = id + a.imdb_award_id = i * 10 end end end @@ -110,7 +111,7 @@ RSpec.shared_context 'movie class' do end class Award - attr_accessor :id, :title, :actor_id + attr_accessor :id, :title, :actor_id, :imdb_award_id end class State From 0c367d25749bb41eb71cb5c79d250e1b024467ca Mon Sep 17 00:00:00 2001 From: Manoj M J Date: Sat, 21 Jul 2018 10:05:01 +0530 Subject: [PATCH 2/2] Minor code refactor --- lib/fast_jsonapi/object_serializer.rb | 17 ++++++++++++----- lib/fast_jsonapi/relationship.rb | 10 ++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index 2d83d3b..d6015c5 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -232,7 +232,11 @@ module FastJsonapi Relationship.new( key: options[:key] || run_key_transform(base_key), name: name, - id_method_name: options[:id_method_name] || "#{base_serialization_key}#{id_postfix}".to_sym, + id_method_name: compute_id_method_name( + options[:id_method_name], + "#{base_serialization_key}#{id_postfix}".to_sym, + block + ), record_type: options[:record_type] || run_key_transform(base_key_sym), object_method_name: options[:object_method_name] || name, object_block: block, @@ -240,13 +244,16 @@ module FastJsonapi relationship_type: relationship_type, cached: options[:cached], polymorphic: fetch_polymorphic_option(options), - conditional_proc: options[:if], - id_method_name_for_inferred_objects: compute_object_method_name_for_inferred_objects(options[:id_method_name], block) + conditional_proc: options[:if] ) end - def compute_object_method_name_for_inferred_objects(id_method_name, block) - (id_method_name.present? && block.present?) ? id_method_name : :id + def compute_id_method_name(custom_id_method_name, id_method_name_from_relationship, block) + if block.present? + custom_id_method_name || :id + else + custom_id_method_name || id_method_name_from_relationship + end end def compute_serializer_name(serializer_key) diff --git a/lib/fast_jsonapi/relationship.rb b/lib/fast_jsonapi/relationship.rb index 797e489..7924969 100644 --- a/lib/fast_jsonapi/relationship.rb +++ b/lib/fast_jsonapi/relationship.rb @@ -1,6 +1,6 @@ module FastJsonapi class Relationship - attr_reader :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc, :id_method_name_for_inferred_objects + attr_reader :key, :name, :id_method_name, :record_type, :object_method_name, :object_block, :serializer, :relationship_type, :cached, :polymorphic, :conditional_proc def initialize( key:, @@ -13,8 +13,7 @@ module FastJsonapi relationship_type:, cached: false, polymorphic:, - conditional_proc:, - id_method_name_for_inferred_objects: + conditional_proc: ) @key = key @name = name @@ -27,7 +26,6 @@ module FastJsonapi @cached = cached @polymorphic = polymorphic @conditional_proc = conditional_proc - @id_method_name_for_inferred_objects = id_method_name_for_inferred_objects end def serialize(record, serialization_params, output_hash) @@ -90,8 +88,8 @@ module FastJsonapi def fetch_id(record, params) if object_block.present? object = object_block.call(record, params) - return object.map { |item| item.public_send(id_method_name_for_inferred_objects) } if object.respond_to? :map - return object.try(id_method_name_for_inferred_objects) + return object.map { |item| item.public_send(id_method_name) } if object.respond_to? :map + return object.try(id_method_name) end record.public_send(id_method_name) end