Skip to content

Instantly share code, notes, and snippets.

@SimplGy
Last active May 17, 2016 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SimplGy/860c71978176dc1c2a67437fdf568ae4 to your computer and use it in GitHub Desktop.
Save SimplGy/860c71978176dc1c2a67437fdf568ae4 to your computer and use it in GitHub Desktop.
An Experiment working on Enforced Symmetricality with JohnSundell's Wrap+Unbox
//
// A definition for the kind of model objects this library can work on
//
import Foundation
public protocol CollieModel: Unboxable, WrapCustomizable, Hashable, CustomStringConvertible {
/// Configure the mapping between client and server property names. keys are client names and values are JSON names eg: "authorId: "author_id"
static var propertyMapping: [String: String]? { get }
}
extension CollieModel {
/// Default property mapping is nil (I'd do an optional get-only var protocol requirement but the language doesn't allow it)
static var propertyMapping: [String:String]? { return nil }
/**
This is the default implementation of value equality for models.
If you have a faster way to do value comparison for your model type feel free to override it.
- parameter otherModel: Another homogenous model to compare to
- returns: true if every property is the same between both models
*/
func sameValueAs<T: CollieModel>(otherModel: T) -> Bool {
do {
let a: Collie.JSON = try Wrap(self)
let b: Collie.JSON = try Wrap(otherModel)
let same = NSDictionary(dictionary: a).isEqualToDictionary(b)
if !same { Collie.trace("!sameValueAs() \n\(a) \n\(b)") }
return same
} catch {
print("sameValueAs error: \(error)")
return false
}
}
/**
Check to see if this object is symmetrical--you can turn it into JSON and back, and all the values match
- returns: true if all the values match
*/
func isSymmetrical() -> Bool {
guard let json = self.toJSON() else { return false }
guard let other = Self(json: json, skipSymmetryValidation: true) else { return false }
let isSymmetrical = self.sameValueAs(other)
Collie.trace("[\(json["id"] ?? "")].isSymmetrical()? \(isSymmetrical)")
return isSymmetrical
}
func toJSON() -> Collie.JSON? {
do {
let json: Collie.JSON = try Wrap(self)
return json
} catch {
print("toJSON() error: \(error)")
return nil
}
}
init?(json: Collie.JSON, skipSymmetryValidation: Bool = false) {
do {
self = try Unbox(json)
if !skipSymmetryValidation { self.isSymmetrical() }
} catch {
print("init?(json:) error: \(error)")
return nil
}
}
static func getKey(key: String) -> String { return Self.propertyMapping?[key] ?? key }
func keyForWrappingPropertyNamed(propertyName: String) -> String? {
return Self.getKey(propertyName)
}
}
//
// An Example model
//
class GooglePlace: CollieModel {
let id: String
let name: String
let rating: Double
let thumbnailUrl: String
static let propertyMapping: [String : String]? = [
"id": "place_id",
"thumbnailUrl": "icon",
]
required init(unboxer: Unboxer) {
id = unboxer.unbox( GooglePlace.getKey("id") )
name = unboxer.unbox( GooglePlace.getKey("name") )
rating = unboxer.unbox( GooglePlace.getKey("rating") )
thumbnailUrl = unboxer.unbox( GooglePlace.getKey("thumbnailUrl") )
}
}
@SimplGy
Copy link
Author

SimplGy commented May 17, 2016

Revision 4 now has symmetry enforced for simple property renaming cases. I'd still like to slim down that required init boilerplate though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment