ar_sync 1.0.5 → 1.1.0

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.
data/core/hooks.js CHANGED
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useArSyncFetch = exports.useArSyncModel = exports.initializeHooks = void 0;
3
4
  var ArSyncApi_1 = require("./ArSyncApi");
4
5
  var ArSyncModel_1 = require("./ArSyncModel");
5
6
  var useState;
@@ -19,9 +20,10 @@ function checkHooks() {
19
20
  }
20
21
  var initialResult = [null, { complete: false, notfound: undefined, connected: true }];
21
22
  function useArSyncModel(request) {
23
+ var _a;
22
24
  checkHooks();
23
- var _a = useState(initialResult), result = _a[0], setResult = _a[1];
24
- var requestString = JSON.stringify(request && request.params);
25
+ var _b = useState(initialResult), result = _b[0], setResult = _b[1];
26
+ var requestString = JSON.stringify((_a = request === null || request === void 0 ? void 0 : request.id) !== null && _a !== void 0 ? _a : request === null || request === void 0 ? void 0 : request.params);
25
27
  var prevRequestStringRef = useRef(requestString);
26
28
  useEffect(function () {
27
29
  prevRequestStringRef.current = requestString;
@@ -68,13 +70,14 @@ function extractParams(query, output) {
68
70
  return output;
69
71
  }
70
72
  function useArSyncFetch(request) {
73
+ var _a;
71
74
  checkHooks();
72
- var _a = useState(initialFetchState), state = _a[0], setState = _a[1];
75
+ var _b = useState(initialFetchState), state = _b[0], setState = _b[1];
73
76
  var query = request && request.query;
74
- var params = request && request.params;
77
+ var resourceIdentifier = (_a = request === null || request === void 0 ? void 0 : request.id) !== null && _a !== void 0 ? _a : request === null || request === void 0 ? void 0 : request.params;
75
78
  var requestString = useMemo(function () {
76
- return JSON.stringify(extractParams(query, [params]));
77
- }, [query, params]);
79
+ return JSON.stringify(extractParams(query, [resourceIdentifier]));
80
+ }, [query, resourceIdentifier]);
78
81
  var prevRequestStringRef = useRef(requestString);
79
82
  var loader = useMemo(function () {
80
83
  var lastLoadId = 0;
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ar_sync.gemspec
6
+ gemspec path: ".."
7
+
8
+ gem "activerecord", "~> 6.0.0"
9
+ gem 'ar_serializer', github: 'tompng/ar_serializer'
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ar_sync.gemspec
6
+ gemspec path: ".."
7
+
8
+ gem "activerecord", "~> 7.0.0"
9
+ gem 'ar_serializer', github: 'tompng/ar_serializer'
data/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var ArSyncModel_1 = require("./core/ArSyncModel");
4
- exports.ArSyncModel = ArSyncModel_1.default;
4
+ Object.defineProperty(exports, "ArSyncModel", { enumerable: true, get: function () { return ArSyncModel_1.default; } });
5
5
  var ArSyncApi_1 = require("./core/ArSyncApi");
6
- exports.ArSyncApi = ArSyncApi_1.default;
6
+ Object.defineProperty(exports, "ArSyncApi", { enumerable: true, get: function () { return ArSyncApi_1.default; } });
@@ -1,9 +1,10 @@
1
- require_relative 'field'
2
1
  require_relative 'collection'
3
2
 
4
3
  module ArSync::ModelBase::ClassMethods
5
4
  def _sync_self?
6
- instance_variable_defined? '@_sync_self'
5
+ return true if defined?(@_sync_self)
6
+
7
+ superclass._sync_self? if superclass < ActiveRecord::Base
7
8
  end
8
9
 
9
10
  def _sync_parents_info
@@ -60,30 +61,59 @@ module ArSync::ModelBase::ClassMethods
60
61
  _sync_define name, **option, &data_block
61
62
  end
62
63
 
63
- def _sync_has_many(name, order: :asc, limit: nil, preload: nil, association: nil, **option, &data_block)
64
- raise "order not in [:asc, :desc] : #{order}" unless %i[asc desc].include? order
64
+ def _sync_has_many(name, direction: :asc, first: nil, last: nil, preload: nil, association: nil, **option, &data_block)
65
+ raise ArgumentError, 'direction not in [:asc, :desc]' unless %i[asc desc].include? direction
66
+ raise ArgumentError, 'first and last cannot be both specified' if first && last
67
+ raise ArgumentError, 'cannot use first or last with direction: :desc' if direction != :asc && !first && !last
65
68
  if data_block.nil? && preload.nil?
66
- underscore_name = name.to_s.underscore.to_sym
69
+ association_name = association || name.to_s.underscore.to_sym
70
+ order_option_from_params = lambda do |params|
71
+ if first || last
72
+ params_first = first && [first, params[:first]&.to_i].compact.min
73
+ params_last = last && [last, params[:last]&.to_i].compact.min
74
+ { direction: direction, first: params_first, last: params_last }
75
+ else
76
+ {
77
+ first: params[:first]&.to_i,
78
+ last: params[:last]&.to_i,
79
+ order_by: params[:order_by],
80
+ direction: params[:direction] || :asc
81
+ }
82
+ end
83
+ end
67
84
  preload = lambda do |records, _context, **params|
68
85
  ArSerializer::Field.preload_association(
69
- self, records, association || underscore_name,
70
- order: (!limit && params && params[:order]) || order,
71
- limit: [params && params[:limit]&.to_i, limit].compact.min
86
+ self,
87
+ records,
88
+ association_name,
89
+ **order_option_from_params.call(params)
72
90
  )
73
91
  end
74
92
  data_block = lambda do |preloaded, _context, **params|
75
- records = preloaded ? preloaded[id] || [] : send(name)
76
- next records unless limit || order == :asc
93
+ records = preloaded ? preloaded[id] || [] : __send__(name)
94
+ next records unless first || last
77
95
  ArSync::CollectionWithOrder.new(
78
96
  records,
79
- order: (!limit && params && params[:order]) || order,
80
- limit: [params && params[:limit]&.to_i, limit].compact.min
97
+ **order_option_from_params.call(params)
81
98
  )
82
99
  end
83
100
  serializer_data_block = lambda do |preloaded, _context, **_params|
84
- preloaded ? preloaded[id] || [] : send(name)
101
+ preloaded ? preloaded[id] || [] : __send__(name)
102
+ end
103
+ if first
104
+ params_type = { first?: :int }
105
+ elsif last
106
+ params_type = { last?: :int }
107
+ else
108
+ params_type = lambda do
109
+ orderable_keys = reflect_on_association(association_name)&.klass&._serializer_orderable_field_keys || []
110
+ orderable_keys &= [*option[:only]].map(&:to_s) if option[:only]
111
+ orderable_keys -= [*option[:except]].map(&:to_s) if option[:except]
112
+ orderable_keys |= ['id']
113
+ order_by = orderable_keys.size == 1 ? orderable_keys.first : orderable_keys.sort
114
+ { first?: :int, last?: :int, direction?: %w[asc desc], orderBy?: order_by }
115
+ end
85
116
  end
86
- params_type = { limit?: :int, order?: [{ :* => %w[asc desc] }, 'asc', 'desc'] }
87
117
  else
88
118
  params_type = {}
89
119
  end
@@ -104,18 +134,25 @@ module ArSync::ModelBase::ClassMethods
104
134
  serializer_field name, **option, namespace: :sync, &data_block
105
135
  end
106
136
 
107
- def sync_define_collection(name, limit: nil, order: :asc)
137
+ def sync_define_collection(name, first: nil, last: nil, direction: :asc)
108
138
  _initialize_sync_callbacks
109
- collection = ArSync::Collection.new self, name, limit: limit, order: order
139
+ collection = ArSync::Collection.new self, name, first: first, last: last, direction: direction
110
140
  sync_parent collection, inverse_of: [self, name]
111
141
  end
112
142
 
113
143
  module WriteHook
114
144
  def _initialize_sync_info_before_mutation
115
- self.class.default_scoped.scoping do
116
- @_sync_watch_values_before_mutation ||= _sync_current_watch_values
117
- @_sync_parents_info_before_mutation ||= _sync_current_parents_info
118
- @_sync_belongs_to_info_before_mutation ||= _sync_current_belongs_to_info
145
+ return unless defined? @_initialized
146
+ if new_record?
147
+ @_sync_watch_values_before_mutation ||= {}
148
+ @_sync_parents_info_before_mutation ||= {}
149
+ @_sync_belongs_to_info_before_mutation ||= {}
150
+ else
151
+ self.class.default_scoped.scoping do
152
+ @_sync_watch_values_before_mutation ||= _sync_current_watch_values
153
+ @_sync_parents_info_before_mutation ||= _sync_current_parents_info
154
+ @_sync_belongs_to_info_before_mutation ||= _sync_current_belongs_to_info
155
+ end
119
156
  end
120
157
  end
121
158
  def _write_attribute(attr_name, value)
@@ -129,7 +166,7 @@ module ArSync::ModelBase::ClassMethods
129
166
  end
130
167
 
131
168
  def _initialize_sync_callbacks
132
- return if instance_variable_defined? '@_sync_callbacks_initialized'
169
+ return if defined? @_sync_callbacks_initialized
133
170
  @_sync_callbacks_initialized = true
134
171
  prepend WriteHook
135
172
  attr_reader :_sync_parents_info_before_mutation, :_sync_belongs_to_info_before_mutation, :_sync_watch_values_before_mutation
@@ -140,8 +177,12 @@ module ArSync::ModelBase::ClassMethods
140
177
  ArSync.sync_keys self, current_user
141
178
  end
142
179
 
143
- _sync_define :defaults, namespace: :sync do |current_user|
144
- { sync_keys: ArSync.sync_keys(self, current_user) }
180
+ serializer_defaults namespace: :sync do |current_user|
181
+ { id: id, sync_keys: ArSync.sync_keys(self, current_user) }
182
+ end
183
+
184
+ after_initialize do
185
+ @_initialized = true
145
186
  end
146
187
 
147
188
  before_destroy do
@@ -1,21 +1,26 @@
1
- require_relative 'field'
2
-
3
1
  class ArSync::Collection
4
- attr_reader :klass, :name, :limit, :order
5
- def initialize(klass, name, limit: nil, order: nil)
2
+ attr_reader :klass, :name, :first, :last, :direction, :ordering
3
+ def initialize(klass, name, first: nil, last: nil, direction: nil)
4
+ direction ||= :asc
6
5
  @klass = klass
7
6
  @name = name
8
- @limit = limit
9
- @order = order
7
+ @first = first
8
+ @last = last
9
+ @direction = direction
10
+ @ordering = { first: first, last: last, direction: direction }.compact
10
11
  self.class.defined_collections[[klass, name]] = self
11
12
  define_singleton_method(name) { to_a }
12
13
  end
13
14
 
14
15
  def to_a
15
- all = klass.all
16
- all = all.order id: order if order
17
- all = all.limit limit if limit
18
- all
16
+ if first
17
+ klass.order(id: direction).limit(first).to_a
18
+ elsif last
19
+ rev = direction == :asc ? :desc : :asc
20
+ klass.order(id: rev).limit(last).reverse
21
+ else
22
+ klass.all.to_a
23
+ end
19
24
  end
20
25
 
21
26
  def self.defined_collections
@@ -45,14 +50,13 @@ class ArSync::Collection
45
50
  end
46
51
  end
47
52
 
48
- class ArSync::CollectionWithOrder < ArSerializer::CompositeValue
49
- def initialize(records, order:, limit:)
50
- @records = records
51
- @order = { mode: order, limit: limit }
52
- end
53
-
54
- def ar_serializer_build_sub_calls
55
- values = @records.map { {} }
56
- [{ order: @order, collection: values }, @records.zip(values)]
53
+ class ArSync::CollectionWithOrder < ArSerializer::CustomSerializable
54
+ def initialize(records, direction:, first: nil, last: nil)
55
+ super records do |results|
56
+ {
57
+ ordering: { direction: direction || :asc, first: first, last: last }.compact,
58
+ collection: records.map(&results).compact
59
+ }
60
+ end
57
61
  end
58
62
  end
data/lib/ar_sync/core.rb CHANGED
@@ -82,17 +82,17 @@ module ArSync
82
82
  end
83
83
 
84
84
  def self.serialize(record_or_records, query, user: nil)
85
- ArSerializer.serialize record_or_records, query, context: user, include_id: true, use: :sync
85
+ ArSerializer.serialize record_or_records, query, context: user, use: :sync
86
86
  end
87
87
 
88
88
  def self.sync_serialize(target, user, query)
89
89
  case target
90
90
  when ArSync::Collection, ArSync::ModelBase
91
- serialized = ArSerializer.serialize target, query, context: user, include_id: true, use: :sync
91
+ serialized = ArSerializer.serialize target, query, context: user, use: :sync
92
92
  return serialized if target.is_a? ArSync::ModelBase
93
93
  {
94
94
  sync_keys: ArSync.sync_keys(target, user),
95
- order: { mode: target.order, limit: target.limit },
95
+ ordering: target.ordering,
96
96
  collection: serialized
97
97
  }
98
98
  when ActiveRecord::Relation, Array
@@ -8,7 +8,7 @@ module ArSync::ModelBase::InstanceMethods
8
8
  values = {}
9
9
  self.class._each_sync_parent do |_, info|
10
10
  [*info[:watch]].each do |watch|
11
- values[watch] = watch.is_a?(Proc) ? instance_exec(&watch) : send(watch)
11
+ values[watch] = watch.is_a?(Proc) ? instance_exec(&watch) : __send__(watch)
12
12
  end
13
13
  end
14
14
  values
data/lib/ar_sync/rails.rb CHANGED
@@ -94,7 +94,7 @@ module ArSync
94
94
  info = sch.class._serializer_field_info api_name
95
95
  raise ArSync::ApiNotFound, "#{type.to_s.capitalize} API named `#{api_name}` not configured" unless info
96
96
  api_params = (request[:params].as_json || {}).transform_keys(&:to_sym)
97
- model = sch.instance_exec(current_user, api_params, &info.data_block)
97
+ model = sch.instance_exec(current_user, **api_params, &info.data_block)
98
98
  { data: yield(model, current_user, request[:query].as_json) }
99
99
  rescue StandardError => e
100
100
  { error: handle_exception(e) }
@@ -1,3 +1,3 @@
1
1
  module ArSync
2
- VERSION = '1.0.5'
2
+ VERSION = '1.1.0'
3
3
  end