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
Hello! Thank you for creating such an amazing gem!
I’m currently facing an issue that I believe has been discussed in the past, but I couldn’t find any specific topics related to it. I’d like to ask for guidance on how others are addressing this challenge in the following use case.
Context
Model
erDiagram
User ||--|{ Post : ""
Post }|--|| Book : ""
Loading
Serializer
For models like the above, the serializers would typically look like this:
The main challenge I’m facing is around the design and usage of serializers. Many articles I’ve seen tend to solve problems using a single, monolithic serializer. This approach often lacks clear separation of concerns and results in overly complex interdependencies. I’d like to know how others tackle the following issues:
Unnecessary Relationships in Different Use Cases
For example, in the /api/post/{:post_id} endpoint, I’d like the response to look like this:
The problem becomes more apparent with endpoints like /api/book/{:book_id}/reviews or /api/book/{:book_id}/review/{:post_id}. In these cases, since the book is already identified by the endpoint, including the book details in every review unnecessarily duplicates data and adds noise to the response.
Sudden N+1 Query Issues
AMS often introduces N+1 query problems as new associations are added to models. For example, the /api/book/{:book_id}/reviews endpoint might be optimized like this:
However, as the product grows, adding a new Author model and updating the serializer like this:
classPostSerializer < ActiveModelSerializers::Modelattributes:id,:comment,:ratebelongs_to:user,serializer: UserSerializerbelongs_to:book,serializer: BookSerializerbelongs_to:author,serializer: AuthorSerializer# new associationend
...suddenly introduces N+1 queries for Author in /api/book/{:book_id}/reviews. Since some legacy endpoints don’t use includes consistently, fixing this across the codebase can be challenging.
My Proposed Solution
One strength of AMS is its model-based approach. To maintain this advantage, I propose the following design:
classBase::PostSerializer < ActiveModelSerializers::Modelattributes:id,:comment,:rateendclassPostSerializer < Base::PostSerializerbelongs_to:user,serializer: UserSerializerbelongs_to:book,serializer: BookSerializerendclassPostWithAuthorSerializer < Base::PostSerializerbelongs_to:user,serializer: UserSerializerbelongs_to:book,serializer: BookSerializerbelongs_to:author,serializer: AuthorSerializer# specific to this use caseend
By defining a Base::PostSerializer for attributes and using separate serializers for specific use cases, we can minimize the impact on existing features. One key rule: never inherit from anything other than the base class to avoid complex, hard-to-manage hierarchies.
Final Question
How are you all addressing these kinds of design challenges with AMS? I’d love to hear your approaches and experiences. Thank you in advance!
Hello! Thank you for creating such an amazing gem!
I’m currently facing an issue that I believe has been discussed in the past, but I couldn’t find any specific topics related to it. I’d like to ask for guidance on how others are addressing this challenge in the following use case.
Context
Model
erDiagram User ||--|{ Post : "" Post }|--|| Book : ""Serializer
For models like the above, the serializers would typically look like this:
The Issue
The main challenge I’m facing is around the design and usage of serializers. Many articles I’ve seen tend to solve problems using a single, monolithic serializer. This approach often lacks clear separation of concerns and results in overly complex interdependencies. I’d like to know how others tackle the following issues:
Unnecessary Relationships in Different Use Cases
For example, in the
/api/post/{:post_id}endpoint, I’d like the response to look like this:{ "id": 12345, "comment": "dummy text", "rate": 4.5, "user": { "id": 12345, "name": "jackson", "post_count": 15, "thumbnail": "http://xxxxxxxx.xxxxx/yyy" }, "book": { "id": 435, "name": "The Little Prince", "avg_rate": 3.9, "review_count": 231, "book_image": "http://xxxxxxxx.xxxxx/xxx" } }However, for
/api/book/{:book_id}, the response should look like this:{ "id": 435, "name": "The Little Prince", "avg_rate": 3.9, "review_count": 231, "book_image": "http://xxxxxxxx.xxxxx/xxx", "last_review": { "id": 12345, "comment": "dummy text", "rate": 4.5, "user": { "id": 12345, "name": "jackson", "post_count": 15, "thumbnail": "http://xxxxxxxx.xxxxx/yyy" } } }The problem becomes more apparent with endpoints like
/api/book/{:book_id}/reviewsor/api/book/{:book_id}/review/{:post_id}. In these cases, since the book is already identified by the endpoint, including the book details in every review unnecessarily duplicates data and adds noise to the response.Sudden N+1 Query Issues
AMS often introduces N+1 query problems as new associations are added to models. For example, the
/api/book/{:book_id}/reviewsendpoint might be optimized like this:However, as the product grows, adding a new Author model and updating the serializer like this:
...suddenly introduces N+1 queries for Author in
/api/book/{:book_id}/reviews. Since some legacy endpoints don’t use includes consistently, fixing this across the codebase can be challenging.My Proposed Solution
One strength of AMS is its model-based approach. To maintain this advantage, I propose the following design:
By defining a
Base::PostSerializerfor attributes and using separate serializers for specific use cases, we can minimize the impact on existing features. One key rule: never inherit from anything other than the base class to avoid complex, hard-to-manage hierarchies.Final Question
How are you all addressing these kinds of design challenges with AMS? I’d love to hear your approaches and experiences. Thank you in advance!