From f2870cf24a945ef1de50255283b16721ad6c31b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20J=C3=A4ger?= Date: Mon, 24 Jun 2024 12:13:50 +0200 Subject: [PATCH 1/3] allow to send action and object --- Sources/ACActionCable/ACCommand.swift | 25 ++++++++++++------- Sources/ACActionCable/ACSubscription.swift | 6 ++--- Tests/ACActionCableTests/ACCommandTests.swift | 15 +++++++++++ .../ACSubscriptionTests.swift | 12 +++++++++ 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Sources/ACActionCable/ACCommand.swift b/Sources/ACActionCable/ACCommand.swift index 34ac0e4..5aee003 100644 --- a/Sources/ACActionCable/ACCommand.swift +++ b/Sources/ACActionCable/ACCommand.swift @@ -42,6 +42,22 @@ public struct ACCommand { // MARK: Initialization + init?(type: ACCommandType, identifier: ACChannelIdentifier, action: String? = nil, object: T? = nil) { + self.type = type + self.identifier = identifier + + if let object, let data = try? Self.encoder.encode(object) { + self.data = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] + } + + if type == .message, let action { + self.data = self.data ?? [:] + self.data?["action"] = action + } + + if type == .message && (self.data ?? [:]).isEmpty { return nil } + } + init?(type: ACCommandType, identifier: ACChannelIdentifier, action: String? = nil) { self.type = type self.identifier = identifier @@ -52,16 +68,7 @@ public struct ACCommand { 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] - } - // MARK: Helpers private func json(from dictionary: [String: Any]) -> String? { diff --git a/Sources/ACActionCable/ACSubscription.swift b/Sources/ACActionCable/ACSubscription.swift index d452742..7a1920a 100644 --- a/Sources/ACActionCable/ACSubscription.swift +++ b/Sources/ACActionCable/ACSubscription.swift @@ -26,14 +26,14 @@ 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: T, 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) + client.send(command, completion: completion) } } 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") From 6b889ed89f58c9eef245105b14ae87203e5d93fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ja=CC=88ger?= Date: Mon, 24 Jun 2024 12:15:12 +0200 Subject: [PATCH 2/3] bump minor version --- ACActionCable.podspec | 4 ++-- ACActionCable.xcodeproj/project.pbxproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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)"; From 6e9fe8dcc116c8fa6341eb461f4b6a2b9a226794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20J=C3=A4ger?= Date: Tue, 25 Jun 2024 08:53:30 +0200 Subject: [PATCH 3/3] Simplify APIs --- Sources/ACActionCable/ACCommand.swift | 13 +------------ Sources/ACActionCable/ACSubscription.swift | 7 +------ 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/Sources/ACActionCable/ACCommand.swift b/Sources/ACActionCable/ACCommand.swift index 5aee003..f6f1da9 100644 --- a/Sources/ACActionCable/ACCommand.swift +++ b/Sources/ACActionCable/ACCommand.swift @@ -42,7 +42,7 @@ public struct ACCommand { // MARK: Initialization - init?(type: ACCommandType, identifier: ACChannelIdentifier, action: String? = nil, object: T? = nil) { + init?(type: ACCommandType, identifier: ACChannelIdentifier, action: String? = nil, object: Encodable? = nil) { self.type = type self.identifier = identifier @@ -58,17 +58,6 @@ public struct ACCommand { if type == .message && (self.data ?? [:]).isEmpty { return nil } } - init?(type: ACCommandType, identifier: ACChannelIdentifier, action: String? = nil) { - self.type = type - self.identifier = identifier - - if type == .message { - guard let action else { return nil } - - self.data = ["action": action] - } - } - // MARK: Helpers private func json(from dictionary: [String: Any]) -> String? { diff --git a/Sources/ACActionCable/ACSubscription.swift b/Sources/ACActionCable/ACSubscription.swift index 7a1920a..36ad1be 100644 --- a/Sources/ACActionCable/ACSubscription.swift +++ b/Sources/ACActionCable/ACSubscription.swift @@ -26,15 +26,10 @@ public class ACSubscription { // MARK: Sending - public func send(action: String? = nil, object: T, completion: ACEventHandler? = nil) { + 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, completion: completion) - } } // MARK: Equatable