Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include namespace when looking up superclass #2172

Merged

Conversation

dpogue
Copy link

@dpogue dpogue commented Aug 3, 2017

Purpose

When falling back to the superclass for finding a serializer, the namespace was getting dropped.

Changes

Pass the namespace through when finding a serializer for the superclass.

@NullVoxPopuli
Copy link
Contributor

NullVoxPopuli commented Aug 4, 2017

can you provide a test demonstrating your scenario?
as-is, superclass should include the namespace:

irb(main):001:0> class A; end
=> nil
irb(main):003:0> class A::C; end
=> nil
irb(main):004:0> class D < A::C; end
=> nil
irb(main):005:0> D.superclass
=> A::C

also, is this a problem that could be solved by:

ActiveModelSerializers.config.serializer_lookup_chain.unshift(
  lambda do |resource_class, _, namespace|
    "#{namespace.name}::#{resource_class.name}Serializer" if namespace
  end
)

@dpogue
Copy link
Author

dpogue commented Aug 4, 2017

It was an issue with the controller namespace not getting passed up to the superclass.

# Superclass model
class User < ActiveRecord::Base
end

# Subclass model
class AppUser < User
end

# Non-namespaced superclass serializer (Wrong)
class UserSerializer < ActiveModel::Serializer
end

# Namespaced superclass serializer (Correct)
class Admin::UserSerializer < ActiveModel::Serializer
end

# Controller
class Admin::UsersController < ApplicationController
  def show
    render :json => AppUser.first
  end
end

When Admin::UsersController tried to render a AppUser, the lookup chains were like this:

["Admin::AppUserSerializer", "AppUserSerializer", "::AppUserSerializer"]
["UserSerializer", "::UserSerializer"]

With this patch, it correctly preserves the controller namespace when searching for the superclass:

["Admin::AppUserSerializer", "AppUserSerializer", "::AppUserSerializer"]
["Admin::UserSerializer", "UserSerializer", "::UserSerializer"]

@NullVoxPopuli
Copy link
Contributor

What happens when you try using the config change to the lookup chain?

@dpogue
Copy link
Author

dpogue commented Aug 4, 2017

The config change to the lookup chain does not resolve the issue, because it is still trying to use a nil namespace for the superclass.

@NullVoxPopuli
Copy link
Contributor

Can you change it to:

ActiveModelSerializers.config.serializer_lookup_chain.unshift(
  lambda do |resource_class, iforgotwhatthisis, namespace|
    puts '-----------------------------------------------'
    puts resource_class
    puts iforgotwhatthisis
    puts namespace


    "#{namespace.name}::#{resource_class.name}Serializer" if namespace
  end
)

and then restart your server, try to load your resource, and copy the console output to here?
This'll help, cause I actually don't remember which namespace that is in the lookups.

@dpogue
Copy link
Author

dpogue commented Aug 4, 2017

-----------------------------------------------
AppUser
ActiveModel::Serializer
Admin
-----------------------------------------------
User
ActiveModel::Serializer

@NullVoxPopuli
Copy link
Contributor

NullVoxPopuli commented Aug 4, 2017

So then, this should solve your use case?

A modification of

ActiveModelSerializers.config.serializer_lookup_chain.unshift(
  lambda do |resource_class, serializer_class, namespace|
    "#{namespace.name}::#{resource_class.name}Serializer" if namespace
  end

cause namespace is Admin it the first execution, and 'resource_class' is AppUser, so putting them together would be Admin::AppUserSerializer

So, I guess the root of this is that you want to use a Serializer based off the superclass of the model rather than specifically add namespacing support.

So then, you could add another lookup chain entry that did something like this:

ActiveModelSerializers.config.serializer_lookup_chain.unshift(
  lambda do |resource_class, serializer_class, namespace|
    if namespace && resource_class.superclass != ActiveRecord::Base # or whatever your top level class is
      "#{namespace.name}::#{resource_class.superclass.name}Serializer"
    end
  end

does that work?

@NullVoxPopuli
Copy link
Contributor

It seems we need another PR that fixes the tests on master, as at least one of them seems unrelated to this PR.

I 'think' I agree that this PR is valuable, though. the namespace should def continue getting passed through the recursion.

@dpogue
Copy link
Author

dpogue commented Sep 5, 2017

#2185 makes the same change, but includes tests, so that would probably be a better one to merge

@dpogue
Copy link
Author

dpogue commented Jul 10, 2019

I have cherry-picked the commit from #2185 that includes tests, and rebased it on 0-10-stable, as requested in #2242.

This PR now supersedes both #2242 and #2185. The cherry-picked commit is attributed to all the authors of all 3 PRs.

@wasifhossain
Copy link
Member

@bf4 you might have had some reason to close a similar PR. can you please share the point with us?
but if you have changed your mind any way, I would like to merge it.

@dpogue can you please leave a changelog entry under the Fixes section. thanks

Co-authored-by: Rafael Gaspar <rafael.gaspar@me.com>
Co-authored-by: Darryl Pogue <darryl@dpogue.ca>
Co-authored-by: Artin Boghosian <artinboghosian@gmail.com>
@dpogue
Copy link
Author

dpogue commented Jul 10, 2019

Changelog entry added :)

@wasifhossain
Copy link
Member

tests are looking good 👌 let's give it a go! also have an eye open for any regression in case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants