From 32b9aedb606d38afb42986349459971a17a2cd01 Mon Sep 17 00:00:00 2001 From: Brad Grzesiak Date: Fri, 13 Sep 2019 08:58:38 -0500 Subject: [PATCH] Allow "if: Proc..." on link --- lib/fast_jsonapi/attribute.rb | 30 ++----------------- lib/fast_jsonapi/link.rb | 19 ++---------- lib/fast_jsonapi/object_serializer.rb | 11 +++++-- lib/fast_jsonapi/scalar.rb | 29 ++++++++++++++++++ .../object_serializer_class_methods_spec.rb | 20 +++++++++++++ spec/shared/contexts/movie_context.rb | 7 +++++ 6 files changed, 70 insertions(+), 46 deletions(-) create mode 100644 lib/fast_jsonapi/scalar.rb diff --git a/lib/fast_jsonapi/attribute.rb b/lib/fast_jsonapi/attribute.rb index 9acc3e09..20bbc5ed 100644 --- a/lib/fast_jsonapi/attribute.rb +++ b/lib/fast_jsonapi/attribute.rb @@ -1,29 +1,5 @@ -module FastJsonapi - class Attribute - attr_reader :key, :method, :conditional_proc - - def initialize(key:, method:, options: {}) - @key = key - @method = method - @conditional_proc = options[:if] - end +require 'fast_jsonapi/scalar' - def serialize(record, serialization_params, output_hash) - if include_attribute?(record, serialization_params) - output_hash[key] = if method.is_a?(Proc) - method.arity.abs == 1 ? method.call(record) : method.call(record, serialization_params) - else - record.public_send(method) - end - end - end - - def include_attribute?(record, serialization_params) - if conditional_proc.present? - conditional_proc.call(record, serialization_params) - else - true - end - end - end +module FastJsonapi + class Attribute < Scalar; end end diff --git a/lib/fast_jsonapi/link.rb b/lib/fast_jsonapi/link.rb index 41f84c2f..fa4fff1d 100644 --- a/lib/fast_jsonapi/link.rb +++ b/lib/fast_jsonapi/link.rb @@ -1,18 +1,5 @@ -module FastJsonapi - class Link - attr_reader :key, :method - - def initialize(key:, method:) - @key = key - @method = method - end +require 'fast_jsonapi/scalar' - def serialize(record, serialization_params, output_hash) - output_hash[key] = if method.is_a?(Proc) - method.arity == 1 ? method.call(record) : method.call(record, serialization_params) - else - record.public_send(method) - end - end - end +module FastJsonapi + class Link < Scalar; end end diff --git a/lib/fast_jsonapi/object_serializer.rb b/lib/fast_jsonapi/object_serializer.rb index c161fb6b..218f616d 100644 --- a/lib/fast_jsonapi/object_serializer.rb +++ b/lib/fast_jsonapi/object_serializer.rb @@ -285,14 +285,19 @@ def fetch_polymorphic_option(options) {} end - def link(link_name, link_method_name = nil, &block) + # def link(link_name, link_method_name = nil, &block) + def link(*params, &block) self.data_links = {} if self.data_links.nil? - link_method_name = link_name if link_method_name.nil? + + options = params.last.is_a?(Hash) ? params.pop : {} + link_name = params.first + link_method_name = params[-1] key = run_key_transform(link_name) self.data_links[key] = Link.new( key: key, - method: block || link_method_name + method: block || link_method_name, + options: options ) end diff --git a/lib/fast_jsonapi/scalar.rb b/lib/fast_jsonapi/scalar.rb new file mode 100644 index 00000000..27d081c6 --- /dev/null +++ b/lib/fast_jsonapi/scalar.rb @@ -0,0 +1,29 @@ +module FastJsonapi + class Scalar + attr_reader :key, :method, :conditional_proc + + def initialize(key:, method:, options: {}) + @key = key + @method = method + @conditional_proc = options[:if] + end + + def serialize(record, serialization_params, output_hash) + if conditionally_allowed?(record, serialization_params) + output_hash[key] = if method.is_a?(Proc) + method.arity.abs == 1 ? method.call(record) : method.call(record, serialization_params) + else + record.public_send(method) + end + end + end + + def conditionally_allowed?(record, serialization_params) + if conditional_proc.present? + conditional_proc.call(record, serialization_params) + else + true + end + end + end +end diff --git a/spec/lib/object_serializer_class_methods_spec.rb b/spec/lib/object_serializer_class_methods_spec.rb index 6fe4718b..5fea112f 100644 --- a/spec/lib/object_serializer_class_methods_spec.rb +++ b/spec/lib/object_serializer_class_methods_spec.rb @@ -400,6 +400,26 @@ def year_since_release_calculator(release_year) expect(action_serializable_hash[:data][:links][:url]).to eq "/action-movie/#{movie.id}" end end + + describe 'optional links' do + subject(:downloadable_serializable_hash) { OptionalDownloadableMovieSerializer.new(movie, params).serializable_hash } + + context 'when the link is provided' do + let(:params) { { params: { signed_url: signed_url } } } + let(:signed_url) { 'http://example.com/download_link?signature=abcdef' } + + it 'includes the link' do + expect(downloadable_serializable_hash[:data][:links][:download]).to eq signed_url + end + end + + context 'when the link is not provided' do + let(:params) { { params: {} } } + it 'does not include the link' do + expect(downloadable_serializable_hash[:data][:links]).to_not have_key(:download) + end + end + end end describe '#key_transform' do diff --git a/spec/shared/contexts/movie_context.rb b/spec/shared/contexts/movie_context.rb index df0c3950..9b3a4f67 100644 --- a/spec/shared/contexts/movie_context.rb +++ b/spec/shared/contexts/movie_context.rb @@ -197,6 +197,12 @@ class HorrorMovieSerializer < GenreMovieSerializer link(:url) { |object| "/horror-movie/#{object.id}" } end + class OptionalDownloadableMovieSerializer < MovieSerializer + link(:download, if: Proc.new { |record, params| params && params[:signed_url] }) do |movie, params| + params[:signed_url] + end + end + class MovieWithoutIdStructSerializer include FastJsonapi::ObjectSerializer attributes :name, :release_year @@ -385,6 +391,7 @@ class MovieSerializer ActionMovieSerializer GenreMovieSerializer HorrorMovieSerializer + OptionalDownloadableMovieSerializer Movie MovieSerializer Actor