Skip to content

Commit

Permalink
Add v0.9 compatibility adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
pravi committed Sep 22, 2020
1 parent a1aa5a2 commit b2857ee
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 13 deletions.
2 changes: 1 addition & 1 deletion app/serializers/export/aspect_serializer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Export
class AspectSerializer < ActiveModel::Serializer
class AspectSerializer < AMS::V09::Serializer
attributes :name
end
end
2 changes: 1 addition & 1 deletion app/serializers/export/contact_serializer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Export
class ContactSerializer < ActiveModel::Serializer
class ContactSerializer < AMS::V09::Serializer
attributes :sharing,
:receiving,
:following,
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/export/others_data_serializer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Export
class OthersDataSerializer < ActiveModel::Serializer
class OthersDataSerializer < AMS::V09::Serializer
# Relayables of other people in the archive: comments, likes, participations, poll participations where author is
# the archive owner
has_many :relayables, serializer: FlatMapArraySerializer, each_serializer: FederationEntitySerializer
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/export/user_serializer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Export
class UserSerializer < ActiveModel::Serializer
class UserSerializer < AMS::V09::Serializer
attributes :username,
:email,
:language,
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/federation_entity_serializer.rb
Expand Up @@ -3,7 +3,7 @@
# This is an ActiveModel::Serializer based class which uses DiasporaFederation::Entity JSON serialization
# features in order to serialize local DB objects. To determine a type of entity class to use the same routines
# are used as for federation messages generation.
class FederationEntitySerializer < ActiveModel::Serializer
class FederationEntitySerializer < AMS::V09::Serializer
include SerializerPostProcessing

private
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/flat_map_array_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true

class FlatMapArraySerializer < ActiveModel::ArraySerializer
class FlatMapArraySerializer < ActiveModelSerializers::SerializableResource
def serializable_object(options={})
@object.flat_map do |subarray|
subarray.map do |item|
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/notification_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true

class NotificationSerializer < ActiveModel::Serializer
class NotificationSerializer < AMS::V09::Serializer
attributes :id,
:target_type,
:target_id,
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/user_info_serializer.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true

class UserInfoSerializer < ActiveModel::Serializer
class UserInfoSerializer < AMS::V09::Serializer
attributes :sub, :name, :nickname, :profile, :picture

def sub
Expand Down
166 changes: 166 additions & 0 deletions config/initializers/active_model_serializers.rb
@@ -0,0 +1,166 @@
module AMS
module V09
class Serializer < ActiveModel::Serializer

def serializable_hash(adapter_options = nil,
options = {},
adapter_instance = self.class.serialization_adapter_instance)
object.nil? ? nil : super
end
end

class ArraySerializer < ActiveModel::Serializer::CollectionSerializer
end

class ResourceIdentifier < ActiveModelSerializers::Adapter::JsonApi::ResourceIdentifier

def initialize(serializer, options)
@id = id_for(serializer)
@type = type_for(serializer)
end

private

def id_for(serializer)
serializer.read_attribute_for_serialization(:id)
end

end

class Base < ActiveModelSerializers::Adapter::Base

def initialize(serializer, options = {})
super
@fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields))
end

private

attr_reader :fieldset

def attributes_for(serializer, fields)
serializer.attributes(fields).except(:id)
end

def resource_object_for(serializer)
resource_object = serializer.fetch(self) do
resource_object = ResourceIdentifier.new(serializer, instance_options).as_json

requested_fields = fieldset && fieldset.fields_for(resource_object[:type])
attributes = attributes_for(serializer, requested_fields)
resource_object.merge!(attributes) if attributes.any?
resource_object
end

resource_object
end

end

# represent resource without associations
class Attributes < Base

def serializable_hash(options = nil)
return nil if serializer.nil? || serializer.object.nil?

is_collection = serializer.respond_to?(:each)
serializers = is_collection ? serializer : [serializer]
data = resource_objects_for(serializers)

result = is_collection ? data : data[0]

self.class.transform_key_casing!(result, instance_options)
end

private

