Skip to content
This repository has been archived by the owner on Jul 14, 2019. It is now read-only.

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Felix Jendrusch committed Apr 20, 2015
1 parent 0c946f1 commit 97e2967
Showing 1 changed file with 18 additions and 93 deletions.
111 changes: 18 additions & 93 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,28 @@
# Pistachio

Pistachio is a generic model framework for Swift. By leveraging [lenses](http://chris.eidhof.nl/posts/lenses-in-swift.html) and value transformers, it allows you to create type safe adapters for any recursive data structure, be it JSON, YAML or XML.
Pistachio is a generic model framework. By leveraging [lenses](http://chris.eidhof.nl/posts/lenses-in-swift.html) and value transformers, it allows you to create type safe adapters for any recursive data structure, be it JSON, YAML or XML.

If you are already familiar with [Argo](https://github.com/thoughtbot/Argo), take a look at [Pistachiargo](https://github.com/felixjendrusch/Pistachiargo).

## Installation

### Carthage

[Carthage](https://github.com/Carthage/Carthage) is a simple, decentralized dependency manager for Cocoa. You can install it with [Homebrew](http://brew.sh) using the following commands:

```
$ brew update
$ brew install carthage
```
[Carthage](https://github.com/Carthage/Carthage) is a simple, decentralized dependency manager for Cocoa.

1. Add Pistachio to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile):

```
github "felixjendrusch/Pistachio" ~> 0.1
github "felixjendrusch/Pistachio" ~> 0.2
```

2. Run `carthage update` to fetch and build Pistachio and its dependencies.

3. On your application target's "General" settings tab, in the "Linked Frameworks and Libraries" section, add the following frameworks from the [Carthage/Build](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#carthagebuild) folder on disk:
- `Pistachio.framework`

4. On your application target's "Build Phases" settings tab, click the "+" icon and choose "New Run Script Phase". Create a Run Script with the following contents:
```
/usr/local/bin/carthage copy-frameworks
```
and add the following paths to the frameworks under "Input Files":
```
$(SRCROOT)/Carthage/Build/iOS/LlamaKit.framework
$(SRCROOT)/Carthage/Build/iOS/Pistachio.framework
```
This script works around an [App Store submission bug](http://www.openradar.me/radar?id=6409498411401216) triggered by universal binaries.
3. [Make sure your application's target links against `Pistachio.framework` and copies all relevant frameworks into its application bundle (iOS); or embeds the binaries of all relevant frameworks (Mac).](https://github.com/carthage/carthage#getting-started)

## Usage

Let's start with defining a simple model:
Let's start by defining a very simple model:

```swift
struct Origin {
Expand Down Expand Up @@ -84,118 +68,59 @@ struct PersonLenses {
}
```

They can be used to access and modify your model:
It can be used to access and modify your model:

```swift
var person = Person(name: "Felix", origin: Origin(city: "Berlin"))
person = set(PersonLenses.name, person, "Robb")
get(PersonLenses.name, person) // == "Robb"
```

And you can compose, lift, transform, [...](https://github.com/felixjendrusch/Pistachio/blob/master/Pistachio/Lens.swift) them:
And you can [compose, lift, etc.](https://github.com/robb/Monocle/blob/master/Monocle/Lens.swift) them:

```swift
let composed = PersonLenses.origin >>> OriginLenses.city
person = set(composed, person, "New York")
get(composed, person) // == "New York"
```

```swift
var persons = [ person ]

let arrayLifted: Lens<[Person], [String]> = lift(composed)
persons = set(arrayLifted, [ person ], [ "San Francisco" ])
get(arrayLifted, persons) // == [ "San Francisco" ]
```

```swift
var result: Result<[Person], NSError> = success(persons)

let resultLifted: Lens<Result<[Person], NSError>, Result<[String], NSError>> = lift(arrayLifted)
result = set(resultLifted, result, success([ "London" ]))
get(resultLifted, result) // == .Success(Box([ "London" ]))
```

```swift
let valueTransformer: ValueTransformer<String, Int> = SocialSecurityNumberValueTransformer

let transformed = transform(PersonLenses.name, valueTransformer)
person = set(transformed, person, 1234567890)
get(PersonLenses.name, person) // == "Felix"
```

Value transformers can be flipped, composed and lifted:

```swift
let flipped = flip(valueTransformer)
flipped.transformedValue(1234567890) // == "Felix"
```

```swift
let composed = flipped >>> UppercaseValueTransformer
flipped.transformedValue(1234567890) // == "FELIX"
```

```swift
let dictionaryLifted = lift([ "Felix": 1234567890 ], 0, "Unknown")
dictionaryLifted.transformedValue("Felix") // == 1234567890
dictionaryLifted.transformedValue("Hans") // == 0
dictionaryLifted.reverseTransformedValue(1234567890) // == "Felix"
dictionaryLifted.reverseTransformedValue(0) // == "Unknown"
```

```swift
let optionalLifted = lift(UppercaseValueTransformer, "")
optionalLifted.transformedValue("Felix") // == "FELIX"
optionalLifted.transformedValue(nil) // == ""
optionalLifted.reverseTransformedValue("FELIX") // == "felix"
optionalLifted.reverseTransformedValue("") // == nil
```

```swift
let arrayLifted = lift(UppercaseValueTransformer)
arrayLifted.transformedValue([ "Felix", "Robb" ]) // == [ "FELIX", "ROBB" ]
```

With lenses and value transformers, you can create adapters for your models:

```swift
struct Adapters {
static let origin = DictionaryAdapter(specification: [
"city_name": transform(OriginLenses.city, StringToAnyObjectValueTransformers)
], dictionaryTansformer: DictionaryToAnyObjectValueTransformers)
"city_name": map(OriginLenses.city, StringToAnyObjectValueTransformers)
], dictionaryTansformer: DictionaryToAnyObjectValueTransformers, value: Origin())

static let person = DictionaryAdapter(specification: [
"name": transform(PersonLenses.name, StringToAnyObjectValueTransformers),
"origin": transform(PersonLenses.origin, lift(origin, Origin()))
], dictionaryTansformer: DictionaryToAnyObjectValueTransformers)
"name": map(PersonLenses.name, StringToAnyObjectValueTransformers),
"origin": map(PersonLenses.origin, origin)
], dictionaryTansformer: DictionaryToAnyObjectValueTransformers, value: Person())
}
```

Uh, what was that? Right, the `origin` adapter was lifted into a value transformer.

Use `fix` to create adapters for recursive models:

```swift
let adapter: DictionaryAdapter<Model, Data, Error> = fix { adapter in
let adapter: DictionaryAdapter<Key, Value, TransformedValue, Error> = fix { adapter in
// use `adapter` to reference the currently created adapter
}
```

Adapters handle encoding to and decoding from data:
Adapters handle transforming and reverse transforming your models:

```swift
let adapter = Adapters.person

var person = Person(name: "Seb", origin: Origin(city: "Berlin"))
var data = adapter.encode(person)
var data = adapter.transform(person)
// == .Success(Box([ "name": "Seb", "origin": [ "city_name": "Berlin" ] ]))

adapter.decode(Person(), from: data.value!)
adapter.reverseTransform(data.value!)
// == .Success(Box(person))
```

Both `encode` and `decode` return a [`LlamaKit.Result`](https://github.com/LlamaKit/LlamaKit/blob/master/LlamaKit/Result.swift), which either holds the encoded/decoded value or an error. This enables you to gracefully handle coding errors.
Both `transform` and `reverseTransform` return a [`Result`](https://github.com/antitypical/Result/blob/master/Result/Result.swift), which either holds the (reverse) transformed value or an error. This enables you to gracefully handle transformation errors.

## Posts

Expand Down

0 comments on commit 97e2967

Please sign in to comment.