Last active
May 17, 2016 18:51
-
-
Save SimplGy/860c71978176dc1c2a67437fdf568ae4 to your computer and use it in GitHub Desktop.
An Experiment working on Enforced Symmetricality with JohnSundell's Wrap+Unbox
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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") ) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Revision 4 now has symmetry enforced for simple property renaming cases. I'd still like to slim down that
required init
boilerplate though.