Commit c1085960 authored by Mauro E. Bender's avatar Mauro E. Bender Committed by Mauro E. Bender

Close #1 - Get a resource item

Get a resource item by an identifier through the API.

Example: Get the item with id 1 from the "items" resource:

```swift
let api = Api( baseURL: <Api URL>, apiPath: "1" )
api.resource( "items" ).item( 1 ) { ( item: Item ) in
   print( "Got item \(item.id)")
}
```
parent 512ed61d
//
// Api.swift
// Pods
//
// Created by Mauro Bender on 13/8/16.
//
//
import Alamofire
public typealias ApiMethod = Alamofire.Method
public class Api {
let baseURL: NSURL
let apiPath: String
var apiURL: NSURL { return baseURL.URLByAppendingPathComponent( apiPath ) }
public init( baseURL: NSURL, apiPath: String ) {
self.baseURL = baseURL
self.apiPath = apiPath
}
// RESOURCE
public func resource<T>( path: String ) -> Resource<T> {
return Resource( api: self, path: path )
}
// REQUESTS
public func request( method: ApiMethod, path: String,
parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL,
headers: [String: String]? = nil, completion: Response<AnyObject, NSError> -> Void )
{
Alamofire.request( method, urlForPath( path ).absoluteString, parameters: parameters,
encoding: encoding, headers: headers ).responseJSON( completionHandler: completion )
}
public func get( path: String, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL,
headers: [String: String]? = nil, completion: Response<AnyObject, NSError> -> Void )
{
return request( .GET, path: path, parameters: parameters, encoding: encoding,
headers: headers, completion: completion)
}
public func post( path: String, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL,
headers: [String: String]? = nil, completion: Response<AnyObject, NSError> -> Void )
{
return request( .POST, path: path, parameters: parameters, encoding: encoding,
headers: headers, completion: completion)
}
func urlForPath( path: String ) -> NSURL {
return apiURL.URLByAppendingPathComponent( path )
}
}
// MARK: Equatable
extension Api: Equatable {}
public func ==(lhs: Api, rhs: Api) -> Bool {
return lhs.baseURL == rhs.baseURL && lhs.apiPath == rhs.apiPath
}
\ No newline at end of file
//
// Resource.swift
// Pods
//
// Created by Mauro Bender on 13/8/16.
//
//
import Alamofire
public protocol JSONSerializable {
init( fromJSON json: [ String: AnyObject ] )
func toJSON() -> [ String: AnyObject ]
}
public class Resource<T: JSONSerializable> {
public let api: Api
public let path: String
init( api: Api, path: String ) {
self.api = api
self.path = path
}
public func item( id: AnyObject, parameters: [ String: String ]? = nil,
headers: [ String: String]? = nil, success: ( ( T ) -> Void ) )
{
api.get( resourceMemberPath( id ), parameters: parameters, headers: headers ) { response in
if let json = response.result.value {
success( T( fromJSON: json as! [String : AnyObject] ) )
}
}
}
func resourceMemberPath( memberId: AnyObject ) -> String {
return "\(path)/\(memberId)"
}
}
\ No newline at end of file
This diff is collapsed.
# frozen_string_literal: true
# A sample Gemfile
source "https://rubygems.org"
gem 'cocoapods', git: 'https://github.com/CocoaPods/CocoaPods.git'
GIT
remote: https://github.com/CocoaPods/CocoaPods.git
revision: 1bf338273637cf658e78388ca996cebabbce12db
specs:
cocoapods (1.1.0.beta.1)
activesupport (>= 4.0.2, < 5)
claide (>= 1.0.0, < 2.0)
cocoapods-core (= 1.1.0.beta.1)
cocoapods-deintegrate (>= 1.0.0, < 2.0)
cocoapods-downloader (>= 1.1.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-stats (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.0.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored (~> 1.2)
escape (~> 0.0.4)
fourflusher (~> 1.0.1)
gh_inspector (~> 1.0)
molinillo (~> 0.5.0)
nap (~> 1.0)
xcodeproj (>= 1.2.0, < 2.0)
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.7.1)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
claide (1.0.0)
cocoapods-core (1.1.0.beta.1)
activesupport (>= 4.0.2)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.0)
cocoapods-downloader (1.1.0)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.0.0)
nap (>= 0.8, < 2.0)
netrc (= 0.7.8)
cocoapods-try (1.1.0)
colored (1.2)
escape (0.0.4)
fourflusher (1.0.1)
fuzzy_match (2.0.4)
gh_inspector (1.0.2)
i18n (0.7.0)
json (1.8.3)
minitest (5.9.0)
molinillo (0.5.0)
nap (1.1.0)
netrc (0.7.8)
thread_safe (0.3.5)
tzinfo (1.2.2)
thread_safe (~> 0.1)
xcodeproj (1.2.0)
activesupport (>= 3)
claide (>= 1.0.0, < 2.0)
colored (~> 1.2)
PLATFORMS
ruby
DEPENDENCIES
cocoapods!
BUNDLED WITH
1.12.5
use_frameworks!
target 'Api_Example' do
pod 'Api', :path => '../'
def common_pods
pod 'Api', :path => '../'
end
target 'Api_Tests' do
inherit! :search_paths
target 'Api_Example' do
common_pods
end
pod 'Quick', '~> 0.8'
pod 'Nimble', '~> 3.0'
end
target 'Api_Tests' do
common_pods
pod 'Quick', '~> 0.8'
pod 'Nimble', '~> 3.0'
pod 'Mockingjay', '1.1.1'
end
PODS:
- Api (0.1.0)
- Alamofire (3.4.1)
- Api (0.1.0):
- Alamofire (~> 3.4)
- Mockingjay (1.1.1):
- Mockingjay/Core (= 1.1.1)
- Mockingjay/XCTest (= 1.1.1)
- Mockingjay/Core (1.1.1):
- URITemplate (~> 1.3)
- Mockingjay/XCTest (1.1.1):
- Mockingjay/Core
- Nimble (3.2.0)
- Quick (0.9.3)
- URITemplate (1.3.1)
DEPENDENCIES:
- Api (from `../`)
- Mockingjay (= 1.1.1)
- Nimble (~> 3.0)
- Quick (~> 0.8)
......@@ -13,10 +24,13 @@ EXTERNAL SOURCES:
:path: "../"
SPEC CHECKSUMS:
Api: 353b3e560c6b9059ff722d3ecee4d666db86d97e
Alamofire: 01a82e2f6c0f860ade35534c8dd88be61bdef40c
Api: d8f98ef3a30ff61b6a870c447b4feee3e70759ad
Mockingjay: 757f80abc947b5ec2918b1bb14f3066574720430
Nimble: 703854335d181df169bbca9c97117b5cf8c47c1d
Quick: 13a2a2b19a5d8e3ed4fd0c36ee46597fd77ebf71
URITemplate: 398a48d6559e23b77bd41176b675b017ad1fc959
PODFILE CHECKSUM: 3a00c58a320d6d5054ff19c91ee85f0dbccf890d
PODFILE CHECKSUM: 96c182174ea46d3ffa1c95cfcd51266de20b3756
COCOAPODS: 1.0.1
COCOAPODS: 1.1.0.beta.1
////
//// ApiTests.swift
//// Api
////
//// Created by Mauro Bender on 13/8/16.
//// Copyright © 2016 CocoaPods. All rights reserved.
////
import Quick
import Nimble
import Mockingjay
import Api
class ApiTests: QuickSpec {
override func setUp() {
super.setUp()
// Register stubs
stub( matchApiPath( "tests/get", method: .GET ), builder: http( 200 ) )
stub( matchApiPath( "tests/delete", method: .DELETE ), builder: http( 200 ) )
}
override func spec() {
describe( "Api" ) {
let api = Api( baseURL: baseURL, apiPath: apiPath )
describe( "resource" ) {
let resource : Resource<Item> = api.resource( "items" )
it( "should have the correct api" ) { expect( resource.api ) == api }
it( "should have the correct path" ) { expect( resource.path ) == "items" }
}
describe( "request" ) {
it( "should call the correct endpoint with the correct method" ) {
waitUntil { done in
api.request( .DELETE, path: "tests/delete" ) { result in done() }
}
}
}
describe( "get" ) {
it( "should call the correct endpoint" ) {
waitUntil { done in api.get( "tests/get" ) { result in done() } }
}
}
}
}
}
//
// Fixtures.swift
// Api
//
// Created by Mauro Bender on 13/8/16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import Api
struct Item {
let id: Int
let name: String
}
extension Item: JSONSerializable {
init(fromJSON json: [String : AnyObject]) {
self.id = json[ "id" ] as! Int
self.name = json[ "name" ] as! String
}
func toJSON() -> [String : AnyObject] {
return [ String: AnyObject ]()
}
}
\ No newline at end of file
//
// Matchers.swift
// Api
//
// Created by Mauro Bender on 13/8/16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import Api
import Foundation
import Mockingjay
let baseURL = NSURL( string: "http://api.test.com" )!
let apiPath = "1"
func matchApiPath( path: String, method: ApiMethod = .GET ) -> ( ( NSURLRequest ) -> Bool ) {
let url = baseURL.URLByAppendingPathComponent( apiPath ).URLByAppendingPathComponent( path )
return { ( request: NSURLRequest ) in
return url == request.URL && request.HTTPMethod == method.rawValue
}
}
\ No newline at end of file
//
// ResourceTests.swift
// Api
//
// Created by Mauro Bender on 13/8/16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import Quick
import Nimble
import Mockingjay
import Api
class ResourceTests: QuickSpec {
override func setUp() {
super.setUp()
// Register stubs
stub( matchApiPath( "items/1" ), builder: json( [ "id": 1, "name": "Item 1" ] ) )
}
override func spec() {
let api = Api( baseURL: baseURL, apiPath: apiPath )
describe( "Resource" ) {
let resource: Resource<Item> = api.resource( "items" )
describe( "item<T>" ) {
context( "when the request is successful" ) {
it( "should call the correct endpoint and return the item" ) {
waitUntil { done in
resource.item( 1 ) { ( item: Item ) in
expect( item.id ) == 1
expect( item.name ) == "Item 1"
done()
}
}
}
}
}
}
}
}
\ No newline at end of file
// https://github.com/Quick/Quick
import Quick
import Nimble
import Api
class TableOfContentsSpec: QuickSpec {
override func spec() {
describe("these will fail") {
it("can do maths") {
expect(1) == 2
}
it("can read") {
expect("number") == "string"
}
it("will eventually fail") {
expect("time").toEventually( equal("done") )
}
context("these will pass") {
it("can do maths") {
expect(23) == 23
}
it("can read") {
expect("🐮") == "🐮"
}
it("will eventually pass") {
var time = "passing"
dispatch_async(dispatch_get_main_queue()) {
time = "done"
}
waitUntil { done in
NSThread.sleepForTimeInterval(0.5)
expect(time) == "done"
done()
}
}
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment