Sitelet https://github.com/jsonapi-serializer/jsonapi-serializer/pull/141/files
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 15 additions & 28 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ require:
- rubocop-performance
- rubocop-rspec

AllCops:
NewCops: enable

Style/FrozenStringLiteralComment:
Enabled: false

Expand Down Expand Up @@ -38,41 +41,25 @@ Performance/TimesMap:
Exclude:
- 'spec/**/**.rb'

# TODO: Fix these...
Style/Documentation:
Metrics/ModuleLength:
Enabled: false

Style/GuardClause:
Exclude:
- 'lib/**/**.rb'

Style/ConditionalAssignment:
Exclude:
- 'lib/**/**.rb'

Style/IfUnlessModifier:
Exclude:
- 'lib/**/**.rb'

Lint/AssignmentInCondition:
Exclude:
- 'lib/**/**.rb'

Metrics:
Metrics/BlockLength:
Exclude:
- 'lib/**/**.rb'
- 'spec/**/**.rb'

Metrics/BlockLength:
Metrics/MethodLength:
Enabled: false

Layout/LineLength:
Exclude:
- 'lib/**/**.rb'
Metrics/CyclomaticComplexity:
Max: 12

Naming/PredicateName:
Exclude:
- 'lib/**/**.rb'
Metrics/PerceivedComplexity:
Max: 12

Metrics/AbcSize:
Max: 36

Naming/AccessorMethodName:
Exclude:
- 'lib/**/**.rb'
- '**/**/dsl.rb'
5 changes: 2 additions & 3 deletions jsonapi-serializer.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ Gem::Specification.new do |gem|
gem.require_paths = ['lib']
gem.extra_rdoc_files = ['LICENSE.txt', 'README.md']

gem.add_runtime_dependency('activesupport', '>= 4.2')

gem.add_development_dependency('activerecord')
gem.add_development_dependency('dry-inflector')
gem.add_development_dependency('bundler')
gem.add_development_dependency('byebug')
gem.add_development_dependency('ffaker')
Expand All @@ -33,4 +31,5 @@ Gem::Specification.new do |gem|
gem.add_development_dependency('rubocop-rspec')
gem.add_development_dependency('simplecov')
gem.add_development_dependency('sqlite3')
gem.add_development_dependency('activesupport')
end
61 changes: 58 additions & 3 deletions lib/jsonapi/serializer.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,67 @@
require 'fast_jsonapi'
require 'jsonapi/serializer/base'
require 'jsonapi/serializer/core'
require 'jsonapi/serializer/dsl'
require 'jsonapi/serializer/errors'
require 'jsonapi/serializer/trackable'

# Provides JSONAPI related functionality
module JSONAPI
# Provides JSONAPI serialization functionality
module Serializer
# TODO: Move and cleanup the old implementation...
extend Trackable

# Self registers any inherited/extended class to keep track of it
#
# @return nothing
def self.included(base)
super

register_serializer(base)

base.class_eval do
include FastJsonapi::ObjectSerializer
include ::JSONAPI::Serializer::Base
extend ::JSONAPI::Serializer::DSL
extend ::JSONAPI::Serializer::Core
end
end

# Serializes an object or a collection
#
# The `options` are passed to the serializer instance and follow the
# same purpose.
#
# The only extra option is the `options[:serializers]`
# one can use to pass a mapping of object to serializer classes to
# be strict about how each object is serialized.
#
# @param object_or_collection [Object] to be serialized
# @param options [Hash] serialization parameters
# @return [Hash] of serialized JSONAPI data
def self.serialize(object_or_collection, options: nil)
options = options.dup || {}
serializers = options.delete(:serializers)
is_col = options[:is_collection] = collection?(
object_or_collection, force: options[:is_collection]
)

serializer = for_object(object_or_collection.first, serializers) if is_col
serializer ||= for_object(object_or_collection, serializers)

serializer.new(object_or_collection, options).serializable_hash
end

# Detects a collection/enumerable
#
# @param resource [Object] to detect
# @return [TrueClass] on a successful detection
def self.collection?(resource, force: nil)
return force unless force.nil?

# Rails 4 does not use [Enumerable]...
active_record = defined?(ActiveRecord::Relation)
return true if active_record && resource.is_a?(ActiveRecord::Relation)

resource.is_a?(Enumerable) && !resource.respond_to?(:each_pair)
end
end
end
53 changes: 53 additions & 0 deletions lib/jsonapi/serializer/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

module JSONAPI
module Serializer
# Our serializer PORO functionality
module Base
def initialize(resource, opts = {})
@resource = resource
@options = opts.dup
@params = @options.delete(:params) || {}
@fieldsets = @options.delete(:fields) || {}
@includes = @options.delete(:include) || []
@include = @includes.map(&:to_s).map(&:strip).reject(&:empty?)
end

def serializable_hash
is_collection = ::JSONAPI::Serializer.collection?(
@resource, force: @options[:is_collection]
)

jsonapi = { data: nil }
jsonapi[:data] = [] if is_collection
jsonapi[:meta] = @options[:meta] if @options[:meta].is_a?(Hash)
jsonapi[:links] = @options[:links] if @options[:links].is_a?(Hash)

return jsonapi if @resource.nil? || (is_collection && @resource.empty?)

data = []
included = []

# Used to avoid including duplicate records...
included_oids = Set.new

Array(@resource).each do |record|
serializer_class = self.class unless is_collection
serializer_class ||= JSONAPI::Serializer.for_object(record)

fieldset = @fieldsets[serializer_class.record_type]
data << serializer_class.record_hash(record, fieldset, @params)

included += serializer_class.record_includes(
record, @includes, included_oids, @fieldsets, @params
)
end

jsonapi[:data] = data
jsonapi[:data] = data.first unless is_collection
jsonapi[:included] = included unless @includes.empty?
jsonapi
end
end
end
end
Loading