diff --git a/ACActionCable.podspec b/ACActionCable.podspec index 5ef6b03..e9342f2 100644 --- a/ACActionCable.podspec +++ b/ACActionCable.podspec @@ -8,12 +8,12 @@ Pod::Spec.new do |spec| spec.name = 'ACActionCable' - spec.version = '2.1.2' + spec.version = '2.2.0' spec.license = { :type => 'MIT', :file => 'LICENSE' } spec.homepage = 'https://github.com/High5Apps/ACActionCable' spec.authors = { 'Julian Tigler' => 'high5apps@gmail.com', 'Fabian Jäger' => 'fabian@mailbutler.io' } spec.summary = 'A well-tested, dependency-free Action Cable client for Rails 6' - spec.source = { :git => 'https://github.com/High5Apps/ACActionCable.git', :tag => 'v2.1.2' } + spec.source = { :git => 'https://github.com/High5Apps/ACActionCable.git', :tag => 'v2.2.0' } spec.swift_version = '5.1' spec.ios.deployment_target = '11.0' spec.osx.deployment_target = '10.13' diff --git a/ACActionCable.xcodeproj/project.pbxproj b/ACActionCable.xcodeproj/project.pbxproj index 61baea1..67b12cd 100644 --- a/ACActionCable.xcodeproj/project.pbxproj +++ b/ACActionCable.xcodeproj/project.pbxproj @@ -322,7 +322,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 2.1.2; + MARKETING_VERSION = 2.2.0; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -352,7 +352,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 2.1.2; + MARKETING_VERSION = 2.2.0; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; diff --git a/Sources/ACActionCable/ACCommand.swift b/Sources/ACActionCable/ACCommand.swift index 34ac0e4..f6f1da9 100644 --- a/Sources/ACActionCable/ACCommand.swift +++ b/Sources/ACActionCable/ACCommand.swift @@ -42,26 +42,22 @@ public struct ACCommand { // MARK: Initialization - init?(type: ACCommandType, identifier: ACChannelIdentifier, action: String? = nil) { + init?(type: ACCommandType, identifier: ACChannelIdentifier, action: String? = nil, object: Encodable? = nil) { self.type = type self.identifier = identifier - if type == .message { - guard let action else { return nil } + if let object, let data = try? Self.encoder.encode(object) { + self.data = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] + } - self.data = ["action": action] + if type == .message, let action { + self.data = self.data ?? [:] + self.data?["action"] = action } - } - - init?(type: ACCommandType, identifier: ACChannelIdentifier, object: T) { - self.type = type - self.identifier = identifier - // special handling of data - guard let data = try? Self.encoder.encode(object), let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []) else { return nil } - self.data = jsonObject as? [String: Any] + if type == .message && (self.data ?? [:]).isEmpty { return nil } } - + // MARK: Helpers private func json(from dictionary: [String: Any]) -> String? { diff --git a/Sources/ACActionCable/ACSubscription.swift b/Sources/ACActionCable/ACSubscription.swift index d452742..36ad1be 100644 --- a/Sources/ACActionCable/ACSubscription.swift +++ b/Sources/ACActionCable/ACSubscription.swift @@ -26,15 +26,10 @@ public class ACSubscription { // MARK: Sending - public func send(object: T, completion: ACEventHandler? = nil) { - guard let command = ACCommand(type: .message, identifier: channelIdentifier, object: object) else { return } + public func send(action: String? = nil, object: Encodable? = nil, completion: ACEventHandler? = nil) { + guard let command = ACCommand(type: .message, identifier: channelIdentifier, action: action, object: object) else { return } client.send(command, completion: completion) } - - public func send(action: String, completion: ACEventHandler? = nil) { - guard let command = ACCommand(type: .message, identifier: channelIdentifier, action: action) else { return } - client.send(command) - } } // MARK: Equatable diff --git a/Tests/ACActionCableTests/ACCommandTests.swift b/Tests/ACActionCableTests/ACCommandTests.swift index c231fad..4992d62 100644 --- a/Tests/ACActionCableTests/ACCommandTests.swift +++ b/Tests/ACActionCableTests/ACCommandTests.swift @@ -46,4 +46,19 @@ class ACCommandTests: XCTestCase { let command = ACCommand(type: .message, identifier: identifier, action: "my_action") XCTAssertEqual(expected, command?.string) } + + func testShouldEncodeActionMessageWithObject() throws { + struct MyObject: Encodable { + let myInt: Int + let myString: String + let myDate: Date + } + + let date = Date(timeIntervalSince1970: 1600545466) + let format = #"{"command":"message","data":"{\"action\":\"my_action\",\"my_date\":%d,\"my_int\":1,\"my_string\":\"test\"}","identifier":"{\"channel\":\"TestChannel\",\"test_id\":42}"}"# + let expected = String(format: format, Int(date.timeIntervalSince1970)) + let identifier = ACChannelIdentifier(channelName: "TestChannel", identifier: ["test_id": 42])! + let command = ACCommand(type: .message, identifier: identifier, action: "my_action", object: MyObject(myInt: 1, myString: "test", myDate: date)) + XCTAssertEqual(expected, command?.string) + } } diff --git a/Tests/ACActionCableTests/ACSubscriptionTests.swift b/Tests/ACActionCableTests/ACSubscriptionTests.swift index 4bba643..2819a57 100644 --- a/Tests/ACActionCableTests/ACSubscriptionTests.swift +++ b/Tests/ACActionCableTests/ACSubscriptionTests.swift @@ -39,6 +39,18 @@ class ACSubscriptionTests: XCTestCase { wait(for: [expectation], timeout: 1) } + func testShouldSendWithActionAndEncodable() throws { + struct MyObject: Encodable { + let myProperty: Int + } + + let expectedSend = #"{"command":"message","data":"{\"action\":\"my_action\",\"my_property\":1}","identifier":"{\"channel\":\"TestChannel\",\"test_id\":32}"}"# + let object = MyObject(myProperty: 1) + let (subscription, expectation) = expectMessage(expectedSend) + subscription.send(action:"my_action", object: object) + wait(for: [expectation], timeout: 1) + } + private func expectMessage(_ expectedSend: String) -> (ACSubscription, XCTestExpectation) { let expectedSubscribe = #"{"command":"subscribe","identifier":"{\"channel\":\"TestChannel\",\"test_id\":32}"}"# let subscribe = expectation(description: "Subscribe")