def resource_objects_for(serializers)
serializers.map { |serializer| resource_object_for(serializer) }
end

end

class AttributesWithIncluded < Base

def serializable_hash(options = nil)
return {} if serializer.object.nil?

is_collection = serializer.respond_to?(:each)
serializers = is_collection ? serializer : [serializer]
primary_data, included = resource_objects_for(serializers)

hash = {}
hash[root] = is_collection ? primary_data : primary_data[0]
hash[:included] = included if included.any?
hash[meta_key] = meta unless meta.blank?

self.class.transform_key_casing!(hash, instance_options)
end

private

def resource_objects_for(serializers)
@primary = []
@included = {}
@resource_identifiers = Set.new
serializers.each { |serializer| process_resource(serializer) }
serializers.each { |serializer| process_relationships(serializer) }

[@primary, @included]
end

def process_resource(serializer)
return false unless resource_already_processed?(serializer)

@primary << resource_object_for(serializer)
true
end

def process_relationship_resource(serializer, json_key)
return false unless resource_already_processed?(serializer)

@included[json_key] << resource_object_for(serializer)
true
end

def process_relationships(serializer)
serializer.associations.each do |association|
process_relationship(association.serializer, association.key)
end
end

def process_relationship(serializer, key)
json_key = key || serializer.json_key.to_s.pluralize
@included[json_key] ||= []

if serializer.respond_to?(:each)
serializer.each { |s| process_relationship(s, key) }
return
end
return unless serializer && serializer.object
return unless process_relationship_resource(serializer, json_key)

process_relationships(serializer)
end

def resource_already_processed?(serializer)
resource_identifier = ResourceIdentifier.new(serializer, instance_options).as_json
@resource_identifiers.add?(resource_identifier)
end

def meta
instance_options.fetch(:meta, nil)
end

def meta_key
instance_options.fetch(:meta_key, 'meta'.freeze)
end

end

end
end

ActiveModelSerializers::Adapter.register :v09_attributes_with_included, AMS::V09::AttributesWithIncluded
ActiveModelSerializers::Adapter.register :v09_attributes, AMS::V09::Attributes
ActiveModelSerializers.config.adapter = :v09_attributes_with_included
6 changes: 3 additions & 3 deletions spec/serializers/serializer_post_processing_spec.rb
Expand Up @@ -2,8 +2,8 @@

describe SerializerPostProcessing do
describe "#modify_serializable_object" do
it "allows to modify serializable object of ActiveModel::Serializer ancestor" do
class TestSerializer < ActiveModel::Serializer
it "allows to modify serializable object of AMS::V09::Serializer ancestor" do
class TestSerializer < AMS::V09::Serializer
include SerializerPostProcessing

def modify_serializable_object(*)
Expand All @@ -21,7 +21,7 @@ def modify_serializable_object(*)

describe "#except" do
it "allows to except a key from attributes" do
class TestSerializer2 < ActiveModel::Serializer
class TestSerializer2 < AMS::V09::Serializer
include SerializerPostProcessing

attributes :key_to_exclude
Expand Down
4 changes: 2 additions & 2 deletions spec/support/serializer_matchers.rb
Expand Up @@ -72,7 +72,7 @@ def serializer_class
def pick_serializer_class
return association_serializer_class unless association_serializer_class.nil?
return @serializer_from_options unless @serializer_from_options.nil?
return ActiveModel::ArraySerializer unless each_serializer_class.nil?
return ActiveModelSerializers::SerializableResource unless each_serializer_class.nil?
end
end

Expand All @@ -82,6 +82,6 @@ def pick_serializer_class
# NOTE: this matcher uses knowledge of AMS internals
RSpec::Matchers.define :serialize_each_with do |expected|
match do |actual|
actual.is_a?(ActiveModel::ArraySerializer) && actual.instance_variable_get("@each_serializer") == expected
actual.is_a?(ActiveModelSerializers::SerializableResource) && actual.instance_variable_get("@each_serializer") == expected
end
end

0 comments on commit b2857ee

Please sign in to comment.