wrstudios / odata4

Simple OData V4.0 Library for Ruby
Other
2 stars 2 forks source link

[Feature] Support for multiple schemas #10

Closed PandaWhisperer closed 6 years ago

PandaWhisperer commented 6 years ago

Background

OData allows for multiple <Schema> elements to be declared in a single metadata document. Each schema acts as a namespace, and can have its own ComplexTypes, EnumTypes and EntityTypes, as well as Actions, Functions, Annotations, etc. (see specs).

EntityTypes in one schema can make use of property types in a different schema. We have observed this in practice, therefore the gem cannot assume that the entire service will live in a single schema.

While there may many many schemas declaring different property- and entity types, only one schema may define an entity container.

This PR adds support for that by extracting a Schema and a EntityContainer class, and delegating all relevant methods from the Service class to those classes.

Notes

Since property types and the entity types that use them may live in separate schemas, and even the entity container may live in a different schema than the entity types it makes use of, we can no longer refer to any of these elements by their simple name only — we have to refer to them by their fully qualified name (i.e. including namespace).

This means, for example, that service.entity_types now returns fully qualified names only, e.g.

      ODataDemo.Product
      ODataDemo.FeaturedProduct
      ODataDemo.ProductDetail
      ODataDemo.Category
      ODataDemo.Supplier
      ODataDemo.Person
      ODataDemo.Customer
      ODataDemo.Employee
      ODataDemo.PersonDetail
      ODataDemo.Advertisement

Similarly, Service#entity_sets now returns the fully qualified names of the entity type for each set. Additionally, it now uses the entity set names as hash keys, because more than one entity set may use the same entity type.

      expect(service.entity_sets).to eq({
        "Products"       => "ODataDemo.Product",
        "ProductDetails" => "ODataDemo.ProductDetail",
        "Categories"     => "ODataDemo.Category",
        "Suppliers"      => "ODataDemo.Supplier",
        "Persons"        => "ODataDemo.Person",
        "PersonDetails"  => "ODataDemo.PersonDetail",
        "Advertisements" => "ODataDemo.Advertisement"
      })

Since this affects the public API, it should be considered a breaking change. We'll increase the gem version number accordingly.

However, since only a single <EntityContainer> is allowed, we can still expose entity collections in the same way as before (i.e. without having to add the namespace).

This resolves #7.