LPMSirenKit 0.1.7

LPMSirenKit 0.1.7

TestsTested
LangLanguage Obj-CObjective C
License MIT
ReleasedLast Release Dec 2014

Maintained by Todd Grooms, Aaron London.



 
Depends on:
AFNetworking~> 2.3.1
CoreDataMate~> 0.1
LPMJSONUtils~> 1.0.0
Mantle~> 1.5
 

  • By
  • Todd Grooms

LPMSirenKit is a lightweight library for interacting with Hypermedia APIs that adhere to the Siren specification.

LPMSirenKit sits on top of AFNetworking and submits requests on behalf of the application. The library will parse the results and cache the entity, link, action, and field objects. The properties for the entity objects are not cached at this level (the library only caches those things that are necessary for navigation).

Usage

Running the Example Project

Clone the Repo

$ git clone [email protected]:lonelyplanet/lpm-sirenkit-ios.git

Change to the Example Directory

$ cd lpm-sirenkit-ios/Example

Run Pod Install to Download Example Project Dependencies

$ pod install

Open the LPMSirenKit.xcworkspace

$ open LPMSirenKit.xcworkspace

Now you can run the project from Xcode. Once the application launches, you will be presented with a screen that will request a URL for a server you wish to run the application against and the location of the manifest. In our definition, the manifest is simply the location of the initial SirenEntity. For most servers, you can leave this field blank as the initial SirenEntity is located at the root URL you specify.

Typical Usage Flow for LPMSirenKit

Initialize

You will create an LPMSirenSessionManager with a base URL, a path to where the manifest for the API can be found, and an instance of NSURLSessionConfiguration (the defaultSessionConfiguration works really well). The manifest is simply the root of the API or, rather, where the API indicates what root level links and/or actions are available. Initialize your LPMSirenSessionManager:

LPMSirenSessionManager *sirenSessionManager = [[LPMSirenSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"http://siren.api"]
                                                                                 manifestPath:manifestPath
                                                                         sessionConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration];

Request Manifest

You will then need to request the manifest:

[sirenSessionManager GETManifestWithParameters:nil completion:^(LPMSirenEntityModel *manifestEntity, NSError *error) {
  // Check manifestEntity and error to determine if request was successful
}];

When you request the manifest, you are fetching the initial SirenEntity which is where you start traversing the API. This entity will most likely contain top-level SirenLinks and SirenActions for the API.

Request Links

After successfully requesting the API's manifest, you are ready to rock. If you take one of the LPMSirenLinkModels that is connected to the manifest LPMSirenEntityModel (since the manifest is just a LPMSirenEntityModel, you can check the manifestEntityModel.sirenLinks relationship for any LPMSirenLinkModels you wish to use), you can request links by using the LPMSirenLinkModel:

[sirenSessionManager GETLink:sirenLinkModel withParameters:nil completion:^(LPMSirenEntityModel *sirenEntityModel, NSError *error) {
  // Check sirenEntityModel and error to determine if request was successful
} error:&error];

Or by using the link's relationship(s) and the GUID of the entity that owns the link:

[sirenSessionManager GETLinkForRelationship:@"self" ofEntityWithGUID:@"guid" withParameters:nil completion:^(LPMSirenEntityModel *sirenEntityModel, NSError *error) {
  // Check sirenEntityModel and error to determine if request was successful
} error:&error];

If the LPMSirenLinkModel is not found for the request method that performs the lookup on LPMSirenKit's local cache, GETLinkForRelationship:ofEntityWithGUID:withParameters:completion:error: will return nil instead of a valid NSURLSessionDataTask and an error code of SirenKitError_ErrorCode_LinkNotFound is given in the NSError parameter.

Submit Actions

You can submit actions by using the LPMSirenActionModel with a dictionary of parameters:

[sirenSessionManager HTTPActionWithSirenAction:sirenActionModel withParameters:parameters completion:^(LPMSirenEntityModel *sirenEntityModel, NSError *error) {
  // Check sirenEntityModel and error to determine if request was successful
} error:&error];

Or by using the action's name and the GUID of the entity that owns the action:

[sirenSessionManager HTTPActionWithName:@"action" onEntityWithGUID:@"guid" withParameters:parameters completion:^(LPMSirenEntityModel *sirenEntityModel, NSError *error) {
  // Check sirenEntityModel and error to determine if request was successful
} error:&error];

If the LPMSirenActionModel is not found for the request method that performs the lookup on LPMSirenKit's local cache, HTTPActionWithName:onEntityWithGUID:withParameters:completion:error: will return nil instead of a valid NSURLSessionDataTask and an error code of SirenKitError_ErrorCode_ActionNotFound is given in the NSError parameter.

LPMSirenKit will attempt to map the parameters given for an action request to the fields associated with that action. Any keys in the parameters dictionary that do not have corresponding LPMSirenFieldModels for the specified LPMSirenActionModel will be ignored in the request (matched by the name property). If you try to set the value of a hidden field, this will be ignored in the request. LPMSirenKit also attempts to match types. For example, if a field indicates that it is a number or url input type, LPMSirenKit validates that the value given for these keys matches the same type (i.e. NSNumber or NSURL). If the type does not match, an error code of SirenKitError_ErrorCode_FieldTypeMismatch is given in the NSError parameter.

Authenticated APIs

Are you interacting with an authenticated Siren API? Cool! We (at Lonely Planet) are as well. LPMSirenSessionManager supports the use of a HTTP Authorization header. Simply set the authorizationHeaderValue property and all subsequent requests will include the header:

sirenSessionManager.authorizationHeaderValue = @"Bearer some-hex-string";

What's a GUID?

Each entity requires a globally unique identifier. However, different APIs use different identifiers and, within the same API, different types/kinds of entities can use different identifiers. LPMSirenSessionStore has a method that allows the client to specify where these GUIDs can be found for each kind of entity.

[LPMSirenSessionStore setGUIDMappingDictionary:@{
                                              @"order": @"properties.orderNumber",
                                              @"items, collection": @"href",
                                              @"info, customer": @"properties.customerId"
                                              }];

In the above scenario, the key should match the entity's class. The value will be the path for the identifier after the response is parsed into LPMSirenEntityModels, LPMSirenLinkModels, or LPMSirenActionModels.

If I would like to make a place/collection entity's GUID that entity's 'self' link, the mapping may look like this:

@"places, collection": @"sirenLinks[0].href" // First link is usually 'self'

Or

@"places, collection": @"sirenLinks[@rel~self].href" // A link whose rel property contains the 'self' identifier; This means rel could be "self" or "this, self" and it would be found

Or even

@"places, collection": @"sirenLinks[@rel=self].href" // A link whose rel property is equal to the 'self' identifier; This means rel has to be "self" to be found

Core Data Dependency

LPMSirenKit currently uses Core Data to cache the Siren related metadata when parsing responses from the server. This is used to help quickly recall what entities, links, and actions a server supports quickly before subsequent requests. LPMSirenKit uses an embedded data store that you as a developer will not have to worry about or maintain. For more information about this data store, check out the LPMSirenKit.xcdatamodeld, ManagedSirenEntity, ManagedSirenLink, ManagedSirenField, and/or ManagedSirenAction.

Requirements

LPMSirenKit depends on several other libraries: AFNetworking, CoreDataMate, LPMJSONUtils, and Mantle. These are included as dependencies in the .podspec and will be installed upon running pod install after adding LPMSirenKit to your Podfile.

Installation

LPMSirenKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'LPMSirenKit'

Author

Todd Grooms, [email protected]

License

LPMSirenKit is available under the MIT license. See the LICENSE file for more info.