Skip to content

Setting root key strategy globally for json adapter #1536

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

Closed
RomanKapitonov opened this issue Feb 24, 2016 · 6 comments
Closed

Setting root key strategy globally for json adapter #1536

RomanKapitonov opened this issue Feb 24, 2016 · 6 comments

Comments

@RomanKapitonov
Copy link
Contributor

After updating to v0.10.0.rc4 tag I had to specify ActiveModelSerializers.config.adapter = :json in an initializer for a rails application in order to make active_model_serializer to add root key to the the response. However if the model is nested the key is built using the whole class name. For example if I specify a model:

class Users::Profile < ActiveRecord::Base
end

and then in controller:

class Users::ProfilesController < ApplicationController
  def show
    @profile = Users::Profile.first
     respond_with @profile, serializer: UserProfileSerializer
  end
end

It will build json containing the root key as follows: {'users/profile': {'name': 'test'}}. Is there any way to make active_model_serializer to use the class itself ignoring nesting? I've looked through the source code and found a method json_key which builds the root element of the json. But overriding that method is not always working. Moving root element build method to a overridable strategy may be a good feature request candidate

@RomanKapitonov
Copy link
Contributor Author

I've found a way to reproduce the issue when json_key method is not called. If you respond_with empty collection of a given type (fetched by cancancan method load_and_authorize_resource) in index action it will ignore the json_key and render an empty collection with wrong root key.

@groyoh
Copy link
Member

groyoh commented Feb 24, 2016

What about using the :root options like so:

render json: @profile, serializer: UserProfileSerializer, root: "profile"

?

@groyoh
Copy link
Member

groyoh commented Feb 24, 2016

I see two other solutions here:

  • Create your own ProfileCollectionSerializer like so:
class ProfileCollectionSerializer < ActiveModel::Serializer::CollectionSerializer
  def json_key
    "profiles"
  end
end
render json: @profiles, serializer: ProfileCollectionSerializer
  • define a wrapper around the cancan collection that responds to #name:
class CollectionWrapper
  include Enumerable
  delegate :each, to: :@collection
  attr_reader :name

  def initialize(collection, name)
    @collection = collection
    @name = name
  end
end
render json: CollectionWrapper.new(@profiles, :profiles)

@RomanKapitonov
Copy link
Contributor Author

@groyoh Those are all valid options, the only concern is that they force you to be explicit about how you define the root element name. I've created a pull requests which should allow you to implicitly use json_key from item serializer when resource is an empty relation

@bf4
Copy link
Member

bf4 commented Mar 1, 2016

@RomanKapitonov

Is there any way to make active_model_serializer to use the class itself ignoring nesting?

There is a type attribute you can use in the serializer if you're using JSON API. (Eventually this should replace the json_key method).

I've found a way to reproduce the issue when json_key method is not called. If you respond_with empty collection of a given type[...] it will ignore the json_key and render an empty collection with wrong root key.

Which is addressed in your PR #1537 Thanks!

@remear
Copy link
Member

remear commented Apr 4, 2016

Did #1618 resolve this?

@remear remear closed this as completed May 26, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants