Skip to content

Commit

Permalink
Merge pull request #82 from mutualmobile/cnstoll_documentationUpdates
Browse files Browse the repository at this point in the history
documentation updates
  • Loading branch information
cnstoll committed Jun 27, 2014
2 parents 9b029f0 + eb993d5 commit c5eeaca
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 3 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
#MMRecord Changelog

##[1.4.0](https://github.com/mutualmobile/MMRecord/issues?milestone=6&state=closed) (Friday, June 27th, 2014)
**New**
* Improved support for sub-entity inheritance. [#50](https://github.com/mutualmobile/MMRecord/issues/50) (Andrea Cremaschi)
* Improved support for sub-entity inheritance in relationships. [#52](https://github.com/mutualmobile/MMRecord/pull/52) (Ian Dundas)
* Added logging and tracking of Core Data errors. [#53](https://github.com/mutualmobile/MMRecord/issues/53) (Viktor Krykun)
* Improved error handling for invalid response formats. [#54](https://github.com/mutualmobile/MMRecord/pull/54) (Jeremy Hilts)
* Added support for MMRecordOptions and the entityPrimaryKeyInjectionBlock in AFMMRecordResponseSerializer. [#56](https://github.com/mutualmobile/MMRecord/issues/56) (Ian Dundas, Jon Brooks, Conrad Stoll)
* Added a new subclassing option for customizing the primary key for a representation. [#58](https://github.com/mutualmobile/MMRecord/pull/58) (Conrad Stoll)
* Added a new MMRecordDebugger class for improving the MMRecord debugging experience. [#59](https://github.com/mutualmobile/MMRecord/pull/59) (Conrad Stoll)
* Added support for merging duplicate dictionaries that represent a single record. [#60](https://github.com/mutualmobile/MMRecord/pull/60) (Andrea Cremaschi and Conrad Stoll)
* Added support for Swift, and a new MMRecordAtlassian example project written in Swift. [#74](https://github.com/mutualmobile/MMRecord/pull/74) (Conrad Stoll)
* Added logging to handle an issue where setting an existing relationship may invalidate an existing inverse relationship. [#75](https://github.com/mutualmobile/MMRecord/issues/75) (Alex Malek)
* Added support for Facebook Tweaks. [#77](https://github.com/mutualmobile/MMRecord/pull/77) (Conrad Stoll)

**Fixed**
* **FIXED** an issue([#45](https://github.com/mutualmobile/MMRecord/issues/45)) where the AFMMRecordResponseSerializer did not pass through AFNetworking 2.0 errors. (Brian Watson)
* **FIXED** an issue([#46](https://github.com/mutualmobile/MMRecord/issues/46)) where the AFMMRecordResponseSerializer did not handle root level response objects. (Andrea Cremaschi)
* **FIXED** an issue([#55](https://github.com/mutualmobile/MMRecord/pull/55)) where the MMRecordMarshaler did not iterate through all potential key paths. (Nick Bolton)


##[1.3.0](https://github.com/mutualmobile/MMRecord/issues?milestone=6&state=closed) (Tuesday, March 4th, 2014)
**New**
* Added a new way to inject a primary key into the population system. [#41](https://github.com/mutualmobile/MMRecord/pull/41) (Conrad Stoll)
Expand Down
2 changes: 1 addition & 1 deletion MMRecord.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'MMRecord'
s.version = '1.3.0'
s.version = '1.4.0'
s.license = 'MIT'
s.summary = 'A simple block based web service integration library.'
s.homepage = 'https://github.com/MutualMobile/MMRecord'
Expand Down
143 changes: 141 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@ Keep reading to learn more about how to start using MMRecord in your project!
- [Download MMRecord](https://github.com/mutualmobile/MMRecord/archive/master.zip) and try out the included example apps.
- Continue reading the integration instructions below.
- Check out the [documentation](http:https://mutualmobile.github.com/MMRecord/Documentation/) for all the rest of the details.
- Review the [examples](https://github.com/mutualmobile/MMRecord#example-usage) below for inspiration on specific usage.
- Read about MMRecord's support for [Swift](https://github.com/mutualmobile/MMRecord#swift-examples) and [Tweaks](https://github.com/mutualmobile/MMRecord#tweaks).
- If you run into any issues, check out some useful [debugging](https://github.com/mutualmobile/MMRecord#debugging) tips.
---
##Installing MMRecord
<img src="https://cocoapod-badges.herokuapp.com/v/MMRecord/badge.png"/><br/>
You can install MMRecord in your project by using [CocoaPods](https://github.com/cocoapods/cocoapods):
```Ruby
pod 'MMRecord', '~> 1.3.0'
pod 'MMRecord', '~> 1.4.0'
```

## Overview
Expand Down Expand Up @@ -256,6 +259,7 @@ For reference, here's a truncated version of the App.net User object to illustra
```

## Example Usage
Here's a few examples of the various types of requests you can make with MMRecord. Notice that AFMMRecordResponseSerializer is a subspec of MMRecord.

### Standard Request

Expand Down Expand Up @@ -381,6 +385,7 @@ sessionManager.responseSerializer = serializer;
```

## MMRecordOptions Examples
`MMRecordOptions` is a way to customize the behavior of a request. One of the ways you can use it is to specify blocks that apply to the following request after you specify a set of options. This allows you to do things like insert a new primary key for a record or specify orphan deletion behaviors.

### Primary Key Injection

Expand Down Expand Up @@ -442,6 +447,102 @@ options.deleteOrphanedRecordBlock = ^(MMRecord *orphan,
failureBlock:failureBlock];
```

## Swift Examples
While MMRecord is implemented in Objective-C, you can also use the library from to build your model in Swift. The main thing you should be aware of when building your model in Swift is that entity managed object class names need to be fully namespaced. An example of that is below.

<p align="center">
<img src="https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-swift.png") alt="MMRecord Model Configuration for Swift"/>
</p>

Note that MMRecordAtlassian is used as the namespace for the Issue class in Swift. This is because the default namespace is the product name for your project. Please be aware that using special characters or spaces in your product name may lead to issues here. Typically those characters get replaced by underscores in your namespace, but for best results, simply use a single word for your product name to avoid issues.

You should also remember to import MMRecord.h, and any of its subspecs you use, in your Objective-C Bridging Header. Then, you're ready to go building your MMRecord model in Swift!

Here's a few examples of using MMRecord in Swift.

### Swift MMRecord Subclass Implementation

```swift
import CoreData

class Plan: ATLRecord {
@NSManaged var name: NSString
@NSManaged var id: NSString

override class func keyPathForResponseObject() -> String {
return "plans.plan"
}
}
```

### Standard Swift Request

```swift
Plan.startRequestWithURN("/plans",
data: nil,
context: managedObjectContext,
domain: self,
resultBlock: {records in
var results: Plan[] = records as Plan[]

self.plans = results
self.tableView.reloadData()
},
failureBlock: { error in

})
```

### Swift Request with MMRecordOptions

```swift
var options = Issue.defaultOptions()

options.entityPrimaryKeyInjectionBlock = {(entity, dictionary, parentProtoRecord) -> NSCopying in
let dict = dictionary as Dictionary
let key: AnyObject? = dict["id"]
let returnKey = key as String
return returnKey
}

options.recordPrePopulationBlock = { protoRecord in
let proto: MMRecordProtoRecord = protoRecord
let entity: NSEntityDescription = protoRecord.entity

var dictionary: AnyObject! = proto.dictionary.mutableCopy()
var mutableDictionary: NSMutableDictionary = dictionary as NSMutableDictionary
var primaryKey: AnyObject! = ""

if (entity.name == "OutwardLink") {
primaryKey = mutableDictionary.valueForKeyPath("outwardIssue.key")
}

if (entity.name == "InwardLink") {
primaryKey = mutableDictionary.valueForKeyPath("inwardIssue.key")
}

mutableDictionary.setValue(primaryKey, forKey: "PrimaryKey")

proto.dictionary = mutableDictionary
}

Issue.setOptions(options)

Issue.startRequestWithURN("/issue",
data: nil,
context: managedObjectContext,
domain: self,
resultBlock: { records in
var results: Issue[] = records as Issue[]

self.results = results
self.tableView.reloadData()
},
failureBlock: { error in

})
```

## Tweaks

MMRecord also provides the TweakModel subspec that implements support for Facebook Tweaks. You can use Tweaks to modify most MMRecord parsing and population parameters. This can be useful if you're working on an app where the API is in flux and is still being actively developed. The UI for Tweaks will show you a list of MMRecord entities in your data model, the primary key for each entity, all of the keys used to populate various attributes, and the key path that points to instances of that entity in the data model. Here's how you use it.
Expand All @@ -461,9 +562,47 @@ After its setup, here's what the Tweaks UI looks like with MMRecord.
<img src="https://www.github.com/mutualmobile/MMRecord/raw/gh-pages/Images/MMRecord-tweaks.png") alt="MMRecord Tweaks UI"/>
</p>
## Debugging
`MMRecordDebugger` is a class used by `MMRecord` to provide debugging information back to you about how your model is configured and how MMRecord is handling the response handed to it by your server class. You can use MMRecordDebugger to help resolve issues that may exist in your model configuration, or identify inconsistencies with your response format.
MMRecord is designed to make it as fast and easy as possible to serialize managed objects from a web service. One of the goals of the library is to provide meaningful means of customization to support all sorts of response formats, while still maintaining an easy to use primary interface that does not require excessive configuration and setup. In most cases, the amount of configuration and customization required by a user of MMRecord will depend on how complex the response format of your web service is.
When MMRecord encounters an error while handling a request it may take a few measures based on the severity of the error.
- Assertions. In some cases, like if a managed object class being populated is not a subclass of MMRecord, an assertion will be thrown.
- Logs. In many cases, MMRecord will log a message containing the error to the console. By default MMRecord will not actually print anything to the console, unless you specify a logging level manually. This is for security reasons.
- Non-failure Errors. In some cases, MMRecord will create an `NSError` describing an issue, and associate it with the `MMRecordDebugger`. However, if the error isn't serious enough, the request will not fail.
- Failure Errors. In several cases, MMRecord will create an `NSError` describing a critical issue it encountered while handling a request. These errors are associated with the debugger, and will be passed back into the failureBlock indicating a reason that the request failed.
If you encounter issues with a request, your first step should be to enable MMRecord logging, using the command below.
```objective-c
[MMRecord setLoggingLevel:MMRecordLoggingLevelAll];
```

You can lower the logging level incrementally to receive finer grained logging information, but its a good idea to start with the highest level to get a broader picture of what is going on.

If your request is failing, you can use the `NSError` object that is passed into the failure block to review all sorts of data about the failure. The error parameter in the failure block will actually include the `MMRecordDebugger` instance, which contains all of the errors encountered while handling the request, and various bits of state relevant to the critical error.

The debugger is attached to the `NSError` in its userInfo dictionary. Here's an example of how you can use it.

```objective-c
failureBlock:^(NSError *error) {
NSDictionary *recordDictionary = [[error userInfo] valueForKey:MMRecordDebuggerParameterRecordDictionary];
MMRecordDebugger *debugger = [[error userInfo] valueForKey:MMRecordDebuggerKey];
NSArray *allErrors = [debugger errorsEncounteredWhileHandlingResponse];
id responseObject = [debugger responseObject];
NSString *entityName = [[debugger initialEntity] name];
}];
```
If you encounter errors that you would like to see tracked, or have suggestions about the severity of some errors, please create an issue or file a pull request.
## Requirements
MMRecord 1.3.0 and higher requires either [iOS 6.0](https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS6.html) and above, or [Mac OS 10.8](https://developer.apple.com/library/mac/releasenotes/macosx/whatsnewinosx/Articles/MacOSX10_8.html) ([64-bit with modern Cocoa runtime](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html)) and above.
MMRecord 1.4.0 and higher requires either [iOS 6.0](https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS6.html) and above, or [Mac OS 10.8](https://developer.apple.com/library/mac/releasenotes/macosx/whatsnewinosx/Articles/MacOSX10_8.html) ([64-bit with modern Cocoa runtime](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html)) and above.
### ARC
Expand Down

0 comments on commit c5eeaca

Please sign in to comment.