mirror of
https://github.com/samsonjs/grape-active_model_serializers.git
synced 2026-03-25 08:45:55 +00:00
Merge pull request #59 from drn/refactor
Refactor option and serializer resolution.
This commit is contained in:
commit
f76ec6dcff
6 changed files with 129 additions and 79 deletions
|
|
@ -2,4 +2,6 @@ require 'active_model_serializers'
|
|||
require 'grape'
|
||||
require 'grape-active_model_serializers/endpoint_extension'
|
||||
require 'grape-active_model_serializers/formatter'
|
||||
require 'grape-active_model_serializers/serializer_resolver'
|
||||
require 'grape-active_model_serializers/options_builder'
|
||||
require 'grape-active_model_serializers/version'
|
||||
|
|
|
|||
|
|
@ -11,80 +11,20 @@ module Grape
|
|||
serializer, options
|
||||
).to_json
|
||||
else
|
||||
Grape::Formatter::Json.call resource, env
|
||||
Grape::Formatter::Json.call(resource, env)
|
||||
end
|
||||
end
|
||||
|
||||
def build_options(resource, env)
|
||||
endpoint = env['api.endpoint']
|
||||
options = build_options_from_endpoint(endpoint)
|
||||
|
||||
options[:scope] = endpoint unless options.key?(:scope)
|
||||
|
||||
# ensure we have a root to fallback on
|
||||
if resource.respond_to?(:to_ary) && !options.key?(:root)
|
||||
options[:root] = default_root(endpoint)
|
||||
end
|
||||
|
||||
options.merge(meta_options(env))
|
||||
Grape::ActiveModelSerializers::OptionsBuilder.new(
|
||||
resource, env
|
||||
).options
|
||||
end
|
||||
|
||||
def fetch_serializer(resource, options)
|
||||
# use serializer specified by options
|
||||
serializer = options[:serializer]
|
||||
|
||||
if serializer.nil?
|
||||
# fetch serializer leverage AMS lookup
|
||||
serializer = ActiveModel::Serializer.serializer_for(resource)
|
||||
# if grape version exists, attempt to apply version namespacing
|
||||
serializer = namespace_serializer(serializer, options[:version])
|
||||
end
|
||||
|
||||
return nil unless serializer
|
||||
|
||||
serializer.new(resource, options)
|
||||
end
|
||||
|
||||
def namespace_serializer(serializer, namespace)
|
||||
"#{namespace.try(:classify)}::#{serializer}".constantize
|
||||
rescue NameError
|
||||
serializer
|
||||
end
|
||||
|
||||
def meta_options(env)
|
||||
options = {}
|
||||
ams_meta = env['ams_meta'] || {}
|
||||
meta = ams_meta.delete(:meta)
|
||||
meta_key = ams_meta.delete(:meta_key)
|
||||
options[:meta_key] = meta_key if meta && meta_key
|
||||
options[:meta] = meta if meta
|
||||
options
|
||||
end
|
||||
|
||||
def build_options_from_endpoint(endpoint)
|
||||
[
|
||||
endpoint.default_serializer_options || {},
|
||||
endpoint.namespace_options,
|
||||
endpoint.route_options,
|
||||
endpoint.options,
|
||||
endpoint.options.fetch(:route_options)
|
||||
].reduce(:merge)
|
||||
end
|
||||
|
||||
# array root is the innermost namespace name ('space') if there is one,
|
||||
# otherwise the route name (e.g. get 'name')
|
||||
def default_root(endpoint)
|
||||
innermost_scope = if endpoint.respond_to?(:namespace_stackable)
|
||||
endpoint.namespace_stackable(:namespace).last
|
||||
else
|
||||
endpoint.settings.peek[:namespace]
|
||||
end
|
||||
|
||||
if innermost_scope
|
||||
innermost_scope.space
|
||||
else
|
||||
endpoint.options[:path][0].to_s.split('/')[-1]
|
||||
end
|
||||
Grape::ActiveModelSerializers::SerializerResolver.new(
|
||||
resource, options
|
||||
).serializer
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
68
lib/grape-active_model_serializers/options_builder.rb
Normal file
68
lib/grape-active_model_serializers/options_builder.rb
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
module Grape
|
||||
module ActiveModelSerializers
|
||||
class OptionsBuilder
|
||||
def initialize(resource, env)
|
||||
self.resource = resource
|
||||
self.env = env
|
||||
end
|
||||
|
||||
def options
|
||||
@options ||= (
|
||||
options = endpoint_options
|
||||
options.merge!(scope: endpoint) unless options.key?(:scope)
|
||||
options.merge!(default_root_options) unless options.key?(:root)
|
||||
options.merge!(meta_options)
|
||||
options
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :resource, :env
|
||||
|
||||
def endpoint_options
|
||||
[
|
||||
endpoint.default_serializer_options || {},
|
||||
endpoint.namespace_options,
|
||||
endpoint.route_options,
|
||||
endpoint.options,
|
||||
endpoint.options.fetch(:route_options)
|
||||
].reduce(:merge)
|
||||
end
|
||||
|
||||
def endpoint
|
||||
@endpoint ||= env['api.endpoint']
|
||||
end
|
||||
|
||||
# array root is the innermost namespace name ('space') if there is one,
|
||||
# otherwise the route name (e.g. get 'name')
|
||||
def default_root_options
|
||||
return {} unless resource.respond_to?(:to_ary)
|
||||
|
||||
if innermost_scope
|
||||
{ root: innermost_scope.space }
|
||||
else
|
||||
{ root: endpoint.options[:path].first.to_s.split('/').last }
|
||||
end
|
||||
end
|
||||
|
||||
def innermost_scope
|
||||
if endpoint.respond_to?(:namespace_stackable)
|
||||
endpoint.namespace_stackable(:namespace).last
|
||||
else
|
||||
endpoint.settings.peek[:namespace]
|
||||
end
|
||||
end
|
||||
|
||||
def meta_options
|
||||
options = {}
|
||||
ams_meta = env['ams_meta'] || {}
|
||||
meta = ams_meta[:meta]
|
||||
meta_key = ams_meta[:meta_key]
|
||||
options[:meta] = meta if meta
|
||||
options[:meta_key] = meta_key if meta && meta_key
|
||||
options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
42
lib/grape-active_model_serializers/serializer_resolver.rb
Normal file
42
lib/grape-active_model_serializers/serializer_resolver.rb
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
module Grape
|
||||
module ActiveModelSerializers
|
||||
class SerializerResolver
|
||||
def initialize(resource, options)
|
||||
self.resource = resource
|
||||
self.options = options
|
||||
end
|
||||
|
||||
def serializer
|
||||
@serializer ||= (
|
||||
serializer_klass.new(resource, options) if serializer_klass
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :resource, :options
|
||||
|
||||
def serializer_klass
|
||||
serializer_klass = options[:serializer]
|
||||
serializer_klass ||= namespaced_resource_serializer_klass
|
||||
serializer_klass
|
||||
end
|
||||
|
||||
def namespaced_resource_serializer_klass
|
||||
"#{namespace}::#{resource_serializer_klass}".constantize
|
||||
rescue NameError
|
||||
resource_serializer_klass
|
||||
end
|
||||
|
||||
def namespace
|
||||
options[:version].try(:classify)
|
||||
end
|
||||
|
||||
def resource_serializer_klass
|
||||
@resource_serializer_klass ||= ActiveModel::Serializer.serializer_for(
|
||||
resource
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -18,10 +18,11 @@ describe Grape::Formatter::ActiveModelSerializers do
|
|||
end
|
||||
end
|
||||
|
||||
let(:env) { { 'api.endpoint' => app.endpoints.first } }
|
||||
let(:options) { described_class.build_options(nil, env) }
|
||||
|
||||
it 'should read serializer options like "root"' do
|
||||
expect(
|
||||
described_class.build_options_from_endpoint(app.endpoints.first)
|
||||
).to include(:root)
|
||||
expect(options).to include(:root)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -65,9 +66,7 @@ describe Grape::Formatter::ActiveModelSerializers do
|
|||
end
|
||||
|
||||
it 'should read serializer options like "root"' do
|
||||
expect(
|
||||
described_class.build_options_from_endpoint(endpoint).keys
|
||||
).to include(:root)
|
||||
expect(options).to include(:root)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,10 +26,11 @@ describe Grape::Formatter::ActiveModelSerializers do
|
|||
end
|
||||
end
|
||||
|
||||
let(:env) { { 'api.endpoint' => app.endpoints.first } }
|
||||
let(:options) { described_class.build_options(nil, env) }
|
||||
|
||||
it 'should read serializer options like "root"' do
|
||||
expect(
|
||||
described_class.build_options_from_endpoint(app.endpoints.first)
|
||||
).to include(:root)
|
||||
expect(options).to include(:root)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -72,9 +73,7 @@ describe Grape::Formatter::ActiveModelSerializers do
|
|||
end
|
||||
|
||||
it 'should read serializer options like "root"' do
|
||||
expect(
|
||||
described_class.build_options_from_endpoint(endpoint).keys
|
||||
).to include(:root)
|
||||
expect(options).to include(:root)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue