diff --git a/lib/panko/serializer.rb b/lib/panko/serializer.rb index 159f183..23209a5 100644 --- a/lib/panko/serializer.rb +++ b/lib/panko/serializer.rb @@ -75,7 +75,7 @@ def method_added(method) def has_one(name, options = {}) serializer_const = options[:serializer] - serializer_const = Panko::SerializerResolver.resolve(name.to_s) if serializer_const.nil? + serializer_const = Panko::SerializerResolver.resolve(name.to_s, self) if serializer_const.nil? raise "Can't find serializer for #{self.name}.#{name} has_one relationship." if serializer_const.nil? @@ -88,7 +88,7 @@ def has_one(name, options = {}) def has_many(name, options = {}) serializer_const = options[:serializer] || options[:each_serializer] - serializer_const = Panko::SerializerResolver.resolve(name.to_s) if serializer_const.nil? + serializer_const = Panko::SerializerResolver.resolve(name.to_s, self) if serializer_const.nil? raise "Can't find serializer for #{self.name}.#{name} has_many relationship." if serializer_const.nil? diff --git a/lib/panko/serializer_resolver.rb b/lib/panko/serializer_resolver.rb index 28b437c..d36527f 100644 --- a/lib/panko/serializer_resolver.rb +++ b/lib/panko/serializer_resolver.rb @@ -1,25 +1,38 @@ # frozen_string_literal: true +require 'active_support/core_ext/string/inflections' +require 'active_support/core_ext/module/introspection' + class Panko::SerializerResolver - def self.resolve(name) - serializer_name = "#{name.singularize.camelize}Serializer" - serializer_const = safe_const_get(serializer_name) + class << self + def resolve(name, from) + serializer_const = nil - return nil if serializer_const.nil? - return nil unless is_serializer(serializer_const) + if namespace = namespace_for(from) + serializer_const = safe_serializer_get("#{namespace}::#{name.singularize.camelize}Serializer") + end - serializer_const - end + serializer_const ||= safe_serializer_get("#{name.singularize.camelize}Serializer") + serializer_const + end - private + private - def self.is_serializer(const) - const < Panko::Serializer - end + if Module.method_defined?(:module_parent_name) + def namespace_for(from) + from.module_parent_name + end + else + def namespace_for(from) + from.parent_name + end + end - def self.safe_const_get(name) - Object.const_get(name) - rescue NameError - nil + def safe_serializer_get(name) + const = Object.const_get(name) + const < Panko::Serializer ? const : nil + rescue NameError + nil + end end end diff --git a/panko_serializer.gemspec b/panko_serializer.gemspec index ddea4f1..6b92a01 100644 --- a/panko_serializer.gemspec +++ b/panko_serializer.gemspec @@ -31,4 +31,5 @@ Gem::Specification.new do |spec| spec.extensions << "ext/panko_serializer/extconf.rb" spec.add_dependency "oj", "~> 3.10.0" + spec.add_dependency "activesupport" end diff --git a/spec/panko/serializer_resolver_spec.rb b/spec/panko/serializer_resolver_spec.rb index f01fa71..302754a 100644 --- a/spec/panko/serializer_resolver_spec.rb +++ b/spec/panko/serializer_resolver_spec.rb @@ -7,7 +7,7 @@ class CoolSerializer < Panko::Serializer end - result = Panko::SerializerResolver.resolve("cool") + result = Panko::SerializerResolver.resolve("cool", Object) expect(result._descriptor).to be_a(Panko::SerializationDescriptor) expect(result._descriptor.type).to eq(CoolSerializer) @@ -17,7 +17,7 @@ class CoolSerializer < Panko::Serializer class PersonSerializer < Panko::Serializer end - result = Panko::SerializerResolver.resolve("persons") + result = Panko::SerializerResolver.resolve("persons", Object) expect(result._descriptor).to be_a(Panko::SerializationDescriptor) expect(result._descriptor.type).to eq(PersonSerializer) @@ -27,22 +27,42 @@ class PersonSerializer < Panko::Serializer class MyCoolSerializer < Panko::Serializer end - result = Panko::SerializerResolver.resolve("my_cool") + result = Panko::SerializerResolver.resolve("my_cool", Object) expect(result._descriptor).to be_a(Panko::SerializationDescriptor) expect(result._descriptor.type).to eq(MyCoolSerializer) end + it "resolves serializer in namespace first" do + class CoolSerializer < Panko::Serializer + end + module MyApp + class CoolSerializer < Panko::Serializer + end + + class PersonSerializer < Panko::Serializer + end + end + + result = Panko::SerializerResolver.resolve("cool", MyApp::PersonSerializer) + expect(result._descriptor).to be_a(Panko::SerializationDescriptor) + expect(result._descriptor.type).to eq(MyApp::CoolSerializer) + + result = Panko::SerializerResolver.resolve("cool", Panko) + expect(result._descriptor).to be_a(Panko::SerializationDescriptor) + expect(result._descriptor.type).to eq(CoolSerializer) + end + describe "errors cases" do it "returns nil when the serializer name can't be found" do - expect(Panko::SerializerResolver.resolve("post")).to be_nil + expect(Panko::SerializerResolver.resolve("post", Object)).to be_nil end it "returns nil when the serializer is not Panko::Serializer" do class SomeObjectSerializer end - expect(Panko::SerializerResolver.resolve("some_object")).to be_nil + expect(Panko::SerializerResolver.resolve("some_object", Object)).to be_nil end end end