ar_sync 1.0.1 → 1.0.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/Gemfile.lock +5 -2
- data/README.md +6 -6
- data/ar_sync.gemspec +2 -2
- data/bin/console +1 -2
- data/core/ActioncableAdapter.d.ts +26 -2
- data/core/ActioncableAdapter.js +3 -3
- data/core/ArSyncApi.d.ts +7 -4
- data/core/ArSyncApi.js +9 -4
- data/core/{ArSyncModelBase.d.ts → ArSyncModel.d.ts} +13 -18
- data/core/{ArSyncModelBase.js → ArSyncModel.js} +33 -10
- data/{graph → core}/ArSyncStore.d.ts +3 -3
- data/{graph → core}/ArSyncStore.js +188 -57
- data/core/DataType.d.ts +17 -13
- data/core/hooks.d.ts +28 -0
- data/core/hooks.js +105 -0
- data/index.d.ts +2 -0
- data/index.js +6 -0
- data/lib/ar_sync.rb +1 -18
- data/lib/ar_sync/class_methods.rb +31 -89
- data/lib/ar_sync/collection.rb +4 -29
- data/lib/ar_sync/core.rb +35 -67
- data/lib/ar_sync/instance_methods.rb +40 -86
- data/lib/ar_sync/rails.rb +18 -27
- data/lib/ar_sync/type_script.rb +39 -18
- data/lib/ar_sync/version.rb +1 -1
- data/lib/generators/ar_sync/install/install_generator.rb +33 -32
- data/lib/generators/ar_sync/types/types_generator.rb +6 -3
- data/package-lock.json +21 -10
- data/package.json +1 -1
- data/src/core/ActioncableAdapter.ts +28 -3
- data/src/core/ArSyncApi.ts +8 -4
- data/src/core/{ArSyncModelBase.ts → ArSyncModel.ts} +51 -20
- data/src/{graph → core}/ArSyncStore.ts +199 -84
- data/src/core/DataType.ts +33 -20
- data/src/core/hooks.ts +108 -0
- data/src/index.ts +2 -0
- data/vendor/assets/javascripts/{ar_sync_tree.js.erb → ar_sync.js.erb} +6 -7
- metadata +33 -38
- data/core/hooksBase.d.ts +0 -29
- data/core/hooksBase.js +0 -80
- data/graph/ArSyncModel.d.ts +0 -10
- data/graph/ArSyncModel.js +0 -22
- data/graph/hooks.d.ts +0 -3
- data/graph/hooks.js +0 -10
- data/graph/index.d.ts +0 -2
- data/graph/index.js +0 -4
- data/src/core/hooksBase.ts +0 -86
- data/src/graph/ArSyncModel.ts +0 -21
- data/src/graph/hooks.ts +0 -7
- data/src/graph/index.ts +0 -2
- data/src/tree/ArSyncModel.ts +0 -145
- data/src/tree/ArSyncStore.ts +0 -323
- data/src/tree/hooks.ts +0 -7
- data/src/tree/index.ts +0 -2
- data/tree/ArSyncModel.d.ts +0 -39
- data/tree/ArSyncModel.js +0 -143
- data/tree/ArSyncStore.d.ts +0 -21
- data/tree/ArSyncStore.js +0 -365
- data/tree/hooks.d.ts +0 -3
- data/tree/hooks.js +0 -10
- data/tree/index.d.ts +0 -2
- data/tree/index.js +0 -4
- data/vendor/assets/javascripts/ar_sync_graph.js.erb +0 -17
data/core/DataType.d.ts
CHANGED
@@ -6,7 +6,8 @@ declare type RecordType = {
|
|
6
6
|
declare type Values<T> = T extends {
|
7
7
|
[K in keyof T]: infer U;
|
8
8
|
} ? U : never;
|
9
|
-
declare type
|
9
|
+
declare type AddNullable<Test, Type> = null extends Test ? Type | null : Type;
|
10
|
+
declare type DataTypeExtractField<BaseType, Key extends keyof BaseType> = Exclude<BaseType[Key], null> extends RecordType ? AddNullable<BaseType[Key], {}> : BaseType[Key] extends RecordType[] ? {}[] : BaseType[Key];
|
10
11
|
declare type DataTypeExtractFieldsFromQuery<BaseType, Fields> = '*' extends Fields ? {
|
11
12
|
[key in Exclude<keyof BaseType, '_meta'>]: DataTypeExtractField<BaseType, key>;
|
12
13
|
} : {
|
@@ -16,45 +17,48 @@ interface ExtraFieldErrorType {
|
|
16
17
|
error: 'extraFieldError';
|
17
18
|
}
|
18
19
|
declare type DataTypeExtractFromQueryHash<BaseType, QueryType> = '*' extends keyof QueryType ? {
|
19
|
-
[key in Exclude<(keyof BaseType) | (keyof QueryType), '_meta' | '_params' | '*'>]: (key extends keyof BaseType ? (key extends keyof QueryType ? (QueryType[key] extends true ? DataTypeExtractField<BaseType, key> : DataTypeFromQuery<BaseType[key] & {}, QueryType[key]
|
20
|
+
[key in Exclude<(keyof BaseType) | (keyof QueryType), '_meta' | '_params' | '*'>]: (key extends keyof BaseType ? (key extends keyof QueryType ? (QueryType[key] extends true ? DataTypeExtractField<BaseType, key> : AddNullable<BaseType[key], DataTypeFromQuery<BaseType[key] & {}, QueryType[key]>>) : DataTypeExtractField<BaseType, key>) : ExtraFieldErrorType);
|
20
21
|
} : {
|
21
|
-
[key in keyof QueryType]: (key extends keyof BaseType ? (QueryType[key] extends true ? DataTypeExtractField<BaseType, key> : DataTypeFromQuery<BaseType[key] & {}, QueryType[key]
|
22
|
+
[key in keyof QueryType]: (key extends keyof BaseType ? (QueryType[key] extends true ? DataTypeExtractField<BaseType, key> : AddNullable<BaseType[key], DataTypeFromQuery<BaseType[key] & {}, QueryType[key]>>) : ExtraFieldErrorType);
|
22
23
|
};
|
23
24
|
declare type _DataTypeFromQuery<BaseType, QueryType> = QueryType extends keyof BaseType | '*' ? DataTypeExtractFieldsFromQuery<BaseType, QueryType> : QueryType extends Readonly<(keyof BaseType | '*')[]> ? DataTypeExtractFieldsFromQuery<BaseType, Values<QueryType>> : QueryType extends {
|
24
25
|
as: string;
|
25
26
|
} ? {
|
26
27
|
error: 'type for alias field is not supported';
|
27
28
|
} | undefined : DataTypeExtractFromQueryHash<BaseType, QueryType>;
|
28
|
-
export declare type DataTypeFromQuery<BaseType, QueryType> = BaseType extends any[] ? CheckAttributesField<BaseType[0], QueryType>[] :
|
29
|
+
export declare type DataTypeFromQuery<BaseType, QueryType> = BaseType extends any[] ? CheckAttributesField<BaseType[0], QueryType>[] : AddNullable<BaseType, CheckAttributesField<BaseType & {}, QueryType>>;
|
29
30
|
declare type CheckAttributesField<P, Q> = Q extends {
|
30
31
|
attributes: infer R;
|
31
32
|
} ? _DataTypeFromQuery<P, R> : _DataTypeFromQuery<P, Q>;
|
32
33
|
declare type IsAnyCompareLeftType = {
|
33
34
|
__any: never;
|
34
35
|
};
|
35
|
-
declare type CollectExtraFields<Type, Path> = IsAnyCompareLeftType extends Type ? null : Type extends ExtraFieldErrorType ? Path : Type extends (infer R)[] ? _CollectExtraFields<R> :
|
36
|
-
declare type _CollectExtraFields<Type> = keyof (Type) extends never ? null : Values<{
|
37
|
-
[key in keyof Type]: CollectExtraFields<Type[key],
|
38
|
-
}
|
36
|
+
declare type CollectExtraFields<Type, Path> = IsAnyCompareLeftType extends Type ? null : Type extends ExtraFieldErrorType ? Path : Type extends (infer R)[] ? _CollectExtraFields<R> : _CollectExtraFields<Type>;
|
37
|
+
declare type _CollectExtraFields<Type> = Type extends object ? (keyof (Type) extends never ? null : Values<{
|
38
|
+
[key in keyof Type]: CollectExtraFields<Type[key], key>;
|
39
|
+
}>) : null;
|
39
40
|
declare type SelectString<T> = T extends string ? T : never;
|
40
|
-
declare type _ValidateDataTypeExtraFileds<Extra, Type> = SelectString<
|
41
|
+
declare type _ValidateDataTypeExtraFileds<Extra, Type> = SelectString<Extra> extends never ? Type : {
|
41
42
|
error: {
|
42
|
-
extraFields: SelectString<
|
43
|
+
extraFields: SelectString<Extra>;
|
43
44
|
};
|
44
45
|
};
|
45
46
|
declare type ValidateDataTypeExtraFileds<Type> = _ValidateDataTypeExtraFileds<CollectExtraFields<Type, []>, Type>;
|
46
47
|
declare type RequestBase = {
|
47
48
|
api: string;
|
48
49
|
query: any;
|
50
|
+
id?: number;
|
49
51
|
params?: any;
|
50
52
|
_meta?: {
|
51
53
|
data: any;
|
52
54
|
};
|
53
55
|
};
|
54
|
-
declare type DataTypeBaseFromRequestType<R> = R extends {
|
56
|
+
declare type DataTypeBaseFromRequestType<R extends RequestBase, ID> = R extends {
|
55
57
|
_meta?: {
|
56
58
|
data: infer DataType;
|
57
59
|
};
|
58
|
-
} ? DataType
|
59
|
-
|
60
|
+
} ? (ID extends number ? ([DataType, R['params']] extends [(infer DT)[], {
|
61
|
+
ids: number[];
|
62
|
+
} | undefined] ? DT : never) : DataType) : never;
|
63
|
+
export declare type DataTypeFromRequest<Req extends RequestBase, R extends RequestBase> = ValidateDataTypeExtraFileds<DataTypeFromQuery<DataTypeBaseFromRequestType<Req, R['id']>, R['query']>>;
|
60
64
|
export {};
|
data/core/hooks.d.ts
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
declare let useState: <T>(t: T | (() => T)) => [T, (t: T | ((t: T) => T)) => void];
|
2
|
+
declare let useEffect: (f: (() => void) | (() => (() => void)), deps: any[]) => void;
|
3
|
+
declare let useMemo: <T>(f: () => T, deps: any[]) => T;
|
4
|
+
declare type InitializeHooksParams = {
|
5
|
+
useState: typeof useState;
|
6
|
+
useEffect: typeof useEffect;
|
7
|
+
useMemo: typeof useMemo;
|
8
|
+
};
|
9
|
+
export declare function initializeHooks(hooks: InitializeHooksParams): void;
|
10
|
+
interface ModelStatus {
|
11
|
+
complete: boolean;
|
12
|
+
notfound?: boolean;
|
13
|
+
connected: boolean;
|
14
|
+
}
|
15
|
+
export declare type DataAndStatus<T> = [T | null, ModelStatus];
|
16
|
+
export interface Request {
|
17
|
+
api: string;
|
18
|
+
params?: any;
|
19
|
+
query: any;
|
20
|
+
}
|
21
|
+
export declare function useArSyncModel<T>(request: Request | null): DataAndStatus<T>;
|
22
|
+
interface FetchStatus {
|
23
|
+
complete: boolean;
|
24
|
+
notfound?: boolean;
|
25
|
+
}
|
26
|
+
declare type DataStatusUpdate<T> = [T | null, FetchStatus, () => void];
|
27
|
+
export declare function useArSyncFetch<T>(request: Request | null): DataStatusUpdate<T>;
|
28
|
+
export {};
|
data/core/hooks.js
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const ArSyncApi_1 = require("./ArSyncApi");
|
4
|
+
const ArSyncModel_1 = require("./ArSyncModel");
|
5
|
+
let useState;
|
6
|
+
let useEffect;
|
7
|
+
let useMemo;
|
8
|
+
function initializeHooks(hooks) {
|
9
|
+
useState = hooks.useState;
|
10
|
+
useEffect = hooks.useEffect;
|
11
|
+
useMemo = hooks.useMemo;
|
12
|
+
}
|
13
|
+
exports.initializeHooks = initializeHooks;
|
14
|
+
function checkHooks() {
|
15
|
+
if (!useState)
|
16
|
+
throw 'uninitialized. needs `initializeHooks({ useState, useEffect, useMemo })`';
|
17
|
+
}
|
18
|
+
const initialResult = [null, { complete: false, notfound: undefined, connected: true }];
|
19
|
+
function useArSyncModel(request) {
|
20
|
+
checkHooks();
|
21
|
+
const [result, setResult] = useState(initialResult);
|
22
|
+
const requestString = JSON.stringify(request && request.params);
|
23
|
+
useEffect(() => {
|
24
|
+
if (!request) {
|
25
|
+
setResult(initialResult);
|
26
|
+
return () => { };
|
27
|
+
}
|
28
|
+
const model = new ArSyncModel_1.default(request, { immutable: true });
|
29
|
+
function update() {
|
30
|
+
const { complete, notfound, connected, data } = model;
|
31
|
+
setResult(resultWas => {
|
32
|
+
const [, statusWas] = resultWas;
|
33
|
+
const statusPersisted = statusWas.complete === complete && statusWas.notfound === notfound && statusWas.connected === connected;
|
34
|
+
const status = statusPersisted ? statusWas : { complete, notfound, connected };
|
35
|
+
return [data, status];
|
36
|
+
});
|
37
|
+
}
|
38
|
+
if (model.complete) {
|
39
|
+
update();
|
40
|
+
}
|
41
|
+
else {
|
42
|
+
setResult(initialResult);
|
43
|
+
}
|
44
|
+
model.subscribe('change', update);
|
45
|
+
model.subscribe('connection', update);
|
46
|
+
return () => model.release();
|
47
|
+
}, [requestString]);
|
48
|
+
return result;
|
49
|
+
}
|
50
|
+
exports.useArSyncModel = useArSyncModel;
|
51
|
+
const initialFetchState = { data: null, status: { complete: false, notfound: undefined } };
|
52
|
+
function useArSyncFetch(request) {
|
53
|
+
checkHooks();
|
54
|
+
const [state, setState] = useState(initialFetchState);
|
55
|
+
const requestString = JSON.stringify(request && request.params);
|
56
|
+
const loader = useMemo(() => {
|
57
|
+
let lastLoadId = 0;
|
58
|
+
let timer = null;
|
59
|
+
function cancel() {
|
60
|
+
if (timer)
|
61
|
+
clearTimeout(timer);
|
62
|
+
timer = null;
|
63
|
+
lastLoadId++;
|
64
|
+
}
|
65
|
+
function fetch(request, retryCount) {
|
66
|
+
cancel();
|
67
|
+
const currentLoadingId = lastLoadId;
|
68
|
+
ArSyncApi_1.default.fetch(request).then((response) => {
|
69
|
+
if (currentLoadingId !== lastLoadId)
|
70
|
+
return;
|
71
|
+
setState({ data: response, status: { complete: true, notfound: false } });
|
72
|
+
}).catch(e => {
|
73
|
+
if (currentLoadingId !== lastLoadId)
|
74
|
+
return;
|
75
|
+
if (!e.retry) {
|
76
|
+
setState({ data: null, status: { complete: true, notfound: true } });
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
timer = setTimeout(() => fetch(request, retryCount + 1), 1000 * Math.min(4 ** retryCount, 30));
|
80
|
+
});
|
81
|
+
}
|
82
|
+
function update() {
|
83
|
+
if (request) {
|
84
|
+
setState(state => {
|
85
|
+
const { data, status } = state;
|
86
|
+
if (!status.complete && status.notfound === undefined)
|
87
|
+
return state;
|
88
|
+
return { data, status: { complete: false, notfound: undefined } };
|
89
|
+
});
|
90
|
+
fetch(request, 0);
|
91
|
+
}
|
92
|
+
else {
|
93
|
+
setState(initialFetchState);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
return { update, cancel };
|
97
|
+
}, [requestString]);
|
98
|
+
useEffect(() => {
|
99
|
+
setState(initialFetchState);
|
100
|
+
loader.update();
|
101
|
+
return () => loader.cancel();
|
102
|
+
}, [requestString]);
|
103
|
+
return [state.data, state.status, loader.update];
|
104
|
+
}
|
105
|
+
exports.useArSyncFetch = useArSyncFetch;
|
data/index.d.ts
ADDED
data/index.js
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
var ArSyncModel_1 = require("./core/ArSyncModel");
|
4
|
+
exports.ArSyncModel = ArSyncModel_1.default;
|
5
|
+
var ArSyncApi_1 = require("./core/ArSyncApi");
|
6
|
+
exports.ArSyncApi = ArSyncApi_1.default;
|
data/lib/ar_sync.rb
CHANGED
@@ -1,22 +1,5 @@
|
|
1
1
|
module ArSync
|
2
|
-
module
|
3
|
-
module TreeSync; end
|
4
|
-
def self.use(mode, klass: ActiveRecord::Base)
|
5
|
-
case mode
|
6
|
-
when :tree
|
7
|
-
if klass.ancestors.include? ArSync::GraphSync
|
8
|
-
raise ArgumentError, 'already activated ArSync::GraphSync'
|
9
|
-
end
|
10
|
-
klass.include ArSync::TreeSync
|
11
|
-
when :graph
|
12
|
-
if klass.ancestors.include? ArSync::TreeSync
|
13
|
-
raise ArgumentError, 'already activated ArSync::TreeSync'
|
14
|
-
end
|
15
|
-
klass.include ArSync::GraphSync
|
16
|
-
else
|
17
|
-
raise ArgumentError, 'argument should be :tree or :graph'
|
18
|
-
end
|
19
|
-
end
|
2
|
+
module ModelBase; end
|
20
3
|
end
|
21
4
|
require 'ar_sync/version'
|
22
5
|
require 'ar_sync/core'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative 'field'
|
2
2
|
require_relative 'collection'
|
3
3
|
|
4
|
-
module ArSync::
|
4
|
+
module ArSync::ModelBase::ClassMethods
|
5
5
|
def _sync_self?
|
6
6
|
instance_variable_defined? '@_sync_self'
|
7
7
|
end
|
@@ -30,89 +30,16 @@ module ArSync::ClassMethodsBase
|
|
30
30
|
superclass._each_sync_child(&block) if superclass < ActiveRecord::Base
|
31
31
|
end
|
32
32
|
|
33
|
-
def sync_parent(parent, inverse_of:, only_to: nil)
|
33
|
+
def sync_parent(parent, inverse_of:, only_to: nil, watch: nil)
|
34
34
|
_initialize_sync_callbacks
|
35
35
|
_sync_parents_info << [
|
36
36
|
parent,
|
37
|
-
{ inverse_name: inverse_of, only_to: only_to }
|
37
|
+
{ inverse_name: inverse_of, only_to: only_to, watch: watch }
|
38
38
|
]
|
39
39
|
end
|
40
|
-
end
|
41
|
-
|
42
|
-
module ArSync::TreeSync::ClassMethods
|
43
|
-
include ArSync::ClassMethodsBase
|
44
|
-
def sync_collection(name)
|
45
|
-
ArSync::Collection::Tree.find self, name
|
46
|
-
end
|
47
|
-
|
48
|
-
def sync_has_data(*names, **option, &original_data_block)
|
49
|
-
@_sync_self = true
|
50
|
-
option = option.dup
|
51
|
-
if original_data_block
|
52
|
-
data_block = ->(*args) { instance_exec(*args, &original_data_block).as_json }
|
53
|
-
end
|
54
|
-
option[:params_type] = {}
|
55
|
-
names.each do |name|
|
56
|
-
type_override = data_block.nil? && reflect_on_association(name.to_s.underscore) ? { type: :any } : {}
|
57
|
-
_sync_define ArSync::DataField.new(name), option.merge(type_override), &data_block
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def sync_has_one(name, **option, &data_block)
|
62
|
-
_sync_define ArSync::HasOneField.new(name), option, &data_block
|
63
|
-
end
|
64
|
-
|
65
|
-
def sync_has_many(name, order: :asc, propagate_when: nil, params_type: nil, limit: nil, preload: nil, association: nil, **option, &data_block)
|
66
|
-
if data_block.nil? && preload.nil?
|
67
|
-
underscore_name = name.to_s.underscore.to_sym
|
68
|
-
preload = lambda do |records, _context, params|
|
69
|
-
ArSerializer::Field.preload_association(
|
70
|
-
self, records, association || underscore_name,
|
71
|
-
order: (!limit && params && params[:order]) || order,
|
72
|
-
limit: [params && params[:limit]&.to_i, limit].compact.min
|
73
|
-
)
|
74
|
-
end
|
75
|
-
data_block = lambda do |preloaded, _context, _params|
|
76
|
-
preloaded ? preloaded[id] || [] : send(name)
|
77
|
-
end
|
78
|
-
params_type = { limit?: :int, order?: [{ :* => %w[asc desc] }, 'asc', 'desc'] }
|
79
|
-
else
|
80
|
-
params_type = {}
|
81
|
-
end
|
82
|
-
field = ArSync::HasManyField.new name, association: association, order: order, limit: limit, propagate_when: propagate_when
|
83
|
-
_sync_define field, preload: preload, association: association, params_type: params_type, **option, &data_block
|
84
|
-
end
|
85
|
-
|
86
|
-
def _sync_define(info, **option, &data_block)
|
87
|
-
_initialize_sync_callbacks
|
88
|
-
_sync_children_info[info.name] = info
|
89
|
-
serializer_field info.name, **option, &data_block unless _serializer_field_info info.name
|
90
|
-
serializer_field info.name, **option, namespace: :sync, &data_block
|
91
|
-
end
|
92
|
-
|
93
|
-
def sync_define_collection(name, limit: nil, order: :asc)
|
94
|
-
_initialize_sync_callbacks
|
95
|
-
collection = ArSync::Collection::Tree.new self, name, limit: limit, order: order
|
96
|
-
sync_parent collection, inverse_of: [self, name]
|
97
|
-
end
|
98
|
-
|
99
|
-
def _initialize_sync_callbacks
|
100
|
-
return if instance_variable_defined? '@_sync_callbacks_initialized'
|
101
|
-
@_sync_callbacks_initialized = true
|
102
|
-
_sync_define ArSync::DataField.new(:id)
|
103
|
-
%i[create update destroy].each do |action|
|
104
|
-
after_commit on: action do
|
105
|
-
next if ArSync.skip_notification?
|
106
|
-
self.class.default_scoped.scoping { _sync_notify action }
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
40
|
|
112
|
-
module ArSync::GraphSync::ClassMethods
|
113
|
-
include ArSync::ClassMethodsBase
|
114
41
|
def sync_collection(name)
|
115
|
-
ArSync::Collection
|
42
|
+
ArSync::Collection.find self, name
|
116
43
|
end
|
117
44
|
|
118
45
|
def sync_has_data(*names, **option, &data_block)
|
@@ -153,22 +80,33 @@ module ArSync::GraphSync::ClassMethods
|
|
153
80
|
limit: [params && params[:limit]&.to_i, limit].compact.min
|
154
81
|
)
|
155
82
|
end
|
83
|
+
serializer_data_block = lambda do |preloaded, _context, _params|
|
84
|
+
preloaded ? preloaded[id] || [] : send(name)
|
85
|
+
end
|
156
86
|
params_type = { limit?: :int, order?: [{ :* => %w[asc desc] }, 'asc', 'desc'] }
|
157
87
|
else
|
158
88
|
params_type = {}
|
159
89
|
end
|
160
|
-
_sync_define
|
161
|
-
|
162
|
-
|
163
|
-
|
90
|
+
_sync_define(
|
91
|
+
name,
|
92
|
+
serializer_data_block: serializer_data_block,
|
93
|
+
preload: preload,
|
94
|
+
association: association,
|
95
|
+
params_type: params_type,
|
96
|
+
**option,
|
97
|
+
&data_block
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
def _sync_define(name, serializer_data_block: nil, **option, &data_block)
|
164
102
|
_initialize_sync_callbacks
|
165
|
-
serializer_field name, **option, &data_block unless _serializer_field_info name
|
103
|
+
serializer_field name, **option, &(serializer_data_block || data_block) unless _serializer_field_info name
|
166
104
|
serializer_field name, **option, namespace: :sync, &data_block
|
167
105
|
end
|
168
106
|
|
169
107
|
def sync_define_collection(name, limit: nil, order: :asc)
|
170
108
|
_initialize_sync_callbacks
|
171
|
-
collection = ArSync::Collection
|
109
|
+
collection = ArSync::Collection.new self, name, limit: limit, order: order
|
172
110
|
sync_parent collection, inverse_of: [self, name]
|
173
111
|
end
|
174
112
|
|
@@ -176,8 +114,9 @@ module ArSync::GraphSync::ClassMethods
|
|
176
114
|
return if instance_variable_defined? '@_sync_callbacks_initialized'
|
177
115
|
@_sync_callbacks_initialized = true
|
178
116
|
mod = Module.new do
|
179
|
-
def
|
117
|
+
def _write_attribute(attr_name, value)
|
180
118
|
self.class.default_scoped.scoping do
|
119
|
+
@_sync_watch_values_before_mutation ||= _sync_current_watch_values
|
181
120
|
@_sync_parents_info_before_mutation ||= _sync_current_parents_info
|
182
121
|
@_sync_belongs_to_info_before_mutation ||= _sync_current_belongs_to_info
|
183
122
|
end
|
@@ -185,32 +124,35 @@ module ArSync::GraphSync::ClassMethods
|
|
185
124
|
end
|
186
125
|
end
|
187
126
|
prepend mod
|
188
|
-
attr_reader :_sync_parents_info_before_mutation, :_sync_belongs_to_info_before_mutation
|
127
|
+
attr_reader :_sync_parents_info_before_mutation, :_sync_belongs_to_info_before_mutation, :_sync_watch_values_before_mutation
|
189
128
|
|
190
129
|
_sync_define :id
|
191
130
|
|
192
131
|
_sync_define :sync_keys, type: [:string] do |current_user|
|
193
|
-
ArSync.
|
132
|
+
ArSync.sync_keys self, current_user
|
194
133
|
end
|
195
134
|
|
196
135
|
_sync_define :defaults, namespace: :sync do |current_user|
|
197
|
-
{ sync_keys: ArSync.
|
136
|
+
{ sync_keys: ArSync.sync_keys(self, current_user) }
|
198
137
|
end
|
199
138
|
|
200
139
|
before_destroy do
|
201
140
|
@_sync_parents_info_before_mutation ||= _sync_current_parents_info
|
141
|
+
@_sync_watch_values_before_mutation ||= _sync_current_watch_values
|
202
142
|
@_sync_belongs_to_info_before_mutation ||= _sync_current_belongs_to_info
|
203
143
|
end
|
204
144
|
|
205
145
|
before_save on: :create do
|
206
|
-
@_sync_parents_info_before_mutation ||=
|
207
|
-
@
|
146
|
+
@_sync_parents_info_before_mutation ||= {}
|
147
|
+
@_sync_watch_values_before_mutation ||= {}
|
148
|
+
@_sync_belongs_to_info_before_mutation ||= {}
|
208
149
|
end
|
209
150
|
|
210
151
|
%i[create update destroy].each do |action|
|
211
152
|
after_commit on: action do
|
212
153
|
next if ArSync.skip_notification?
|
213
154
|
self.class.default_scoped.scoping { _sync_notify action }
|
155
|
+
@_sync_watch_values_before_mutation = nil
|
214
156
|
@_sync_parents_info_before_mutation = nil
|
215
157
|
@_sync_belongs_to_info_before_mutation = nil
|
216
158
|
end
|
data/lib/ar_sync/collection.rb
CHANGED
@@ -11,11 +11,6 @@ class ArSync::Collection
|
|
11
11
|
define_singleton_method(name) { to_a }
|
12
12
|
end
|
13
13
|
|
14
|
-
def sync_send_event(type:, to_user: nil, data:)
|
15
|
-
event_data = { type: type, data: data }
|
16
|
-
ArSync.sync_tree_send to: self, action: :event, path: [], data: event_data, to_user: to_user
|
17
|
-
end
|
18
|
-
|
19
14
|
def to_a
|
20
15
|
all = klass.all
|
21
16
|
all = all.order id: order if order
|
@@ -30,35 +25,15 @@ class ArSync::Collection
|
|
30
25
|
def self.find(klass, name)
|
31
26
|
defined_collections[[klass, name]]
|
32
27
|
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class ArSync::Collection::Tree < ArSync::Collection
|
36
|
-
def initialize(*)
|
37
|
-
super
|
38
|
-
@field = ArSync::CollectionField.new @name, limit: @limit, order: @order
|
39
|
-
self.class._sync_children_info[[@klass, @name]] = @field
|
40
|
-
end
|
41
|
-
|
42
|
-
def _sync_notify_parent(*); end
|
43
|
-
|
44
|
-
def self._sync_children_info
|
45
|
-
@sync_children_info ||= {}
|
46
|
-
end
|
47
|
-
|
48
|
-
def self._sync_child_info(key)
|
49
|
-
_sync_children_info[key]
|
50
|
-
end
|
51
|
-
end
|
52
28
|
|
53
|
-
|
54
|
-
def _sync_notify_child_changed(_child, _name, _to_user, _owned); end
|
29
|
+
def _sync_notify_child_changed(_name, _to_user); end
|
55
30
|
|
56
|
-
def _sync_notify_child_added(child, _name, to_user
|
57
|
-
ArSync.
|
31
|
+
def _sync_notify_child_added(child, _name, to_user)
|
32
|
+
ArSync.sync_send to: self, action: :add, model: child, path: :collection, to_user: to_user
|
58
33
|
end
|
59
34
|
|
60
35
|
def _sync_notify_child_removed(child, _name, to_user, _owned)
|
61
|
-
ArSync.
|
36
|
+
ArSync.sync_send to: self, action: :remove, model: child, path: :collection, to_user: to_user
|
62
37
|
end
|
63
38
|
|
64
39
|
def self._sync_children_info
|