Skip to content

Conversation

@pixelhandler
Copy link
Owner

  • Update findRelated adapter method to be friendly to polymorphic associations
  • Add example (in dummy app) of solution using polymorphic association for 'imageable' relation
  • Add acceptance test for resource (pictures) that has polymorphic association (imageable)

The dummy app uses resources: employee, product and pictures. The pictures have an imageable relation which can be either an employee or product resource. There is no model prototype for the imageable resources only a service.

The solution to support polymorphic associations did require an imageable service, but this service only utilizes the findRelated method which uses the URLs provided in the relationship objects of the resource.

See the changed files list. Only a minor change in the adapter#findRelated method was needed for the polymorphic association support of a related resource. However the implementation does need a service that represents the polymorphic relation, in this case imageable is the service that supports types for employee or product.

Some links for the rails api:

Below is a payload for a resource that uses polymorphic associations.

There are 3 types: Employee, Product, Picture. The Picture belongs to an Imageable resource (Employees and Products both use a has_many relation for Pictures).

In the payload below the request is for http://localhost:3000/api/v1/pictures?include=imageable so the 1st 5 of 6 pictures are returned and included are the imaginable types a few products and an employee.

The links under each picture resource's relationships objects have the url which should return the imageable resource regardless of type. E.g. http://localhost:3000/api/v1/pictures/5/imageable may be an Employee and http://localhost:3000/api/v1/pictures/4/imageable may be a Product.

{
  "data": [
    {
      "id": "1",
      "type": "pictures",
      "links": {
        "self": "http://localhost:3000/api/v1/pictures/1"
      },
      "attributes": {
        "name": "box of chocolates"
      },
      "relationships": {
        "imageable": {
          "links": {
            "self": "http://localhost:3000/api/v1/pictures/1/relationships/imageable",
            "related": "http://localhost:3000/api/v1/pictures/1/imageable"
          },
          "data": {
            "type": "products",
            "id": "3"
          }
        }
      }
    },
    {
      "id": "2",
      "type": "pictures",
      "links": {
        "self": "http://localhost:3000/api/v1/pictures/2"
      },
      "attributes": {
        "name": "10 foot candy cane"
      },
      "relationships": {
        "imageable": {
          "links": {
            "self": "http://localhost:3000/api/v1/pictures/2/relationships/imageable",
            "related": "http://localhost:3000/api/v1/pictures/2/imageable"
          },
          "data": {
            "type": "products",
            "id": "2"
          }
        }
      }
    },
    {
      "id": "3",
      "type": "pictures",
      "links": {
        "self": "http://localhost:3000/api/v1/pictures/3"
      },
      "attributes": {
        "name": "Hot apple fritter"
      },
      "relationships": {
        "imageable": {
          "links": {
            "self": "http://localhost:3000/api/v1/pictures/3/relationships/imageable",
            "related": "http://localhost:3000/api/v1/pictures/3/imageable"
          },
          "data": {
            "type": "products",
            "id": "1"
          }
        }
      }
    },
    {
      "id": "4",
      "type": "pictures",
      "links": {
        "self": "http://localhost:3000/api/v1/pictures/4"
      },
      "attributes": {
        "name": "Boston Creme"
      },
      "relationships": {
        "imageable": {
          "links": {
            "self": "http://localhost:3000/api/v1/pictures/4/relationships/imageable",
            "related": "http://localhost:3000/api/v1/pictures/4/imageable"
          },
          "data": {
            "type": "products",
            "id": "1"
          }
        }
      }
    },
    {
      "id": "5",
      "type": "pictures",
      "links": {
        "self": "http://localhost:3000/api/v1/pictures/5"
      },
      "attributes": {
        "name": "Bill at EmberConf"
      },
      "relationships": {
        "imageable": {
          "links": {
            "self": "http://localhost:3000/api/v1/pictures/5/relationships/imageable",
            "related": "http://localhost:3000/api/v1/pictures/5/imageable"
          },
          "data": {
            "type": "employees",
            "id": "1"
          }
        }
      }
    }
  ],
  "included": [
    {
      "id": "3",
      "type": "products",
      "links": {
        "self": "http://localhost:3000/api/v1/products/3"
      },
      "attributes": {
        "name": "Chocolates"
      },
      "relationships": {
        "pictures": {
          "links": {
            "self": "http://localhost:3000/api/v1/products/3/relationships/pictures",
            "related": "http://localhost:3000/api/v1/products/3/pictures"
          }
        }
      }
    },
    {
      "id": "2",
      "type": "products",
      "links": {
        "self": "http://localhost:3000/api/v1/products/2"
      },
      "attributes": {
        "name": "Candy Canes"
      },
      "relationships": {
        "pictures": {
          "links": {
            "self": "http://localhost:3000/api/v1/products/2/relationships/pictures",
            "related": "http://localhost:3000/api/v1/products/2/pictures"
          }
        }
      }
    },
    {
      "id": "1",
      "type": "products",
      "links": {
        "self": "http://localhost:3000/api/v1/products/1"
      },
      "attributes": {
        "name": "Donuts"
      },
      "relationships": {
        "pictures": {
          "links": {
            "self": "http://localhost:3000/api/v1/products/1/relationships/pictures",
            "related": "http://localhost:3000/api/v1/products/1/pictures"
          }
        }
      }
    },
    {
      "id": "1",
      "type": "employees",
      "links": {
        "self": "http://localhost:3000/api/v1/employees/1"
      },
      "attributes": {
        "name": "Bill Heaton"
      },
      "relationships": {
        "pictures": {
          "links": {
            "self": "http://localhost:3000/api/v1/employees/1/relationships/pictures",
            "related": "http://localhost:3000/api/v1/employees/1/pictures"
          }
        }
      }
    }
  ],
  "meta": {
    "page": {
      "total": 7,
      "sort": [
        {
          "field": "id",
          "direction": "asc"
        }
      ],
      "offset": 0,
      "limit": 5
    }
  },
  "links": {
    "first": "http://localhost:3000/api/v1/pictures?include=imageable&page%5Blimit%5D=5&page%5Boffset%5D=0",
    "next": "http://localhost:3000/api/v1/pictures?include=imageable&page%5Blimit%5D=5&page%5Boffset%5D=5",
    "last": "http://localhost:3000/api/v1/pictures?include=imageable&page%5Blimit%5D=5&page%5Boffset%5D=2"
  }
}

@oliverbarnes
Copy link
Contributor

Looks good to me 👍

@pixelhandler
Copy link
Owner Author

@oliverbarnes thanks for taking a look. I need to add some more tests for the polymorphic association then will be ready to merge.

@pixelhandler pixelhandler force-pushed the polymorphic-resources branch 2 times, most recently from c1b551d to 36830a4 Compare August 24, 2015 06:39
@pixelhandler pixelhandler force-pushed the polymorphic-resources branch from 36830a4 to 8770603 Compare August 24, 2015 17:47
pixelhandler added a commit that referenced this pull request Aug 24, 2015
Add support for polymorphic association in a resource
@pixelhandler pixelhandler merged commit 89a0ebe into master Aug 24, 2015
@pixelhandler pixelhandler deleted the polymorphic-resources branch August 24, 2015 17:50
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.

3 participants