[Mementifier 3.6.1] Using Profiles in Nested/Child Objects Using Mappers

Recently I had the need to use Mementifier profiles from within a related child entity. In my case, I was using Quick’s single-table inheritance to dynamically assemble the parent, and I wanted different mementos from the related children, based on the parent “type”. The good news is, this can all be handled via Mappers within Mementifier.

I want to share how I did this, in case anyone else ever needs to do something similar.

Super simple example:
Let’s say you have a User entity, and that user has many Post entities (has many relationship). In our example, when we call getMemento() on User we want the Post entity to use the userpost profile.

Now, I’m using Quick in my example here, but if you’re not using Quick, simply substitute the setUpMementifier() method with whatever method you use when configuring your memento. Pro tip: I like to explicitly define defaultIncludes rather than specifying “*” so Mementifier doesn’t have to introspect the object every time.

Examples:

// User.cfc (a Quick entity)

private void function setUpMementifier() {

	// set up the memento defaults
	super.setUpMementifier();

	// We want to use a specific profile for each of these posts
	// Start by definining the mapper
	this.memento.mappers[ "posts" ] = function( _, item ) {
		// retrieve the relationship and map to a new array
		return this.getPosts().map( function( post ) { 
			// return a memento using a custom profile here
			return post.getMemento( profile = "userpost" );
		} );
	};

}

Now let’s take things up a notch and pretend that User has some type of inheritance schema. In this next case, we want to dynamically get a different profile based on the userType property of the User. We can solve that with a simple switch() statement.

private void function setUpMementifier() {

	// set up the memento defaults
	super.setUpMementifier();

	// We want to use a specific profile for each of these posts
	// Start by definining the mapper
	this.memento.mappers[ "posts" ] = function( _, item ) {
		
		// by default, use the generic memento profile
		var profile = "default";
		
		// reassign which profile to use based on the userType
		switch( getUserType() ) {
			case "administrator":
				profile="useradmin";
				break;
			case "contributor":
				profile="usercontributor";
				break;
			default:
		}
		
		// map the posts to a new array
		return this.getPosts().map( function( post ) { 
			// specify the custom profile here
			return post.getMemento( profile = profile );
		} );
	};

}