I have an versioned Rails API application using concerns to bundle shared functionality between multiple serializers. I would expect namespaced serializer concerns to load properly, similar to how namespaced controller concerns work. However, when I namespace a serializer concern, it encounters an uninitialized constant exception. I believe the concern files aren't being loaded at all by by Active Model Serializers. Is there something I am missing to set this up properly?
class ApplicationSerializer < ActiveModel::Serializer
# Shared functionality
end
module V2
class PersonaSerializer < ApplicationSerializer
include V2::ClaimableSerializer
# Other serializer attributes / methods
end
end
module V2
module ClaimableSerializer
extend ActiveSupport::Concern
included do
# Shared attributes to be included with this concern
end
end
end
ActiveModelSerializers Version 0.10.5
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-linux]
Rails Version 5.0.2
Completed 500 Internal Server Error in 560ms (ActiveRecord: 46.3ms)
NameError (uninitialized constant V2::ClaimableSerializer):
app/serializers/v2/persona_serializer.rb:3:in `<class:PersonaSerializer>'
app/serializers/v2/persona_serializer.rb:2:in `<module:V2>'
app/serializers/v2/persona_serializer.rb:1:in `<top (required)>'
app/controllers/v2/auth/sessions_controller.rb:8:in `render_create_success'
app/docs/base_doc.rb:33:in `block in doc_for'
app/controllers/application_controller.rb:36:in `set_time_zone'
Try include ::V2::ClaimableSerializer instead of include V2::ClaimableSerializer.
I'm going to close this because its a Ruby issue, possibly resolvable by modifying the autoload paths in Rails, and not an AMS issue. Please feel free to continue discussing though.
Per https://github.com/rails/rails/pull/18213 and https://github.com/rails/rails/pull/18239/files
you probably want to add
Rails.application.configure do
config.paths.add "app/serializers/concerns", eager_load: true
end
@bf4 Thanks, that led me to finding the solution.
Using include ::V2::ClaimableSerializer doesn't change anything since I don't have any other classes called ClaimableSerializer in my project. Both eager loading and autoloading the directory resulted in the namespace being lost (i.e. it would look for ClaimableSerializer instead of V2::ClaimableSerializer. What I ended up doing was moving my concerns to the top level and putting my v2 directory inside of it. All worked out of the box without any configuration this way:
โโโโ serializers
โโโโ v2
โ persona_serializer.rb
โโโโ concerns
โ claimable_serializer.rb
โโโโ serializers
โโโโ concerns
โ โโโโ v2
โ โ claimable_serializer.rb
โโโโ v2
โ persona_serializer.rb
Yay!
Most helpful comment
@bf4 Thanks, that led me to finding the solution.
Using
include ::V2::ClaimableSerializerdoesn't change anything since I don't have any other classes calledClaimableSerializerin my project. Both eager loading and autoloading the directory resulted in the namespace being lost (i.e. it would look forClaimableSerializerinstead ofV2::ClaimableSerializer. What I ended up doing was moving my concerns to the top level and putting my v2 directory inside of it. All worked out of the box without any configuration this way:Old Directory Structure
New Directory Structure