diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index c33465f..7ce418c 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -221,7 +221,8 @@ module FastJsonapi serializer: compute_serializer_name(options[:serializer] || base_key_sym), relationship_type: relationship_type, cached: options[:cached] || false, - polymorphic: fetch_polymorphic_option(options) + polymorphic: fetch_polymorphic_option(options), + conditional_proc: options[:if] } end diff --git a/lib/fast_jsonapi/serialization_core.rb b/lib/fast_jsonapi/serialization_core.rb index 27da6af..f02c2c4 100644 --- a/lib/fast_jsonapi/serialization_core.rb +++ b/lib/fast_jsonapi/serialization_core.rb @@ -82,11 +82,14 @@ module FastJsonapi relationships = relationships_to_serialize if relationships.nil? relationships.each_with_object({}) do |(_k, relationship), hash| - name = relationship[:key] - empty_case = relationship[:relationship_type] == :has_many ? [] : nil - hash[name] = { - data: ids_hash_from_record_and_relationship(record, relationship, params) || empty_case - } + conditional_proc = relationship[:conditional_proc] + if conditional_proc.blank? || conditional_proc.call(record, params) + name = relationship[:key] + empty_case = relationship[:relationship_type] == :has_many ? [] : nil + hash[name] = { + data: ids_hash_from_record_and_relationship(record, relationship, params) || empty_case + } + end end end diff --git a/spec/lib/object_serializer_spec.rb b/spec/lib/object_serializer_spec.rb index 46d0cea..7338047 100644 --- a/spec/lib/object_serializer_spec.rb +++ b/spec/lib/object_serializer_spec.rb @@ -341,4 +341,33 @@ describe FastJsonapi::ObjectSerializer do expect(serializable_hash['data']['attributes'].has_key?('director')).to be_falsey end end + + context 'when optional relationships are determined by record data' do + it 'returns optional relationship when relationship is included' do + json = MovieOptionalRelationshipSerializer.new(movie).serialized_json + serializable_hash = JSON.parse(json) + expect(serializable_hash['data']['relationships'].has_key?('actors')).to be_truthy + end + + it "doesn't return optional relationship when relationship is not included" do + movie.actor_ids = [] + json = MovieOptionalRelationshipSerializer.new(movie).serialized_json + serializable_hash = JSON.parse(json) + expect(serializable_hash['data']['relationships'].has_key?('actors')).to be_falsey + end + end + + context 'when optional relationships are determined by params data' do + it 'returns optional relationship when relationship is included' do + json = MovieOptionalRelationshipWithParamsSerializer.new(movie, { params: { admin: true }}).serialized_json + serializable_hash = JSON.parse(json) + expect(serializable_hash['data']['relationships'].has_key?('actors')).to be_truthy + end + + it "doesn't return optional relationship when relationship is not included" do + json = MovieOptionalRelationshipWithParamsSerializer.new(movie, { params: { admin: false }}).serialized_json + serializable_hash = JSON.parse(json) + expect(serializable_hash['data']['relationships'].has_key?('actors')).to be_falsey + end + end end diff --git a/spec/shared/contexts/movie_context.rb b/spec/shared/contexts/movie_context.rb index 4df6a91..6a5693e 100644 --- a/spec/shared/contexts/movie_context.rb +++ b/spec/shared/contexts/movie_context.rb @@ -292,6 +292,20 @@ RSpec.shared_context 'movie class' do attributes :name attribute :director, if: Proc.new { |record, params| params && params[:admin] == true } end + + class MovieOptionalRelationshipSerializer + include FastJsonapi::ObjectSerializer + set_type :movie + attributes :name + has_many :actors, if: Proc.new { |record| record.actors.any? } + end + + class MovieOptionalRelationshipWithParamsSerializer + include FastJsonapi::ObjectSerializer + set_type :movie + attributes :name + has_many :actors, if: Proc.new { |record, params| params && params[:admin] == true } + end end