Chapter 9. Implementing Unidirectional Functional Associations with AngularJS and Parse.com

Table of Contents

1. Many-to-One Relation in Parse
1.1. Create/Update Pointer
1.2. Retrieve Objects
1.3. Remove Pointer
2. New issues
3. Encode our Web Application with Unidirectional Functional Association
3.1. List Objects Use Case
3.2. Create Object Use Case
3.3. Update Object Use Case
3.4. Delete Object Use Case

The two example apps that we have discussed in previous parts, the minimal app and the validation app, have been limited to managing the data of one object type only. A real app, however, has to manage the data of several object types, which are typically related to each other in various ways. In particular, there may be associations and subtype (inheritance) relationships between object types. Handling associations and subtype relationships are advanced issues in software application engineering. They are often not sufficiently discussed in software development text books and not well supported by application development frameworks. In this part of the tutorial, we show how to deal with unidirectional associations, while bidirectional associations and subtype relationships are covered in parts 4 and 5.

Now three classes will exist in our web applications: Publisher, Book and Author. Their association can be represented as a Publisher-Book-Author design model:

Figure 9.1.  Publisher-Book-Author design model

Publisher-Book-Author design model


We adopt the approach of model-based development, which provides a general methodology for engineering all kinds of artifacts, including data management apps. For being able to understand this tutorial, you need to understand the underlying concepts and theory. Either you first read the theory chapter on reference properties and associations, before you continue to read this tutorial chapter, or you start reading this tutorial chapter and consult the theory chapter only on demand, e.g., when you stumble upon a term that you don't know.

A unidirectional functional association is either one-to-one or many-to-one. In both cases such an association is represented, or implemented, with the help of a single-valued reference property.

In this chapter of our tutorial, we show

  1. how to handle the many-to-one relation between objects by the backend storage service Parse.com,

  2. how to process the relations using Angular $http together with Parse REST API based on an association-free information design model with single-valued reference properties representing unidirectional functional associations,

  3. how to encode the views and controllers for our web application.

1. Many-to-One Relation in Parse

Based on the classical relational database there are three (four) kinds of relationships between objects: One-to-One, Many-to-One (One-to-Many), Many-to-Many. Replying these kinds of relation, Parse provides four ways:

  • Pointer: which is suitable for one-to-one and many-to-one relationships;

  • Array: which is suitable for one-to-many and many-to-many relationships;

  • Parse Relation : which is suitable for many-to-many relationship;

  • Join Table : which is suitable for many-to-many relation.

The official online document about Relations from Parse.com shows only the situation that how to solve Relations in Parse when developing an application for Android or iOS, but it's not fully suitable for REST API, however it tells us the logical solutions indeed.

According our Public Library web application, the Many-to-One relationship (unidirectional functional association) appears between Publisher and Book. A single-valued reference property, such as the property publisher of the object type Book, allows storing internal references to objects of another type, such as Publisher. According to the introduction of relationships in Parse, we can use Pointer to build the relation between them. Please notice that the objectId, which we used very offen, is the Parse.com built-in standard ID for one object record.

The starting point for building the relationship using Pointer between publisher and book objects is an association-free design model like following:

Figure 9.2. Publisher-Book association-free model

Publisher-Book association-free model


1.1. Create/Update Pointer

Suppose we got one Publisher object and two Book objects, we want to associate all Book objects with this publisher:

twoBooks.forEach( function( book) {
  $http( {
    method: 'PUT',
    url: 'https://api.parse.com/1/classes/Book/' + book.objectId,
    data: {
      publisher: {
        __type: 'Pointer',
        className: 'Publisher',
        objectId: publisher.objectId
      }
    }
  });
});

The objectId of this publisher will be saved as a property into each book object. In Pasre Core, the record of one book would be:

The record of this publisher keeps:

1.2. Retrieve Objects

If we want to get the information about the publisher of one known book:

$http( {
  method: 'GET',
  url: 'https://api.parse.com/1/classes/Publisher/' +
       book.publisher.objectId
});

Parse provides an operation include for returning multiple types of related objects in one query, when the type of this property is Pointer. In our case, the property publisher from Book is a Pointer, we can get all related publisher objects even during getting all books, without send a get request again for getting all corresponded publisher:

// Get all books
$http( {
  method: 'GET',
  url: 'http://api.parse.com/1/classes/Book',
  params: { include: 'publisher'}
});

1.3. Remove Pointer

Suppose we want to remove the relations between the publisher and two books:

twoBooks.forEach( function ( book) {
  $http( {
    method: 'PUT',
    url: 'https://api.parse.com/1/classes/Book/' +
         book.objectId,
    data: { publisher: { __op: 'Delete'}}
  });
});

This HTTP request will set the value of publisher::Pointer<publisher> field from ooTkye1JWh to undefined, so that this book will have no publisher in the record.

If we didn't delete the association but delete this publisher, the records of these two books won't be changed, which means the publisher's objectId still exists in the publisher field, but this Pointer will point to none. For security reasons, it would be better delete the Pointer after deleted a publisher.