Allow conditional attributes

This commit is contained in:
Trevor Hinesley 2018-06-21 14:50:51 -05:00 committed by Shishir Kakaraddi
parent 44d5e0f9c5
commit bad004fd42
4 changed files with 64 additions and 2 deletions

View File

@ -149,13 +149,20 @@ module FastJsonapi
def attributes(*attributes_list, &block)
attributes_list = attributes_list.first if attributes_list.first.class.is_a?(Array)
options = attributes_list.last.is_a?(Hash) ? attributes_list.pop : {}
self.attributes_to_serialize = {} if self.attributes_to_serialize.nil?
self.optional_attributes_to_serialize = {} if self.optional_attributes_to_serialize.nil?
attributes_list.each do |attr_name|
method_name = attr_name
key = run_key_transform(method_name)
if options[:if].present?
optional_attributes_to_serialize[key] = [method_name, options[:if]]
else
attributes_to_serialize[key] = block || method_name
end
end
end
alias_method :attribute, :attributes

View File

@ -12,6 +12,7 @@ module FastJsonapi
included do
class << self
attr_accessor :attributes_to_serialize,
:optional_attributes_to_serialize,
:relationships_to_serialize,
:cachable_relationships_to_serialize,
:uncachable_relationships_to_serialize,
@ -73,13 +74,21 @@ module FastJsonapi
end
def attributes_hash(record, params = {})
attributes_to_serialize.each_with_object({}) do |(key, method), attr_hash|
attributes = attributes_to_serialize.each_with_object({}) do |(key, method), attr_hash|
attr_hash[key] = if method.is_a?(Proc)
method.arity == 1 ? method.call(record) : method.call(record, params)
else
record.public_send(method)
end
end
self.optional_attributes_to_serialize = {} if self.optional_attributes_to_serialize.nil?
optional_attributes_to_serialize.each do |key, details|
method_name, check_proc = details
attributes[key] = record.send(method_name) if check_proc.call(record, params)
end
attributes
end
def relationships_hash(record, relationships = nil, params = {})

View File

@ -309,4 +309,36 @@ describe FastJsonapi::ObjectSerializer do
expect(serializable_hash[:included][0][:links][:self]).to eq url
end
end
context 'when optional attributes are determined by record data' do
it 'returns optional attribute when attribute is included' do
movie.release_year = 2001
json = MovieOptionalRecordDataSerializer.new(movie).serialized_json
serializable_hash = JSON.parse(json)
expect(serializable_hash['data']['attributes']['release_year']).to eq movie.release_year
end
it "doesn't return optional attribute when attribute is not included" do
movie.release_year = 1970
json = MovieOptionalRecordDataSerializer.new(movie).serialized_json
serializable_hash = JSON.parse(json)
expect(serializable_hash['data']['attributes'].has_key?('release_year')).to be_falsey
end
end
context 'when optional attributes are determined by params data' do
it 'returns optional attribute when attribute is included' do
movie.director = 'steven spielberg'
json = MovieOptionalParamsDataSerializer.new(movie, { params: { admin: true }}).serialized_json
serializable_hash = JSON.parse(json)
expect(serializable_hash['data']['attributes']['director']).to eq 'steven spielberg'
end
it "doesn't return optional attribute when attribute is not included" do
movie.director = 'steven spielberg'
json = MovieOptionalParamsDataSerializer.new(movie, { params: { admin: false }}).serialized_json
serializable_hash = JSON.parse(json)
expect(serializable_hash['data']['attributes'].has_key?('director')).to be_falsey
end
end
end

View File

@ -278,6 +278,20 @@ RSpec.shared_context 'movie class' do
set_type :account
belongs_to :supplier
end
class MovieOptionalRecordDataSerializer
include FastJsonapi::ObjectSerializer
set_type :movie
attributes :name
attribute :release_year, if: Proc.new { |record| record.release_year >= 2000 }
end
class MovieOptionalParamsDataSerializer
include FastJsonapi::ObjectSerializer
set_type :movie
attributes :name
attribute :director, if: Proc.new { |record, params| params && params[:admin] == true }
end
end