From ce2c8003eebf715058f17ce3b849d3c1f6510b88 Mon Sep 17 00:00:00 2001 From: Gleydson Tavares Date: Fri, 10 Aug 2018 13:15:02 -0300 Subject: [PATCH 01/11] add the "option key" in customizable options --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a03e1a8..8b40273 100644 --- a/README.md +++ b/README.md @@ -409,6 +409,7 @@ serializer.serializable_hash Option | Purpose | Example ------------ | ------------- | ------------- set_type | Type name of Object | ```set_type :movie ``` +key | Key of Object | ```belongs_to :owner, key: :user ``` set_id | ID of Object | ```set_id :owner_id ``` cache_options | Hash to enable caching and set cache length | ```cache_options enabled: true, cache_length: 12.hours, race_condition_ttl: 10.seconds``` id_method_name | Set custom method name to get ID of an object | ```has_many :locations, id_method_name: :place_ids ``` From e3c45d9b1bb667b67cb40e3d5de9870ba9974617 Mon Sep 17 00:00:00 2001 From: Igor Khodyrev Date: Thu, 26 Jul 2018 16:18:17 +0300 Subject: [PATCH 02/11] Fix weak entities case (id is not meaningful attribute) with include. --- lib/fast_jsonapi/serialization_core.rb | 2 +- spec/lib/object_serializer_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/fast_jsonapi/serialization_core.rb b/lib/fast_jsonapi/serialization_core.rb index 8598fe0..e64bf1a 100644 --- a/lib/fast_jsonapi/serialization_core.rb +++ b/lib/fast_jsonapi/serialization_core.rb @@ -134,7 +134,7 @@ module FastJsonapi included_records.concat(serializer_records) unless serializer_records.empty? end - code = "#{record_type}_#{inc_obj.id}" + code = "#{record_type}_#{serializer.id_from_record(inc_obj)}" next if known_included_objects.key?(code) known_included_objects[code] = inc_obj diff --git a/spec/lib/object_serializer_spec.rb b/spec/lib/object_serializer_spec.rb index 06aac37..236cf8d 100644 --- a/spec/lib/object_serializer_spec.rb +++ b/spec/lib/object_serializer_spec.rb @@ -158,6 +158,32 @@ describe FastJsonapi::ObjectSerializer do end end + context 'id attribute is the same for actors and not a primary key' do + before do + ActorSerializer.set_id :email + movie.actor_ids = [0, 0, 0] + class << movie + def actors + super.each_with_index { |actor, i| actor.email = "actor#{i}@email.com" } + end + end + end + + after { ActorSerializer.set_id nil } + + let(:options) { { include: ['actors'] } } + subject { MovieSerializer.new(movie, options).serializable_hash } + + it 'returns all actors in includes' do + + expect( + subject[:included].select { |i| i[:type] == :actor }.map { |i| i[:id] } + ).to eq( + movie.actors.map(&:email) + ) + end + end + context 'nested includes' do it 'has_many to belongs_to: returns correct nested includes when serializable_hash is called' do # 3 actors, 3 agencies From 42d92037960d9ba3a5b5b97f7be80a33ca98098b Mon Sep 17 00:00:00 2001 From: Alessandro Dal Grande Date: Sat, 21 Jul 2018 22:27:10 -0700 Subject: [PATCH 03/11] Fix confusing error when using include and no relationship was set If you forgot to set any `has_many` in the serializer and tried to serialize with an `include` you would get: ``` NoMethodError (undefined method `[]' for nil:NilClass): ``` That is not very helpful. Setting the variable with a default case makes sure the right error message gets displayed. --- lib/fast_jsonapi/object_serializer.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index 28b4390..afab577 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -292,7 +292,8 @@ module FastJsonapi includes.detect do |include_item| klass = self parse_include_item(include_item).each do |parsed_include| - relationship_to_include = klass.relationships_to_serialize[parsed_include] + relationships_to_serialize = klass.relationships_to_serialize || {} + relationship_to_include = relationships_to_serialize[parsed_include] raise ArgumentError, "#{parsed_include} is not specified as a relationship on #{klass.name}" unless relationship_to_include raise NotImplementedError if relationship_to_include.polymorphic.is_a?(Hash) klass = relationship_to_include.serializer.to_s.constantize From 3973b312a7473216ad6db2d7224168313d833fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pradel?= Date: Thu, 23 Aug 2018 15:50:35 -0700 Subject: [PATCH 04/11] Demodulize relationship record class name --- lib/fast_jsonapi/relationship.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fast_jsonapi/relationship.rb b/lib/fast_jsonapi/relationship.rb index 7924969..6acc0a3 100644 --- a/lib/fast_jsonapi/relationship.rb +++ b/lib/fast_jsonapi/relationship.rb @@ -68,7 +68,7 @@ module FastJsonapi def id_hash_from_record(record, record_types) # memoize the record type within the record_types dictionary, then assigning to record_type: - associated_record_type = record_types[record.class] ||= record.class.name.underscore.to_sym + associated_record_type = record_types[record.class] ||= record.class.name.demodulize.underscore.to_sym id_hash(record.id, associated_record_type) end From 955f4f234d0e6fa768c5457839d5d39d04bad26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pradel?= Date: Thu, 23 Aug 2018 16:58:39 -0700 Subject: [PATCH 05/11] Add support for polymorphic includes --- lib/fast_jsonapi/object_serializer.rb | 3 +-- lib/fast_jsonapi/serialization_core.rb | 12 +++++++++--- spec/lib/object_serializer_spec.rb | 18 ++++++++++++++++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index afab577..26a4f95 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -295,8 +295,7 @@ module FastJsonapi relationships_to_serialize = klass.relationships_to_serialize || {} relationship_to_include = relationships_to_serialize[parsed_include] raise ArgumentError, "#{parsed_include} is not specified as a relationship on #{klass.name}" unless relationship_to_include - raise NotImplementedError if relationship_to_include.polymorphic.is_a?(Hash) - klass = relationship_to_include.serializer.to_s.constantize + klass = relationship_to_include.serializer.to_s.constantize unless relationship_to_include.polymorphic.is_a?(Hash) end end end diff --git a/lib/fast_jsonapi/serialization_core.rb b/lib/fast_jsonapi/serialization_core.rb index e64bf1a..a456b21 100644 --- a/lib/fast_jsonapi/serialization_core.rb +++ b/lib/fast_jsonapi/serialization_core.rb @@ -119,9 +119,10 @@ module FastJsonapi next unless relationships_to_serialize && relationships_to_serialize[item] relationship_item = relationships_to_serialize[item] next unless relationship_item.include_relationship?(record, params) - raise NotImplementedError if relationship_item.polymorphic.is_a?(Hash) - record_type = relationship_item.record_type - serializer = relationship_item.serializer.to_s.constantize + unless relationship_item.polymorphic.is_a?(Hash) + record_type = relationship_item.record_type + serializer = relationship_item.serializer.to_s.constantize + end relationship_type = relationship_item.relationship_type included_objects = relationship_item.fetch_associated_object(record, params) @@ -129,6 +130,11 @@ module FastJsonapi included_objects = [included_objects] unless relationship_type == :has_many included_objects.each do |inc_obj| + if relationship_item.polymorphic.is_a?(Hash) + record_type = inc_obj.class.name.demodulize.underscore + serializer = self.compute_serializer_name(inc_obj.class.name.demodulize.to_sym).to_s.constantize + end + if remaining_items(items) serializer_records = serializer.get_included_records(inc_obj, remaining_items(items), known_included_objects, fieldsets, params) included_records.concat(serializer_records) unless serializer_records.empty? diff --git a/spec/lib/object_serializer_spec.rb b/spec/lib/object_serializer_spec.rb index 236cf8d..85f4a79 100644 --- a/spec/lib/object_serializer_spec.rb +++ b/spec/lib/object_serializer_spec.rb @@ -278,10 +278,24 @@ describe FastJsonapi::ObjectSerializer do end end - it 'polymorphic throws an error that polymorphic is not supported' do + it 'polymorphic has_many: returns correct nested includes when serializable_hash is called' do options = {} options[:include] = [:groupees] - expect(-> { GroupSerializer.new([group], options)}).to raise_error(NotImplementedError) + + serializable_hash = GroupSerializer.new([group], options).serializable_hash + + persons_serialized = serializable_hash[:included].find_all { |included| included[:type] == :person }.map { |included| included[:id].to_i } + groups_serialized = serializable_hash[:included].find_all { |included| included[:type] == :group }.map { |included| included[:id].to_i } + + persons = group.groupees.find_all { |groupee| groupee.is_a?(Person) } + persons.each do |person| + expect(persons_serialized).to include(person.id) + end + + groups = group.groupees.find_all { |groupee| groupee.is_a?(Group) } + groups.each do |group| + expect(groups_serialized).to include(group.id) + end end end From 8357acd6a7aec7bab5498528d48e3812d7c8449b Mon Sep 17 00:00:00 2001 From: Orhan Toy Date: Wed, 25 Jul 2018 20:24:01 +0200 Subject: [PATCH 06/11] [ci skip] Fix punctuation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 67f9790..0038b67 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,7 @@ end ``` ### Links Per Object -Links are defined in FastJsonapi using the `link` method. By default, link are read directly from the model property of the same name.In this example, `public_url` is expected to be a property of the object being serialized. +Links are defined in FastJsonapi using the `link` method. By default, link are read directly from the model property of the same name. In this example, `public_url` is expected to be a property of the object being serialized. You can configure the method to use on the object for example a link with key `self` will get set to the value returned by a method called `url` on the movie object. From 5a70b1a686d6e7c103030be02baf81c27fb01417 Mon Sep 17 00:00:00 2001 From: Matthew Lanigan Date: Wed, 18 Jul 2018 00:02:41 -0400 Subject: [PATCH 07/11] Do not use ActiveSupport core extensions Core extensions do not play well with many other gems; especially considering that they only seem to be included for one `to_json` call, they should be avoided. --- lib/fast_jsonapi/object_serializer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index 26a4f95..183d622 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'active_support/core_ext/object' +require 'active_support/json' require 'active_support/concern' require 'active_support/inflector' require 'fast_jsonapi/attribute' @@ -65,7 +65,7 @@ module FastJsonapi end def serialized_json - self.class.to_json(serializable_hash) + ActiveSupport::JSON.encode(serializable_hash) end private From 6dc34cd4d4d75ab1805fe322693dffff7a19db36 Mon Sep 17 00:00:00 2001 From: Kenji Sakurai Date: Sat, 8 Sep 2018 23:48:44 +0900 Subject: [PATCH 08/11] Fix set_key_transform's set_type to give priority to pre-set value --- lib/fast_jsonapi/object_serializer.rb | 6 +++++- .../object_serializer_class_methods_spec.rb | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index 183d622..de01061 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -143,7 +143,11 @@ module FastJsonapi self.transform_method = mapping[transform_name.to_sym] # ensure that the record type is correctly transformed - set_type(reflected_record_type) if reflected_record_type + if record_type + set_type(record_type) + elsif reflected_record_type + set_type(reflected_record_type) + end end def run_key_transform(input) diff --git a/spec/lib/object_serializer_class_methods_spec.rb b/spec/lib/object_serializer_class_methods_spec.rb index 397ace5..c1edc0a 100644 --- a/spec/lib/object_serializer_class_methods_spec.rb +++ b/spec/lib/object_serializer_class_methods_spec.rb @@ -411,4 +411,22 @@ describe FastJsonapi::ObjectSerializer do it_behaves_like 'returning key transformed hash', :movie_type, :underscore_movie_type, :release_year end end + + describe '#set_key_transform after #set_type' do + subject(:serializable_hash) { MovieSerializer.new(movie).serializable_hash } + + before do + MovieSerializer.set_type :foo_bar + MovieSerializer.set_key_transform :camel + end + + after do + MovieSerializer.set_type :movie + MovieSerializer.transform_method = nil + end + + it 'returns correct hash which type equals transformed set_type value' do + expect(serializable_hash[:data][:type]).to eq :FooBar + end + end end From 57f09c7d71ebf9af1536623b0901e78a3af1ff1b Mon Sep 17 00:00:00 2001 From: Kenji Sakurai Date: Mon, 10 Sep 2018 10:32:53 +0900 Subject: [PATCH 09/11] Fix method order in spec after --- spec/lib/object_serializer_class_methods_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/object_serializer_class_methods_spec.rb b/spec/lib/object_serializer_class_methods_spec.rb index c1edc0a..233608e 100644 --- a/spec/lib/object_serializer_class_methods_spec.rb +++ b/spec/lib/object_serializer_class_methods_spec.rb @@ -421,8 +421,8 @@ describe FastJsonapi::ObjectSerializer do end after do - MovieSerializer.set_type :movie MovieSerializer.transform_method = nil + MovieSerializer.set_type :movie end it 'returns correct hash which type equals transformed set_type value' do From 64f7b6c50d6104dee7b7957dfd518a01bf3f2277 Mon Sep 17 00:00:00 2001 From: Kenji Sakurai Date: Sun, 16 Sep 2018 14:18:10 +0900 Subject: [PATCH 10/11] Add spec for singular and plural, so remove same checking example. --- .../object_serializer_class_methods_spec.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/spec/lib/object_serializer_class_methods_spec.rb b/spec/lib/object_serializer_class_methods_spec.rb index 233608e..347b188 100644 --- a/spec/lib/object_serializer_class_methods_spec.rb +++ b/spec/lib/object_serializer_class_methods_spec.rb @@ -416,7 +416,7 @@ describe FastJsonapi::ObjectSerializer do subject(:serializable_hash) { MovieSerializer.new(movie).serializable_hash } before do - MovieSerializer.set_type :foo_bar + MovieSerializer.set_type type_name MovieSerializer.set_key_transform :camel end @@ -425,8 +425,20 @@ describe FastJsonapi::ObjectSerializer do MovieSerializer.set_type :movie end - it 'returns correct hash which type equals transformed set_type value' do - expect(serializable_hash[:data][:type]).to eq :FooBar + context 'when sets singular type name' do + let(:type_name) { :film } + + it 'returns correct hash which type equals transformed set_type value' do + expect(serializable_hash[:data][:type]).to eq :Film + end + end + + context 'when sets plural type name' do + let(:type_name) { :films } + + it 'returns correct hash which type equals transformed set_type value' do + expect(serializable_hash[:data][:type]).to eq :Films + end end end end From fced516356fd4ccb07b1bf17810c71f2bd0cc36e Mon Sep 17 00:00:00 2001 From: Shishir Kakaraddi Date: Wed, 19 Sep 2018 20:16:32 -0700 Subject: [PATCH 11/11] transforms type for polymorphic relationships too --- lib/fast_jsonapi/object_serializer.rb | 5 +- lib/fast_jsonapi/relationship.rb | 18 +++++-- .../lib/object_serializer_polymorphic_spec.rb | 51 +++++++++++++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 spec/lib/object_serializer_polymorphic_spec.rb diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index 183d622..a5436f4 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -195,7 +195,7 @@ module FastJsonapi self.relationships_to_serialize = {} if relationships_to_serialize.nil? self.cachable_relationships_to_serialize = {} if cachable_relationships_to_serialize.nil? self.uncachable_relationships_to_serialize = {} if uncachable_relationships_to_serialize.nil? - + if !relationship.cached self.uncachable_relationships_to_serialize[relationship.name] = relationship else @@ -249,7 +249,8 @@ module FastJsonapi relationship_type: relationship_type, cached: options[:cached], polymorphic: fetch_polymorphic_option(options), - conditional_proc: options[:if] + conditional_proc: options[:if], + transform_method: @transform_method ) end diff --git a/lib/fast_jsonapi/relationship.rb b/lib/fast_jsonapi/relationship.rb index 6acc0a3..e06b07f 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, :transform_method def initialize( key:, @@ -13,7 +13,8 @@ module FastJsonapi relationship_type:, cached: false, polymorphic:, - conditional_proc: + conditional_proc:, + transform_method: ) @key = key @name = name @@ -26,6 +27,7 @@ module FastJsonapi @cached = cached @polymorphic = polymorphic @conditional_proc = conditional_proc + @transform_method = transform_method end def serialize(record, serialization_params, output_hash) @@ -68,7 +70,7 @@ module FastJsonapi def id_hash_from_record(record, record_types) # memoize the record type within the record_types dictionary, then assigning to record_type: - associated_record_type = record_types[record.class] ||= record.class.name.demodulize.underscore.to_sym + associated_record_type = record_types[record.class] ||= run_key_transform(record.class.name.demodulize.underscore) id_hash(record.id, associated_record_type) end @@ -93,5 +95,13 @@ module FastJsonapi end record.public_send(id_method_name) end + + def run_key_transform(input) + if self.transform_method.present? + input.to_s.send(*self.transform_method).to_sym + else + input.to_sym + end + end end -end \ No newline at end of file +end diff --git a/spec/lib/object_serializer_polymorphic_spec.rb b/spec/lib/object_serializer_polymorphic_spec.rb new file mode 100644 index 0000000..f889141 --- /dev/null +++ b/spec/lib/object_serializer_polymorphic_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe FastJsonapi::ObjectSerializer do + class List + attr_accessor :id, :name, :items + end + + class ChecklistItem + attr_accessor :id, :name + end + + class Car + attr_accessor :id, :model, :year + end + + class ListSerializer + include FastJsonapi::ObjectSerializer + set_type :list + attributes :name + set_key_transform :dash + has_many :items, polymorphic: true + end + + let(:car) do + car = Car.new + car.id = 1 + car.model = 'Toyota Corolla' + car.year = 1987 + car + end + + let(:checklist_item) do + checklist_item = ChecklistItem.new + checklist_item.id = 2 + checklist_item.name = 'Do this action!' + checklist_item + end + + context 'when serializing id and type of polymorphic relationships' do + it 'should return correct type when transform_method is specified' do + list = List.new + list.id = 1 + list.items = [checklist_item, car] + list_hash = ListSerializer.new(list).to_hash + record_type = list_hash[:data][:relationships][:items][:data][0][:type] + expect(record_type).to eq 'checklist-item'.to_sym + record_type = list_hash[:data][:relationships][:items][:data][1][:type] + expect(record_type).to eq 'car'.to_sym + end + end +end