Started with some Wiki pages

This commit is contained in:
Pepi 2015-11-12 18:26:36 +01:00
parent 5471d99e19
commit 613f043663
11 changed files with 186 additions and 11 deletions

View File

@ -51,16 +51,6 @@ The library is maintained by [@pepibumur](https://github.com/pepibumur) under [G
- [ ] CoreDataDefaultStorage tests
- [ ] Request fluent interface
- [ ] Documentation (Jazzy): *Make sure all the components are documented*
- [ ] Create 2.0 Wiki:
- Setup:
- CoreData
- Carthage
- Getting started
- Storages. Build your own!
- Fetching
- Operations
- Testing
- Good practices
- [ ] Create Contribution document
- Make tasks
- Style guideline

View File

@ -1,7 +1,8 @@
import Foundation
import ReactiveCocoa
import Result
public struct Request<T> {
public struct Request<T: Entity> {
// MARK: - Attributes
@ -22,6 +23,17 @@ public struct Request<T> {
// MARK: - Public
func inContext(context: Context) -> Result<[T], Error> {
return context.fetch(self)
}
func inStorage(storage: Storage) -> Result<[T], Error> {
storage.mainContext.fetch(self)
return Result(error: Error.InvalidType)
}
// func inContext(context: Context) -> ([T], Error?) {
// return context.fetch(self)
// }

13
Wiki/README.md Normal file
View File

@ -0,0 +1,13 @@
SugarRecord Wiki
===================
Welcome to the SugarRecord Wiki. You'll find here useful documents about how to use SugarRecord in your projects. Here's the list of available documents:
- [Setup SugarRecord in your project](setup.md)
- [Design principles](principles.md)
- [Getting started](started.md)
- [Concepts](concepts.md)
- [Storages. Build your own!](storages.md)
- [Operations](operations.md)
- [Testing](testing.md)
- [Good practices](practices.md)

36
Wiki/concepts.md Normal file
View File

@ -0,0 +1,36 @@
Concepts
============
## Storage
A **storage** represents a database setup configuration. Thinking about CoreData it represents the persistent store, coordinator, and all the context needed for operations. In case of Realm it's much simpler, just a Realm. SugarRecord defines Storage as a protocol whose interface is shown below:
```swift
var type: StorageType { get } // .Realm / .CoreData
var mainContext: Context! { get }
var saveContext: Context! { get }
var memoryContext: Context! { get }
func removeStore() throws
func operation(operation: (context: Context, save: Saver) -> Void, completed: (() -> Void)?)
func operation(queue queue: Queue, operation: (context: Context, save: Saver) -> Void, completed: (() -> Void)?)
```
- **mainContext:** Context for operations in the main thread. Use it for fetching models to be used in the presentation layer
- **saveContext:** Context used for high load operations like persisting data received from an API.
- **memoryContext:** Not persisted context, very useful for testing.
- **removeStore:** Removes the local store.
- **operation:** Define operation blocks and pass them to this function. You can use it for high load operations.
### CoreData
#### CoreDataDefaultStorage
### Realm
#### RealmDefaultStorage
### Build your own Storage
In case the existing storages are not enough for you or you need a different configuration we encourage you to implement your own and propose it to the library. We're opened to help you and included them in the library. *Examples of storages could be for example a CoreData storage with iCloud, Dropbox Storage, ...*
Here you have a document with some tips for designing your [storage](design.md)
## Context

0
Wiki/operations.md Normal file
View File

2
Wiki/practices.md Normal file
View File

@ -0,0 +1,2 @@
Good practices
===============

22
Wiki/principles.md Normal file
View File

@ -0,0 +1,22 @@
Design principles
==========
SugarRecord is designed as a wrapper around existing persistence solutions. Although there're solutions like Realm that offer a clear and easy to use interface (fluent) there are others like CoreData whose setup and operations are not so straightforward. Most of companies and projects end up building their own wrapper around CoreData with their own needs. For most projects, these basic needs are always the same, and having a solution like SugarRecord saves time and more than one headache.
- **Protocol Oriented Design**: Compared with SugarRecord 1.0 where we used the early version of Swift we tried for this version to stick to the Protocol Oriented Programming idea. Most of components have been designed starting from a set of protocols and them extending existing components to add the SugarRecord behaviour. Thanks to this approach we can keep using the elements behind SugarRecord but we add that extra layer, these extra behaviours that make CoreData/Realm/.. easier.
- **Beginner & Advanced users would fall in love**: We designed it to make it easier for beginners but we didn't want to restrict it only for these target of developers. That's why SugarRecord also allows advanced developers to push the wrapper to their limits doing whatever they need.
- **Friendly syntax**: Because we want our code to be readable. We got very inspired here by [Realm](http://realm.io) whose interface is worth of analisys. We wanted to avoid all these lines that you need for example in CoreData to fetch elements from the database. SugarRecord interface is fluent starting from models, thus you can do something like `Person.filteredBy("name", equalTo: "Pedro")` and SugarRecord does the rest.
- **Multi-Platform**: In the last two years we've seen more SDKs coming out, the most recent one, *tvOS*. CoreData and Realm the main supported persistence solutions offer their frameworks for these platforms, why not giving support to them? You can enjoy using CoreData building your app for AppleTV or your OSX app, SugarRecord is multi platform.
- **Flexible**: One idea we loved from our version 1.0 and that we wanted to keep here was the customization freedom. Although we offer some defined Storages *(stacks in SugarRecord 1.0)* for Realm and CoreData, `Storage` is a protocol, you can implement your own CoreData configuration or even any other persistence solution. SugarRecord is just the wrapper! :tada:
- **Code and quality and TDD**: Compared with other frameworks that we can find in the community we didn't want to end up with a library and tons of tasks for adding tests. SugarRecord is designed and implemented starting from tests, the library is fully covered with unit tests to ensure stability on these apps that are using SugarRecord. We strongly encourage new contributors to stick to these coding style. *Thanks [Quick](https://github.com/Quick/Quick) and [Nimble](https://github.com/Quick/Nimble) for their great frameworks we used for testing SugarRecord*s
- **Actively Supported**: Something we admit we didn't do on the right way with the version 1.0 was giving an active support. The language was changing faster than we could afford and we ended up leaving the project on hold. This time the language is much more stable, and we're building a group of contributors that actively will support the library to make it a reference in the Swift community. If you are interested in contribute with us, drop me a line [pedro@gitdo.io](mailto://pedro@gitdo.io)
- **Reactive**: Something that 1.0 didn't have and that we wanted for this version is having a Reactive interface. We offer it as a complement for these developer that use *Functional Reactive Programming* concepts in their projects. If you haven't heard about it yet or haven't use it before SugarRecord could be a great opportunity to play with it. *Thanks here to [ReactiveCocoa](https://github.com/reactivecocoa/reactivecocoa) for its incredible Framework that brings Reactive concepts to Swift*
- **Anti singleton, shared states**: SugarRecord doesn't offer shared instances, or default stacks. We removed that and instead we leave that responsibility to the developer. We strongly think that a Singleton based design is something de developer has to decide depending on the context where it's using the library. SugarRecord can perfectly work without shared instances but it's not closed to them, you can use them!

41
Wiki/setup.md Normal file
View File

@ -0,0 +1,41 @@
Setup
=======
SugarRecord supports integration using the two main dependency managers for Swift/Objectiv-C, [CocoaPods](https://cocoapods.org) and [Carthage](https://github.com/carthage/carthage). Decide which one fits with your project and follow the steps below.
> We recommend you to use the same dependency manager you've used for other dependencies in your project.
## CocoaPods
1. The first think you need is having CocoaPods installed. In case you don't have it you can install it with `gem install cocoapods`
2. Once installed you have to add the following line to your `Podfile`:
```ruby
pod 'SugarRecord', :git => 'https://github.com/gitdoapp/sugarrecord.git'
```
3. Then execute `pod install` and CocoaPods will fetch your dependencies and integrate them with your project using a `Workspace`
4. Open your project using the `.xcworkspace` file.
### Subspecs
If you follow the steps above you'll integrate SugarRecord with all the persistence solutions available. If you want only one of them you can specify thanks to the defined subspecs in the project:
```
pod 'SugarRecord/CoreData', :git => 'https://github.com/gitdoapp/sugarrecord.git'
pod 'SugarRecord/Realm', :git => 'https://github.com/gitdoapp/sugarrecord.git'
```
## Carthage
If you prefer to use `Carthage` the follow these steps:
1. Install Carthage if you didn't have it installed with `brew install carthage`
2. Once completed edit your `Cartfile` and add the dependency:
```ruby
github 'gitdoapp/sugarrecord'
```
3. Execute the command `carthage update` and Carthage will fetch the dependency and compile them under `/Carthage/Build`
4. Follow the steps [here](https://github.com/carthage/carthage) to add this compiled frameworks into your project.
### Platforms
SugarRecord is available for *iOS/OSX/watchOS/tvOS*, you'll find these frameworks in respective folders inside `/Carthage/Build`. If your project conforms only to only one of these platforms then use the proper framework. You don't need all of them
> Don't forget to drag all the compiled frameworks. Some of them might be internal dependencies of SugarRecord and without them the project could not compile.

57
Wiki/started.md Normal file
View File

@ -0,0 +1,57 @@
Getting started
============
## Storage
### CoreData
Create an instance of the `CoreDataDefaultStorage`
```swift
let storage = try! CoreDataDefaultStorage(store: .Named("mydb.sqlite"), model: .Merged(nil), migrate: true)
```
### Realm
Create an instance of the `RealmDefaultStorage`
```swift
let storage = try! RealmDefaultStorage()
```
## Fetching
You can fetch models directly using the available interface around models like the examples shown below:
```swift
let person = Person.filteredWith("name", equalTo: "pedro").inStorage(storage).value.first
let people = Person.sortedBy(sortDescriptor: NSSortDescriptor(key: "name": ascending: true)).value
```
You can check all the available methods in the library [**reference**](http://blog.gitdo.io/SugarRecord/). Look for `Requestable` protocol and `Request` struct components.
> If you think would be great to add another method to that interface drop me a line, [pedro@gitdo.io](mailto://pedro@gitdo.io), the idea is evolve it according to the developers needs.
**Notes**
- Fetch results are returned as a generic type `Result<[T], Error>` that wraps the fetching result and the error. If you want to unwrap the error or the value you can use its properties `value` and `error` respectively as shown above.
- The returned value is always an array, in case you expect one value, use the first element of that array. Keep in mind that that value is an optional and might be nil.
## Saving/Deleting
Saving and deleting operation must be executed using the operation method of your storage. Its use is very simple as show below:
```swift
storage?.operation({ (context, save) -> Void in
for apiIssue in apiIssues {
let issue: Issue! = context.insert().value
issue.identifier = apiIssue.identifier
issue.name = apiIssue.name
}
save()
}, completed: { () -> Void in
// YAI!
})
```
1. When the method is called you pass an operation. An operation is a closure with a `context` as an `save` as input parameters:
- **Context:** It's the entry point to your storage. It defines `insert/delete/fetch` methods.
- **Save:** It's a closure that you have to call if you want to persist your changes. Otherwise your changes won't be persisted.
2. Then the operation is completed the storage calls your `completed` closure in case you need to do something after these operations complete.

0
Wiki/storages.md Normal file
View File

2
Wiki/testing.md Normal file
View File

@ -0,0 +1,2 @@
Unit testing with SugarRecord
============================