You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I don't have a solid mental model for what's happening when I'm trying to set a class -> serializable class mapping.
I've got two classes:
class Relationship < ApplicationRecord
# relationship stuff. baggage, if you will.
end
# then, nested in app/models/relationships:
class Relationships::Approve < Relationship
# approval related things, so all that logic is only here
end
I've got a SerializableRelationship class that's working. I'd like to reuse that with these subclasses.
class Api::Relationships::ApprovesController < Api::ApiController
before_action :set_relationship
def update
if @relationship.update(status: "approved", action_user: current_user)
render jsonapi: @relationship
else
render jsonapi_errors: @relationship.errors
end
end
private
def set_relationship
@relationship = Relationships::Approve.find(params[:id])
end
end
How do I:
set this option inside my controller action?
set this option at the controller wide level? (aka this )
application-wide level (in the initializer)?
I know that, once I get it, it'll probably be an "ohhhh" moment. I conceptually understand it's a big hash that makes certain keys to certain other classes that serialize those things. But I need to see an example, and get details, because I don't understand:
what does the key need to be?
what does the value need to be?
are modifications made to the things I pass in?
I've been guessing things and not getting feedback I know how to understand from the errors.
I think this would make some great addition to the docs! I'll check back in when I figure it out, and maybe PR in some updates if you're ok with that.
Oh my gosh! So helpful! I'm not doing Ruby/Rails full time anymore, but next coding session I'll sit down and get a PR in before starting on my personal stuff.
Reacted by Lucas Hosseini, Chris Masters, Sergey and Rafał Trojanowski
One thing that I am struggling with is how to "duck-type" the rendering; for example, I have more than one class (specifically, one is a model, the other is a double) that both respond to the same API and I want to render with the same subclass of JSONAPI::Serializable::Resource. I was hoping that specifying jsonapi_class in a call to render jsonapi: would let me say "use this renderer", but that doesn't appear to be the case. Is there a way I can request that jsonapi-rails render an object with a given serializable, regardless of what it's underlying class is?
@bprotas Yes, you were almost there: the class option of the render method does that for you, and the default value for the class option can be overridden by overriding the jsonapi_class method. Note that when explicitly specifying a class option, you will prevent the default mapping to kick in (User -> SerializableUser), but you can alway do either
Thanks @beauby ; I appreciate the response. This isn't quite what I was looking for - it assumes that here my class is always Article to be serialized by MyCustomSerializableArticle, but in fact I want MyCustomSerializableArticle to be used to render regardless of if the object is of class Article or not (it might be a subclass of Article, or a class of Rspec::Mocks::Double if I'm writing a test.
I ended up with this line of code to always use the same serializer, regardless of the class of object I'm serializing:
@bprotas I see. The json:api standard is based on the idea of serializing a graph of resources, so the general case is that one needs to map each resource type to a serializer.
In your case, you could do
I've created a PR that allows customizing the default serializer mappings in the config file. #92
I think it makes sense for situations like this one. i.e. STI models normally will use the same serializer so would be good if you could manually specify that.
Activity
beauby commentedon Nov 16, 2017
Hi @ZempTime
Override
jsonapi_classin yourApplicationController.The key is the class name of the object you are passing to
render jsonapi:. Usually, it is anActiveRecordmodel class name.The value is a Serializable class (usually a subclass of
JSONAPI::Serializable::Resource).Not sure I understand but I'd say no: the models are not modified, and the serializable classes are just instantiated.
I agree and that would be of great help! (:
ZempTime commentedon Nov 17, 2017
Oh my gosh! So helpful! I'm not doing Ruby/Rails full time anymore, but next coding session I'll sit down and get a PR in before starting on my personal stuff.
bprotas commentedon Dec 6, 2017
One thing that I am struggling with is how to "duck-type" the rendering; for example, I have more than one class (specifically, one is a model, the other is a double) that both respond to the same API and I want to render with the same subclass of
JSONAPI::Serializable::Resource. I was hoping that specifyingjsonapi_classin a call torender jsonapi:would let me say "use this renderer", but that doesn't appear to be the case. Is there a way I can request thatjsonapi-railsrender an object with a given serializable, regardless of what it's underlying class is?beauby commentedon Dec 6, 2017
@bprotas Yes, you were almost there: the
classoption of therendermethod does that for you, and the default value for theclassoption can be overridden by overriding thejsonapi_classmethod. Note that when explicitly specifying aclassoption, you will prevent the default mapping to kick in (User -> SerializableUser), but you can alway do eitheror overriding
jsonapi_classasbprotas commentedon Dec 6, 2017
Thanks @beauby ; I appreciate the response. This isn't quite what I was looking for - it assumes that here my class is always
Articleto be serialized byMyCustomSerializableArticle, but in fact I wantMyCustomSerializableArticleto be used to render regardless of if the object is of classArticleor not (it might be a subclass ofArticle, or a class ofRspec::Mocks::Doubleif I'm writing a test.I ended up with this line of code to always use the same serializer, regardless of the class of object I'm serializing:
This feels like a bit of a hack; I would rather not have to use the hash:
I might still be misunderstanding how the library is supposed to work?
Thank you again for the quick response!
beauby commentedon Dec 7, 2017
@bprotas I see. The json:api standard is based on the idea of serializing a graph of resources, so the general case is that one needs to map each resource type to a serializer.
In your case, you could do
i.e. use a hash with a default value, or even
using a lambda.
bprotas commentedon Dec 7, 2017
ah interesting - that is much cleaner, thank you!
JoeWoodward commentedon Sep 2, 2018
I've created a PR that allows customizing the default serializer mappings in the config file. #92
I think it makes sense for situations like this one. i.e. STI models normally will use the same serializer so would be good if you could manually specify that.