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

Automatically serialize belongsToMany into relation meta attribute #74

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jamesdixon
Copy link
Contributor

This PR adds the ability to automatically serialize pivot/join table data returned by Bookshelf into a relationships' meta attribute for belongsToMany relations.

The serializer already has a relationshipMeta option that accepts an object containing a string or function. This PR adds a function that is passed to relationshipMeta by default that will serialize pivot data into the relationships' meta attribute. This function can be overridden by passing your own function to relationshipMeta as an option.

A few questions/comments:

  • Do we want serialization of pivot data to occur automatically? or should we provide an option to disable?
  • If a user wants to override the relationshipMeta function with their own method, do we couple this with the option to enable or disable serialization of belongsToMany pivot data to allow chaining of the provided method and the method we provide so they don't have to provide their own function for serializing belongsToMany relations into metadata?
  • Some modifications to the toJSON method were made to add pivot data to the model that's ultimately passed into the function provided to relationshipMeta. Currently, .serialize({ shallow: true }) will not include pivot data. I looked at the Bookshelf code (https://github.com/tgriesser/bookshelf/blob/9c7b56cb3145930d56c55b07ddf4d36a702e31b3/src/base/model.js#L263) for this and it doesn't appear that there would be an adverse affect for allowing pivot data to be included even when doing a shallow serialization, but for now, I've done the work on our end.

@jamesdixon
Copy link
Contributor Author

Another to point to mention:

Currently, the attributes returned as part of meta are not affected by the serializer's typeForAttribute option. In my case, everything should be camelCased, but those attributes are snake_case.

@jamesdixon
Copy link
Contributor Author

jamesdixon commented Sep 27, 2016

@chamini2 to clarify, the PR allows for pivot data (data contained in join tables) to be automatically serialized into meta data on a relationship.

Imagine that I have a three tables: appointment, appointment_service and appointment_pet. The latter two tables are join tables that associate services and pets with an appointment. However, what if I needed to specify that certain pets are only applicable to a specific service? For example, I have a feeding service that should only apply to the dog, Max. The place to specify that information would be another field in appointment_service -- let's call it specific_pets. According to the JSON API folks, the place to put this type of information would be the meta attr of the relation. This PR enables serialization of those pivot/join properties into the meta attr of the relation.

@chamini2
Copy link
Collaborator

So it's for belongsToMany relations. But the test I see in this PR talks about a belongsTo relation, should it be changed to belongsToMany then?

@jamesdixon
Copy link
Contributor Author

Correct. The description in the test is a typo :)

@jamesdixon
Copy link
Contributor Author

@chamini2 any comment on this other than the typo in the test name?

@chamini2
Copy link
Collaborator

chamini2 commented Oct 4, 2016

Actually, I haven't reviewed it yet! I tried to understand the feature with the spec and since I'm not entirely sure how pivot tables work I can't really review it right now. I was waiting for some time available to understand what's accomplished here! 😄

Are you needing this at the moment? I can take a look for next monday for sure.

@jamesdixon
Copy link
Contributor Author

No rush on it at all, so please take your time. I'd prioritize the plugin-related tickets before this.

Copy link
Collaborator

@chamini2 chamini2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add documentation for the new option

template[relName] = relTemplate;
template.attributes.push(relName);
});

return template;
}

function relationshipMeta(relation, models) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not declare this relationshipMeta function here, because it is just the default function to use in case none was passed.

I would declare it where it is being used as a default.

/**
* Recursively adds data-related properties to the
* template to be sent to the serializer
*/
function processSample(info: Information, sample: Model): SerialOpts {
let { bookOpts, linkOpts }: Information = info;
let { bookOpts, linkOpts, serialOpts }: Information = info;
let { enableLinks }: BookOpts = bookOpts;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding it here, like:

const defaultRelationshipMeta = function (relation, models) {
  if (isArray(models)) { ... }
}
const { relationshipMeta = defaultRelationshipMeta } = seralOpts;

expect(_.matches(expected)(result)).toBe(true);

});

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test for the attribute omission done

@chamini2
Copy link
Collaborator

Maybe rebase from master?

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.

2 participants