ledger_sync 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -3
- data/lib/ledger_sync.rb +12 -6
- data/lib/ledger_sync/adaptors/ledger_serializer.rb +124 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_attribute.rb +148 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_attribute_set.rb +51 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_type/mapping_type.rb +41 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_type/references_many_type.rb +24 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_type/value_type.rb +17 -0
- data/lib/ledger_sync/adaptors/operation.rb +15 -9
- data/lib/ledger_sync/adaptors/quickbooks_online/account/ledger_serializer.rb +21 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/create.rb +8 -36
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/update.rb +4 -35
- data/lib/ledger_sync/adaptors/quickbooks_online/account/searcher.rb +3 -44
- data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +75 -28
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/ledger_serializer.rb +40 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/create.rb +9 -48
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/find.rb +10 -21
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/update.rb +9 -52
- data/lib/ledger_sync/adaptors/quickbooks_online/bill_line_item/ledger_serializer.rb +27 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/ledger_serializer.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/create.rb +2 -25
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/find.rb +2 -14
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/update.rb +3 -30
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/ledger_serializer.rb +35 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/create.rb +2 -39
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/find.rb +2 -14
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/update.rb +4 -43
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit_line_item/ledger_serializer.rb +27 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/ledger_serializer.rb +48 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/create.rb +10 -51
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/find.rb +10 -22
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/update.rb +10 -55
- data/lib/ledger_sync/adaptors/quickbooks_online/expense_line_item/ledger_serializer.rb +27 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/ledger_serializer.rb +32 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/create.rb +4 -37
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/find.rb +4 -15
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/update.rb +5 -42
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry_line_item/ledger_serializer.rb +31 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer.rb +103 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/{account/mapping.rb → ledger_serializer_type/account_sub_type.rb} +128 -148
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/account_type.rb +51 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/amount_type.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/classification_type.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/date_type.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/journal_entry_line_item_type.rb +20 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/payment_type.rb +21 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation.rb +2 -7
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/create.rb +29 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/find.rb +31 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/full_update.rb +43 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/sparse_update.rb +29 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/ledger_serializer.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/create.rb +1 -24
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/update.rb +2 -29
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/ledger_serializer.rb +33 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/create.rb +1 -29
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/update.rb +4 -35
- data/lib/ledger_sync/adaptors/quickbooks_online/util/adaptor_error_parser.rb +2 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/util/operation_error_parser.rb +2 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/ledger_serializer.rb +25 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/create.rb +1 -23
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/update.rb +2 -29
- data/lib/ledger_sync/adaptors/test/account/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/account/operations/find.rb +5 -1
- data/lib/ledger_sync/adaptors/test/account/operations/invalid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/account/operations/update.rb +8 -2
- data/lib/ledger_sync/adaptors/test/account/operations/valid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/customer/operations/find.rb +5 -1
- data/lib/ledger_sync/adaptors/test/customer/operations/invalid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/update.rb +1 -24
- data/lib/ledger_sync/adaptors/test/customer/operations/valid.rb +3 -6
- data/lib/ledger_sync/adaptors/test/expense/operations/create.rb +8 -3
- data/lib/ledger_sync/adaptors/test/expense/operations/find.rb +4 -14
- data/lib/ledger_sync/adaptors/test/expense/operations/update.rb +2 -32
- data/lib/ledger_sync/adaptors/test/ledger_serializer.rb +64 -0
- data/lib/ledger_sync/adaptors/test/operation/create.rb +27 -0
- data/lib/ledger_sync/adaptors/test/operation/find.rb +29 -0
- data/lib/ledger_sync/adaptors/test/operation/update.rb +34 -0
- data/lib/ledger_sync/adaptors/test/payment/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/payment/operations/find.rb +5 -1
- data/lib/ledger_sync/adaptors/test/payment/operations/update.rb +1 -23
- data/lib/ledger_sync/adaptors/test/transfer/operations/create.rb +1 -22
- data/lib/ledger_sync/adaptors/test/transfer/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/test/transfer/operations/update.rb +1 -25
- data/lib/ledger_sync/adaptors/test/vendor/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/vendor/operations/find.rb +7 -1
- data/lib/ledger_sync/adaptors/test/vendor/operations/invalid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/vendor/operations/update.rb +1 -23
- data/lib/ledger_sync/adaptors/test/vendor/operations/valid.rb +1 -0
- data/lib/ledger_sync/error/adaptor_errors.rb +17 -5
- data/lib/ledger_sync/error/operation_errors.rb +12 -5
- data/lib/ledger_sync/error/resource_errors.rb +5 -1
- data/lib/ledger_sync/resource.rb +33 -6
- data/lib/ledger_sync/resource_attribute.rb +4 -0
- data/lib/ledger_sync/resource_attribute/dirty_mixin.rb +16 -0
- data/lib/ledger_sync/resource_attribute/mixin.rb +19 -7
- data/lib/ledger_sync/resource_attribute/reference/many.rb +55 -1
- data/lib/ledger_sync/resource_attribute_set.rb +6 -7
- data/lib/ledger_sync/resources/account.rb +1 -1
- data/lib/ledger_sync/resources/bill.rb +1 -0
- data/lib/ledger_sync/resources/bill_line_item.rb +2 -0
- data/lib/ledger_sync/resources/expense.rb +5 -1
- data/lib/ledger_sync/resources/expense_line_item.rb +2 -0
- data/lib/ledger_sync/resources/journal_entry.rb +1 -0
- data/lib/ledger_sync/result.rb +4 -3
- data/lib/ledger_sync/type/id.rb +34 -0
- data/lib/ledger_sync/type/reference_many.rb +8 -2
- data/lib/ledger_sync/type/reference_one.rb +5 -0
- data/lib/ledger_sync/type/value_mixin.rb +12 -0
- data/lib/ledger_sync/util/hash_helpers.rb +16 -0
- data/lib/ledger_sync/version.rb +1 -1
- data/qa.rb +142 -0
- metadata +38 -5
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/mapping.rb +0 -15
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/mapping.rb +0 -14
- data/lib/ledger_sync/error/sync_errors.rb +0 -22
@@ -6,6 +6,7 @@ module LedgerSync
|
|
6
6
|
class Find < Operation::Find
|
7
7
|
class Contract < LedgerSync::Adaptors::Contract
|
8
8
|
schema do
|
9
|
+
required(:external_id).maybe(:string)
|
9
10
|
required(:ledger_id).filled(:string)
|
10
11
|
required(:from_account).hash(Types::Reference)
|
11
12
|
required(:to_account).hash(Types::Reference)
|
@@ -15,19 +16,6 @@ module LedgerSync
|
|
15
16
|
required(:transaction_date).maybe(:date?)
|
16
17
|
end
|
17
18
|
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def operate
|
22
|
-
return failure(nil) if resource.ledger_id.nil?
|
23
|
-
|
24
|
-
response = adaptor.find(
|
25
|
-
resource: 'transfer',
|
26
|
-
id: resource.ledger_id
|
27
|
-
)
|
28
|
-
|
29
|
-
success(response: response)
|
30
|
-
end
|
31
19
|
end
|
32
20
|
end
|
33
21
|
end
|
@@ -6,6 +6,7 @@ module LedgerSync
|
|
6
6
|
class Update < Operation::Update
|
7
7
|
class Contract < LedgerSync::Adaptors::Contract
|
8
8
|
params do
|
9
|
+
required(:external_id).maybe(:string)
|
9
10
|
required(:ledger_id).filled(:string)
|
10
11
|
required(:from_account).hash(Types::Reference)
|
11
12
|
required(:to_account).hash(Types::Reference)
|
@@ -15,31 +16,6 @@ module LedgerSync
|
|
15
16
|
required(:transaction_date).filled(:date?)
|
16
17
|
end
|
17
18
|
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def operate
|
22
|
-
ledger_resource_data = adaptor.find(
|
23
|
-
resource: 'transfer',
|
24
|
-
id: resource.ledger_id
|
25
|
-
)
|
26
|
-
response = adaptor.post(
|
27
|
-
resource: 'transfer',
|
28
|
-
payload: merge_into(from: local_resource_data, to: ledger_resource_data)
|
29
|
-
)
|
30
|
-
|
31
|
-
success(response: response)
|
32
|
-
end
|
33
|
-
|
34
|
-
def local_resource_data
|
35
|
-
{
|
36
|
-
'amount' => resource.amount,
|
37
|
-
'currency' => resource.currency,
|
38
|
-
'from_account_id' => resource.from_account.ledger_id,
|
39
|
-
'to_account_id' => resource.to_account.ledger_id,
|
40
|
-
'date' => resource.transaction_date
|
41
|
-
}
|
42
|
-
end
|
43
19
|
end
|
44
20
|
end
|
45
21
|
end
|
@@ -6,6 +6,7 @@ module LedgerSync
|
|
6
6
|
class Create < Operation::Create
|
7
7
|
class Contract < LedgerSync::Adaptors::Contract
|
8
8
|
schema do
|
9
|
+
required(:external_id).maybe(:string)
|
9
10
|
required(:ledger_id).value(:nil)
|
10
11
|
required(:display_name).maybe(:string)
|
11
12
|
required(:first_name).maybe(:string)
|
@@ -37,7 +38,10 @@ module LedgerSync
|
|
37
38
|
|
38
39
|
resource.ledger_id = response.dig('id')
|
39
40
|
|
40
|
-
success(
|
41
|
+
success(
|
42
|
+
resource: Test::LedgerSerializer.new(resource: resource).deserialize(hash: response),
|
43
|
+
response: response
|
44
|
+
)
|
41
45
|
end
|
42
46
|
end
|
43
47
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module LedgerSync
|
2
4
|
module Adaptors
|
3
5
|
module Test
|
@@ -6,6 +8,7 @@ module LedgerSync
|
|
6
8
|
class Find < Operation::Find
|
7
9
|
class Contract < LedgerSync::Adaptors::Contract
|
8
10
|
params do
|
11
|
+
required(:external_id).maybe(:string)
|
9
12
|
required(:ledger_id).filled(:string)
|
10
13
|
optional(:display_name).maybe(:string)
|
11
14
|
optional(:first_name).maybe(:string)
|
@@ -24,7 +27,10 @@ module LedgerSync
|
|
24
27
|
id: resource.ledger_id
|
25
28
|
)
|
26
29
|
|
27
|
-
success(
|
30
|
+
success(
|
31
|
+
resource: Test::LedgerSerializer.new(resource: resource).deserialize(hash: response),
|
32
|
+
response: response
|
33
|
+
)
|
28
34
|
end
|
29
35
|
end
|
30
36
|
end
|
@@ -6,6 +6,7 @@ module LedgerSync
|
|
6
6
|
class Invalid < Operation::Create
|
7
7
|
class Contract < LedgerSync::Adaptors::Contract
|
8
8
|
schema do
|
9
|
+
required(:external_id).filled(:string)
|
9
10
|
required(:ledger_id).filled(:string)
|
10
11
|
required(:display_name).filled(:string)
|
11
12
|
required(:first_name).filled(:string)
|
@@ -6,6 +6,7 @@ module LedgerSync
|
|
6
6
|
class Update < Operation::Update
|
7
7
|
class Contract < LedgerSync::Adaptors::Contract
|
8
8
|
schema do
|
9
|
+
required(:external_id).maybe(:string)
|
9
10
|
required(:ledger_id).filled(:string)
|
10
11
|
required(:display_name).maybe(:string)
|
11
12
|
required(:first_name).maybe(:string)
|
@@ -13,29 +14,6 @@ module LedgerSync
|
|
13
14
|
optional(:email).maybe(:string)
|
14
15
|
end
|
15
16
|
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def operate
|
20
|
-
ledger_resource_data = adaptor.find(
|
21
|
-
resource: 'vendor',
|
22
|
-
id: resource.ledger_id
|
23
|
-
)
|
24
|
-
|
25
|
-
response = adaptor.post(
|
26
|
-
resource: 'vendor',
|
27
|
-
payload: merge_into(from: local_resource_data, to: ledger_resource_data)
|
28
|
-
)
|
29
|
-
|
30
|
-
success(response: response)
|
31
|
-
end
|
32
|
-
|
33
|
-
def local_resource_data
|
34
|
-
{
|
35
|
-
'name' => resource.name,
|
36
|
-
'email' => resource.email
|
37
|
-
}
|
38
|
-
end
|
39
17
|
end
|
40
18
|
end
|
41
19
|
end
|
@@ -6,6 +6,7 @@ module LedgerSync
|
|
6
6
|
class Valid < Operation::Create
|
7
7
|
class Contract < LedgerSync::Adaptors::Contract
|
8
8
|
schema do
|
9
|
+
optional(:external_id).maybe(:string)
|
9
10
|
optional(:ledger_id).maybe(:string)
|
10
11
|
optional(:display_name).maybe(:string)
|
11
12
|
optional(:first_name).maybe(:string)
|
@@ -4,15 +4,20 @@ module LedgerSync
|
|
4
4
|
class Error
|
5
5
|
class AdaptorError < Error
|
6
6
|
attr_reader :adaptor
|
7
|
+
attr_reader :response
|
7
8
|
|
8
|
-
def initialize(adaptor:, message:)
|
9
|
+
def initialize(adaptor:, message:, response:nil)
|
9
10
|
@adaptor = adaptor
|
11
|
+
@response = response
|
10
12
|
super(message: message)
|
11
13
|
end
|
12
14
|
|
13
15
|
class MissingAdaptorError < self
|
14
16
|
def initialize(message:)
|
15
|
-
super(
|
17
|
+
super(
|
18
|
+
message: message,
|
19
|
+
adaptor: nil,
|
20
|
+
)
|
16
21
|
end
|
17
22
|
end
|
18
23
|
|
@@ -22,20 +27,27 @@ module LedgerSync
|
|
22
27
|
def initialize(message:, adaptor:, attribute:, validation:)
|
23
28
|
@attribute = attribute
|
24
29
|
@validation = validation
|
25
|
-
super(
|
30
|
+
super(
|
31
|
+
message: message,
|
32
|
+
adaptor: adaptor,
|
33
|
+
)
|
26
34
|
end
|
27
35
|
end
|
28
36
|
|
29
37
|
class ThrottleError < self
|
30
38
|
attr_reader :rate_limiting_wait_in_seconds
|
31
39
|
|
32
|
-
def initialize(adaptor:, message: nil)
|
40
|
+
def initialize(adaptor:, message: nil, response:nil)
|
33
41
|
message ||= 'Your request has been throttled.'
|
34
42
|
@rate_limiting_wait_in_seconds = LedgerSync.adaptors.config_from_klass(
|
35
43
|
klass: adaptor.class
|
36
44
|
).rate_limiting_wait_in_seconds
|
37
45
|
|
38
|
-
super(
|
46
|
+
super(
|
47
|
+
adaptor: adaptor,
|
48
|
+
message: message,
|
49
|
+
response: response
|
50
|
+
)
|
39
51
|
end
|
40
52
|
end
|
41
53
|
|
@@ -4,9 +4,11 @@ module LedgerSync
|
|
4
4
|
class Error
|
5
5
|
class OperationError < Error
|
6
6
|
attr_reader :operation
|
7
|
+
attr_reader :response
|
7
8
|
|
8
|
-
def initialize(message:, operation:)
|
9
|
+
def initialize(message:, operation:, response:nil)
|
9
10
|
@operation = operation
|
11
|
+
@response = response
|
10
12
|
super(message: message)
|
11
13
|
end
|
12
14
|
|
@@ -15,10 +17,14 @@ module LedgerSync
|
|
15
17
|
class LedgerValidationError < self; end
|
16
18
|
|
17
19
|
class PerformedOperationError < self
|
18
|
-
def initialize(message: nil, operation:)
|
20
|
+
def initialize(message: nil, operation:, response:nil)
|
19
21
|
message ||= 'Operation has already been performed. Please check the result.'
|
20
22
|
|
21
|
-
super(
|
23
|
+
super(
|
24
|
+
message: message,
|
25
|
+
operation: operation,
|
26
|
+
response: response
|
27
|
+
)
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
@@ -26,13 +32,14 @@ module LedgerSync
|
|
26
32
|
attr_reader :attribute,
|
27
33
|
:validation
|
28
34
|
|
29
|
-
def initialize(message:, attribute:, operation:, validation:)
|
35
|
+
def initialize(message:, attribute:, operation:, validation:, response:nil)
|
30
36
|
@attribute = attribute
|
31
37
|
@validation = validation
|
32
38
|
|
33
39
|
super(
|
34
40
|
message: message,
|
35
|
-
operation: operation
|
41
|
+
operation: operation,
|
42
|
+
response: response
|
36
43
|
)
|
37
44
|
end
|
38
45
|
end
|
@@ -16,7 +16,11 @@ module LedgerSync
|
|
16
16
|
|
17
17
|
resource_class = resource.class
|
18
18
|
|
19
|
-
message =
|
19
|
+
message = attribute.type.error_message(
|
20
|
+
attribute: attribute,
|
21
|
+
resource: resource,
|
22
|
+
value: value
|
23
|
+
)
|
20
24
|
|
21
25
|
super(message: message, resource: nil)
|
22
26
|
end
|
data/lib/ledger_sync/resource.rb
CHANGED
@@ -14,6 +14,7 @@ module LedgerSync
|
|
14
14
|
include ResourceAttribute::Reference::Many::Mixin
|
15
15
|
|
16
16
|
PRIMITIVES = [
|
17
|
+
ActiveModel::Type,
|
17
18
|
Date,
|
18
19
|
DateTime,
|
19
20
|
FalseClass,
|
@@ -27,24 +28,50 @@ module LedgerSync
|
|
27
28
|
|
28
29
|
serialize except: %i[resource_attributes references]
|
29
30
|
|
30
|
-
|
31
|
+
def assign_attribute(name, value)
|
32
|
+
public_send("#{name}=", value)
|
33
|
+
end
|
34
|
+
|
35
|
+
def assign_attributes(**keywords)
|
36
|
+
keywords.each { |k, v| assign_attribute(k, v) }
|
37
|
+
end
|
31
38
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
@sync_token = sync_token
|
39
|
+
def changed?
|
40
|
+
super || resource_attributes.references_many.select(&:changed?).any?
|
41
|
+
end
|
36
42
|
|
37
|
-
|
43
|
+
def changes
|
44
|
+
super.merge(Hash[resource_attributes.references_many.map { |ref| [ref.name, ref.changes['value']] if ref.changed? }.compact])
|
45
|
+
end
|
46
|
+
|
47
|
+
def dup
|
48
|
+
Marshal.load(Marshal.dump(self))
|
38
49
|
end
|
39
50
|
|
40
51
|
def klass_from_resource_type(obj)
|
41
52
|
LedgerSync.const_get(LedgerSync::Util::StringHelpers.camelcase(obj))
|
42
53
|
end
|
43
54
|
|
55
|
+
def to_h
|
56
|
+
resource_attributes.to_h.merge(dirty_attributes_to_h)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.inherited(subclass)
|
60
|
+
subclass.attribute :external_id, type: Type::ID
|
61
|
+
subclass.attribute :ledger_id, type: Type::ID
|
62
|
+
end
|
63
|
+
|
44
64
|
def self.resource_type
|
45
65
|
@resource_type ||= LedgerSync::Util::StringHelpers.underscore(name.split('::').last).to_sym
|
46
66
|
end
|
47
67
|
|
68
|
+
def self.serialize_attribute?(sattr)
|
69
|
+
sattr = sattr.to_sym
|
70
|
+
return true if resource_attributes.key?(sattr)
|
71
|
+
|
72
|
+
false
|
73
|
+
end
|
74
|
+
|
48
75
|
def ==(other)
|
49
76
|
other.fingerprint == fingerprint
|
50
77
|
end
|
@@ -32,6 +32,21 @@ module LedgerSync
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# Change the dirty change set of {"name" => ["Bill", "Bob"]}
|
36
|
+
# to current values of attributes that have changed: {"name" => "Bob"}
|
37
|
+
def changes_to_h
|
38
|
+
Hash[changes.map { |k, v| [k, v.last] }]
|
39
|
+
end
|
40
|
+
|
41
|
+
def dirty_attributes_to_h
|
42
|
+
Hash[self.class.dirty_attributes.keys.map do |k|
|
43
|
+
[
|
44
|
+
k,
|
45
|
+
public_send(k)
|
46
|
+
]
|
47
|
+
end]
|
48
|
+
end
|
49
|
+
|
35
50
|
# Normally you would just call `changes_applied`, but because we
|
36
51
|
# define an `@attributes` instance variable, the `ActiveModel::Dirty`
|
37
52
|
# mixin assumes it is a list of attributes in their format (spoiler: it
|
@@ -43,6 +58,7 @@ module LedgerSync
|
|
43
58
|
@mutations_before_last_save = mutations_from_database
|
44
59
|
# forget_attribute_assignments # skipped as our attributes do not implement this method
|
45
60
|
@mutations_from_database = ActiveModel::ForcedMutationTracker.new(self) # Manually set to expected value
|
61
|
+
resource_attributes.references_many.map(&:save)
|
46
62
|
end
|
47
63
|
end
|
48
64
|
end
|
@@ -21,19 +21,21 @@ module LedgerSync
|
|
21
21
|
resource_attributes[name].value
|
22
22
|
end
|
23
23
|
|
24
|
-
define_method "#{name}
|
25
|
-
|
26
|
-
|
27
|
-
attribute = resource_attributes[name]
|
28
|
-
|
29
|
-
unless attribute.valid_with?(value: val)
|
24
|
+
define_method "_#{name}_valid_with_value?" do |val|
|
25
|
+
unless resource_attributes[name].valid_with?(value: val)
|
30
26
|
raise ResourceError::AttributeTypeError.new(
|
31
|
-
attribute:
|
27
|
+
attribute: resource_attributes[name],
|
32
28
|
resource: self,
|
33
29
|
value: val
|
34
30
|
)
|
35
31
|
end
|
32
|
+
end
|
36
33
|
|
34
|
+
define_method "#{name}=" do |val|
|
35
|
+
attribute = resource_attributes[name]
|
36
|
+
public_send("_#{name}_valid_with_value?", val)
|
37
|
+
val = attribute.type.cast(val) if attribute.type.cast?
|
38
|
+
public_send("#{name}_will_change!") unless val == resource_attributes[name] # For Dirty
|
37
39
|
attribute.value = val
|
38
40
|
end
|
39
41
|
|
@@ -47,10 +49,15 @@ module LedgerSync
|
|
47
49
|
_define_attribute_methods(name)
|
48
50
|
|
49
51
|
resource_attributes.add(resource_attribute)
|
52
|
+
references_many_resource_attributes << resource_attribute if resource_attribute.type.is_a?(Reference::Many)
|
50
53
|
|
51
54
|
resource_attribute
|
52
55
|
end
|
53
56
|
|
57
|
+
def references_many_resource_attributes
|
58
|
+
@references_many_resource_attributes ||= []
|
59
|
+
end
|
60
|
+
|
54
61
|
def resource_attributes
|
55
62
|
@resource_attributes ||= ResourceAttributeSet.new(resource: self)
|
56
63
|
end
|
@@ -82,6 +89,11 @@ module LedgerSync
|
|
82
89
|
@resource_attributes ||= Marshal.load(Marshal.dump(self.class.resource_attributes))
|
83
90
|
end
|
84
91
|
|
92
|
+
def save
|
93
|
+
resoure_attributes.map(&:save)
|
94
|
+
super
|
95
|
+
end
|
96
|
+
|
85
97
|
def serialize_attributes
|
86
98
|
Hash[resource_attributes.map { |k, v| [k, v.value] }]
|
87
99
|
end
|
@@ -7,6 +7,48 @@ module LedgerSync
|
|
7
7
|
class ResourceAttribute
|
8
8
|
class Reference
|
9
9
|
class Many < Reference
|
10
|
+
class ManyArray
|
11
|
+
include ActiveModel::Dirty
|
12
|
+
|
13
|
+
ARRAY_METHODS_TO_OVERRIDE_WITH_DIRTY = %w[<< | []= + -].freeze
|
14
|
+
|
15
|
+
delegate :count,
|
16
|
+
:each,
|
17
|
+
:include?,
|
18
|
+
:map,
|
19
|
+
to: :value
|
20
|
+
|
21
|
+
attr_accessor :value
|
22
|
+
|
23
|
+
define_attribute_methods :value
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@value = []
|
27
|
+
end
|
28
|
+
|
29
|
+
ARRAY_METHODS_TO_OVERRIDE_WITH_DIRTY.each do |array_method|
|
30
|
+
define_method(array_method) do |val|
|
31
|
+
value_will_change!
|
32
|
+
@value = @value.send(array_method, val)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(other)
|
37
|
+
return false unless other.is_a?(ManyArray)
|
38
|
+
return false unless other.sorted_fingerprints == sorted_fingerprints
|
39
|
+
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def save
|
44
|
+
changes_applied
|
45
|
+
end
|
46
|
+
|
47
|
+
def sorted_fingerprints
|
48
|
+
value.map(&:fingerprint).sort
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
10
52
|
module Mixin
|
11
53
|
def self.included(base)
|
12
54
|
base.extend(ClassMethods)
|
@@ -25,9 +67,21 @@ module LedgerSync
|
|
25
67
|
super(
|
26
68
|
name: name,
|
27
69
|
type: Type::ReferenceMany.new(resource_class: to),
|
28
|
-
value:
|
70
|
+
value: ManyArray.new
|
29
71
|
)
|
30
72
|
end
|
73
|
+
|
74
|
+
def changed?
|
75
|
+
value.changed?
|
76
|
+
end
|
77
|
+
|
78
|
+
def changes
|
79
|
+
value.changes
|
80
|
+
end
|
81
|
+
|
82
|
+
def save
|
83
|
+
value.save
|
84
|
+
end
|
31
85
|
end
|
32
86
|
end
|
33
87
|
end
|