synced 1.1.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -7
- data/lib/synced/model.rb +38 -28
- data/lib/synced/strategies/full.rb +8 -7
- data/lib/synced/strategies/synced_all_at_timestamp_strategy.rb +31 -0
- data/lib/synced/strategies/synced_per_scope_timestamp_strategy.rb +26 -0
- data/lib/synced/strategies/updated_since.rb +12 -3
- data/lib/synced/synchronizer.rb +11 -11
- data/lib/synced/timestamp.rb +19 -0
- data/lib/synced/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3293144a530b0b41b214912ec147152b207e4b2
|
4
|
+
data.tar.gz: a016b6c1cb3628884c5c465a2c84e9f167c83a36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b42ca3a24e7d58cfd666a01de3c8c22e28bd67db53f74649a77c678e6212b5e689977d3158a96d202bc3167e0dd41d180ea858e01c9ea29639fd5e95ef2e9e4
|
7
|
+
data.tar.gz: e9da5291a6c4fbbb7a2e52078b6a4817e6b6cd631eb6acbaeefa519ace7db4ebc295af66235065561ac48c0766c8d5cb8a10b6144a1b81c565196b89d0338eba
|
data/README.md
CHANGED
@@ -77,6 +77,13 @@ rental.synced_data.bedrooms # => 4
|
|
77
77
|
rental.synced_data.rental_type # => "villa"
|
78
78
|
```
|
79
79
|
|
80
|
+
## Synced strategies
|
81
|
+
|
82
|
+
There are currently 3 synced strategies: `:full`, `:updated_since` and `:check`.
|
83
|
+
- `:full` strategy fetches all available data each time, being simple but very inefficient in most cases.
|
84
|
+
- `:updated_since` is default strategy and syncs only changes since last sync. It's more efficient, but also more complex.
|
85
|
+
- `:check` strategy fetches everything like full one, but only compares the datas without updating anything.
|
86
|
+
|
80
87
|
## Synced database fields
|
81
88
|
|
82
89
|
Option name | Default value | Description | Required |
|
@@ -89,8 +96,7 @@ Custom fields name can be configured in the `synced` statement of your model:
|
|
89
96
|
|
90
97
|
```ruby
|
91
98
|
class Rental < ActiveRecord::Base
|
92
|
-
synced id_key: :remote_id, data_key: :remote_data
|
93
|
-
synced_all_at_key: :remote_all_synced_at
|
99
|
+
synced id_key: :remote_id, data_key: :remote_data
|
94
100
|
end
|
95
101
|
```
|
96
102
|
|
@@ -201,20 +207,30 @@ end
|
|
201
207
|
|
202
208
|
This will map remote `:description` to local `:headline` attribute.
|
203
209
|
|
204
|
-
## Partial updates (using
|
210
|
+
## Partial updates (using `:updated_since` strategy)
|
205
211
|
|
206
212
|
Partial updates mean that first synchronization will copy all of the remote
|
207
213
|
objects into local database and next synchronizations will sync only
|
208
214
|
added/changed and removed objects. This significantly improves synchronization
|
209
215
|
time and saves network traffic.
|
210
216
|
|
211
|
-
In order to enable it add timestamp column named `synced_all_at` to your
|
212
|
-
database. Synced will automatically detect it.
|
213
|
-
|
214
217
|
NOTE: In order it to work, given endpoint needs to support updated_since
|
215
218
|
parameter. Check [API documentation](http://docs.api.bookingsync.com/reference/)
|
216
219
|
for given endpoint.
|
217
220
|
|
221
|
+
### Storing last sync timestamps
|
222
|
+
|
223
|
+
When using `:updated_since` sync strategy you need to store the timestamp of the last sync somewhere.
|
224
|
+
By default `Synced::Strategies::SyncedAllAtTimestampStrategy` strategy is used, which requires
|
225
|
+
`synced_all_at` column to be present in the synced model. This is simple solution but on large syncs it causes serious
|
226
|
+
overhead on updating the timestamps on all the records.
|
227
|
+
|
228
|
+
There is also a `Synced::Strategies::SyncedPerScopeTimestampStrategy`, that uses another model,
|
229
|
+
`Synced::Timestamp`, to store the synchronization timestamps. Migration can be copied from the synced dummy app
|
230
|
+
`spec/dummy/db/migrate/20160126082137_create_synced_timestamps.rb`.
|
231
|
+
This strategy is added to fix the problems with massive updates on `synced_all_at`. Proper cleanup of timestamp records
|
232
|
+
is needed once in a while with `Synced::Timestamp.cleanup` (cleans records older than 1 week).
|
233
|
+
|
218
234
|
### Forcing local objects to be re-synced with the API
|
219
235
|
|
220
236
|
When you add a new column or change something in the synced attributes and you
|
@@ -392,7 +408,6 @@ Option name | Default value | Description
|
|
392
408
|
---------------------|------------------|-----------------------------------------------------------------------------------|--------|-------------|
|
393
409
|
`:id_key` | `:synced_id` | ID of the object fetched from the API | YES | NO |
|
394
410
|
`:data_key` | `:synced_data` | Object fetched from the API | YES | NO |
|
395
|
-
`:synced_all_at_key` | `:synced_all_at` | Time of the last synchronization | YES | NO |
|
396
411
|
`:associations` | `[]` | [Sync remote associations to local ones](#associations) | YES | NO |
|
397
412
|
`:local_attributes` | `[]` | [Sync remote attributes to local ones](#local-attributes) | YES | NO |
|
398
413
|
`:mapper` | `nil` | [Module used for mapping remote objects](#local-attributes-with-mapping-modules) | YES | NO |
|
data/lib/synced/model.rb
CHANGED
@@ -6,11 +6,10 @@ module Synced
|
|
6
6
|
#
|
7
7
|
# @param options [Hash] Configuration options for synced. They are inherited
|
8
8
|
# by subclasses, but can be overwritten in the subclass.
|
9
|
+
# @option options [Symbol] strategy: synchronization strategy, one of :full, :updated_since, :check.
|
10
|
+
# Defaults to :updated_since
|
9
11
|
# @option options [Symbol] id_key: attribute name under which
|
10
12
|
# remote object's ID is stored, default is :synced_id.
|
11
|
-
# @option options [Symbol] synced_all_at_key: attribute name under which
|
12
|
-
# last synchronization time is stored, default is :synced_all_at. It's only
|
13
|
-
# used when only_updated option is enabled.
|
14
13
|
# @option options [Boolean] only_updated: If true requests to API will take
|
15
14
|
# advantage of updated_since param and fetch only created/changed/deleted
|
16
15
|
# remote objects
|
@@ -34,28 +33,25 @@ module Synced
|
|
34
33
|
# Works only for partial (updated_since param) synchronizations.
|
35
34
|
# @option options [Array|Hash] delegate_attributes: Given attributes will be defined
|
36
35
|
# on synchronized object and delegated to synced_data Hash
|
37
|
-
# @option options [Hash]
|
36
|
+
# @option options [Hash] query_params: Given attributes and their values
|
38
37
|
# which will be passed to api client to perform search
|
39
|
-
def synced(
|
40
|
-
options.symbolize_keys!
|
38
|
+
def synced(strategy: :updated_since, **options)
|
41
39
|
options.assert_valid_keys(:associations, :data_key, :fields,
|
42
40
|
:globalized_attributes, :id_key, :include, :initial_sync_since,
|
43
|
-
:local_attributes, :mapper, :only_updated, :remove,
|
44
|
-
:delegate_attributes, :
|
45
|
-
class_attribute :synced_id_key, :
|
41
|
+
:local_attributes, :mapper, :only_updated, :remove,
|
42
|
+
:delegate_attributes, :query_params, :timestamp_strategy)
|
43
|
+
class_attribute :synced_id_key, :synced_data_key,
|
46
44
|
:synced_local_attributes, :synced_associations, :synced_only_updated,
|
47
45
|
:synced_mapper, :synced_remove, :synced_include, :synced_fields,
|
48
46
|
:synced_globalized_attributes, :synced_initial_sync_since, :synced_delegate_attributes,
|
49
|
-
:
|
47
|
+
:synced_query_params, :synced_timestamp_strategy, :synced_strategy
|
48
|
+
self.synced_strategy = strategy
|
50
49
|
self.synced_id_key = options.fetch(:id_key, :synced_id)
|
51
|
-
self.synced_all_at_key = options.fetch(:synced_all_at_key,
|
52
|
-
synced_column_presence(:synced_all_at))
|
53
50
|
self.synced_data_key = options.fetch(:data_key,
|
54
51
|
synced_column_presence(:synced_data))
|
55
52
|
self.synced_local_attributes = options.fetch(:local_attributes, [])
|
56
53
|
self.synced_associations = options.fetch(:associations, [])
|
57
|
-
self.synced_only_updated = options.fetch(:only_updated,
|
58
|
-
column_names.include?(synced_all_at_key.to_s))
|
54
|
+
self.synced_only_updated = options.fetch(:only_updated, synced_strategy == :updated_since)
|
59
55
|
self.synced_mapper = options.fetch(:mapper, nil)
|
60
56
|
self.synced_remove = options.fetch(:remove, false)
|
61
57
|
self.synced_include = options.fetch(:include, [])
|
@@ -65,7 +61,8 @@ module Synced
|
|
65
61
|
self.synced_initial_sync_since = options.fetch(:initial_sync_since,
|
66
62
|
nil)
|
67
63
|
self.synced_delegate_attributes = options.fetch(:delegate_attributes, [])
|
68
|
-
self.
|
64
|
+
self.synced_query_params = options.fetch(:query_params, {})
|
65
|
+
self.synced_timestamp_strategy = options.fetch(:timestamp_strategy, nil)
|
69
66
|
include Synced::DelegateAttributes
|
70
67
|
include Synced::HasSyncedData
|
71
68
|
end
|
@@ -77,7 +74,7 @@ module Synced
|
|
77
74
|
# @param model_class [Class] - ActiveRecord model class to which remote objects
|
78
75
|
# will be synchronized.
|
79
76
|
# @param scope [ActiveRecord::Base] - Within this object scope local objects
|
80
|
-
# will be synchronized. By default it's model_class.
|
77
|
+
# will be synchronized. By default it's model_class. Can be infered from active record association scope.
|
81
78
|
# @param remove [Boolean] - If it's true all local objects within
|
82
79
|
# current scope which are not present in the remote array will be destroyed.
|
83
80
|
# If only_updated is enabled, ids of objects to be deleted will be taken
|
@@ -97,42 +94,55 @@ module Synced
|
|
97
94
|
# create/remove/update rentals only within website.
|
98
95
|
# It requires relation website.rentals to exist.
|
99
96
|
#
|
100
|
-
#
|
97
|
+
# website.rentals.synchronize(remote: remote_rentals)
|
101
98
|
#
|
102
|
-
def synchronize(
|
103
|
-
options.
|
104
|
-
options.assert_valid_keys(:api, :fields, :include, :remote, :remove,
|
105
|
-
:scope, :strategy, :search_params, :association_sync)
|
99
|
+
def synchronize(scope: scope_from_relation, strategy: synced_strategy, **options)
|
100
|
+
options.assert_valid_keys(:api, :fields, :include, :remote, :remove, :query_params, :association_sync)
|
106
101
|
options[:remove] = synced_remove unless options.has_key?(:remove)
|
107
102
|
options[:include] = Array.wrap(synced_include) unless options.has_key?(:include)
|
108
103
|
options[:fields] = Array.wrap(synced_fields) unless options.has_key?(:fields)
|
109
|
-
options[:
|
104
|
+
options[:query_params] = synced_query_params unless options.has_key?(:query_params)
|
110
105
|
options.merge!({
|
106
|
+
scope: scope,
|
107
|
+
strategy: strategy,
|
111
108
|
id_key: synced_id_key,
|
112
109
|
synced_data_key: synced_data_key,
|
113
|
-
synced_all_at_key: synced_all_at_key,
|
114
110
|
data_key: synced_data_key,
|
115
111
|
local_attributes: synced_local_attributes,
|
116
112
|
associations: synced_associations,
|
117
113
|
only_updated: synced_only_updated,
|
118
114
|
mapper: synced_mapper,
|
119
115
|
globalized_attributes: synced_globalized_attributes,
|
120
|
-
initial_sync_since: synced_initial_sync_since
|
116
|
+
initial_sync_since: synced_initial_sync_since,
|
117
|
+
timestamp_strategy: synced_timestamp_strategy
|
121
118
|
})
|
122
119
|
Synced::Synchronizer.new(self, options).perform
|
123
120
|
end
|
124
121
|
|
125
|
-
# Reset
|
122
|
+
# Reset last sync timestamp for given scope, this forces synced to sync
|
126
123
|
# all the records on the next sync. Useful for cases when you add
|
127
124
|
# a new column to be synced and you use updated since strategy for faster
|
128
125
|
# synchronization.
|
129
|
-
def reset_synced
|
130
|
-
|
131
|
-
|
126
|
+
def reset_synced(scope: scope_from_relation)
|
127
|
+
options = {
|
128
|
+
scope: scope,
|
129
|
+
strategy: synced_strategy,
|
130
|
+
only_updated: synced_only_updated,
|
131
|
+
initial_sync_since: synced_initial_sync_since,
|
132
|
+
timestamp_strategy: synced_timestamp_strategy
|
133
|
+
}
|
134
|
+
Synced::Synchronizer.new(self, options).reset_synced
|
132
135
|
end
|
133
136
|
|
134
137
|
private
|
135
138
|
|
139
|
+
# attempt to get scope from association reflection, so you could do:
|
140
|
+
# account.bookings.synchronize
|
141
|
+
# and the scope would be account
|
142
|
+
def scope_from_relation
|
143
|
+
all.proxy_association.owner if all.respond_to?(:proxy_association)
|
144
|
+
end
|
145
|
+
|
136
146
|
def synced_column_presence(name)
|
137
147
|
name if column_names.include?(name.to_s)
|
138
148
|
end
|
@@ -21,8 +21,6 @@ module Synced
|
|
21
21
|
# will be synchronized. By default it's model_class.
|
22
22
|
# @option options [Symbol] id_key: attribute name under which
|
23
23
|
# remote object's ID is stored, default is :synced_id.
|
24
|
-
# @option options [Symbol] synced_all_at_key: attribute name under which
|
25
|
-
# remote object's sync time is stored, default is :synced_all_at
|
26
24
|
# @option options [Symbol] data_key: attribute name under which remote
|
27
25
|
# object's data is stored.
|
28
26
|
# @option options [Array] local_attributes: Array of attributes in the remote
|
@@ -48,7 +46,6 @@ module Synced
|
|
48
46
|
@model_class = model_class
|
49
47
|
@scope = options[:scope]
|
50
48
|
@id_key = options[:id_key]
|
51
|
-
@synced_all_at_key = options[:synced_all_at_key]
|
52
49
|
@data_key = options[:data_key]
|
53
50
|
@remove = options[:remove]
|
54
51
|
@only_updated = options[:only_updated]
|
@@ -64,7 +61,7 @@ module Synced
|
|
64
61
|
@perform_request = options[:remote].nil? && !@association_sync
|
65
62
|
@remote_objects = Array.wrap(options[:remote]) unless @perform_request
|
66
63
|
@globalized_attributes = synced_attributes_as_hash(options[:globalized_attributes])
|
67
|
-
@
|
64
|
+
@query_params = options[:query_params]
|
68
65
|
end
|
69
66
|
|
70
67
|
def perform
|
@@ -93,6 +90,10 @@ module Synced
|
|
93
90
|
end
|
94
91
|
end
|
95
92
|
|
93
|
+
def reset_synced
|
94
|
+
RuntimeError.new("Full strategy does not support reset_synced functionality")
|
95
|
+
end
|
96
|
+
|
96
97
|
private
|
97
98
|
|
98
99
|
def synchronize_associations(remote, local_object)
|
@@ -184,11 +185,11 @@ module Synced
|
|
184
185
|
end
|
185
186
|
options[:fields] = @fields if @fields.present?
|
186
187
|
options[:auto_paginate] = true
|
187
|
-
end.merge(
|
188
|
+
end.merge(query_params)
|
188
189
|
end
|
189
190
|
|
190
|
-
def
|
191
|
-
Hash[@
|
191
|
+
def query_params
|
192
|
+
Hash[@query_params.map do |param, value|
|
192
193
|
final_value = value.respond_to?(:call) ? search_param_value_for_lambda(value) : value
|
193
194
|
[param, final_value]
|
194
195
|
end]
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Synced
|
2
|
+
module Strategies
|
3
|
+
# This is a strategy for UpdatedSince defining how to store and update synced timestamps.
|
4
|
+
# It uses synced_all_at column on model to store update time.
|
5
|
+
class SyncedAllAtTimestampStrategy
|
6
|
+
attr_reader :relation_scope
|
7
|
+
|
8
|
+
def initialize(relation_scope:, **_options)
|
9
|
+
@relation_scope = relation_scope
|
10
|
+
end
|
11
|
+
|
12
|
+
def last_synced_at
|
13
|
+
relation_scope.minimum(synced_all_at_key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def update(timestamp)
|
17
|
+
relation_scope.update_all(synced_all_at_key => timestamp)
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset
|
21
|
+
relation_scope.update_all(synced_all_at_key => nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def synced_all_at_key
|
27
|
+
:synced_all_at
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'synced/timestamp'
|
2
|
+
|
3
|
+
module Synced
|
4
|
+
module Strategies
|
5
|
+
# This is a strategy for UpdatedSince defining how to store and update synced timestamps.
|
6
|
+
# It uses a separate timestamps table to track when different models were synced in specific scopes.
|
7
|
+
class SyncedPerScopeTimestampStrategy
|
8
|
+
def initialize(scope:, model_class:, **_options)
|
9
|
+
@scope = scope
|
10
|
+
@model_class = model_class
|
11
|
+
end
|
12
|
+
|
13
|
+
def last_synced_at
|
14
|
+
Synced::Timestamp.with_scope_and_model(@scope, @model_class).last_synced_at
|
15
|
+
end
|
16
|
+
|
17
|
+
def update(timestamp)
|
18
|
+
Synced::Timestamp.with_scope_and_model(@scope, @model_class).create!(synced_at: timestamp)
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset
|
22
|
+
Synced::Timestamp.with_scope_and_model(@scope, @model_class).delete_all
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require "synced/strategies/synced_all_at_timestamp_strategy"
|
2
|
+
require "synced/strategies/synced_per_scope_timestamp_strategy"
|
3
|
+
|
1
4
|
module Synced
|
2
5
|
module Strategies
|
3
6
|
# This strategy performs partial synchronization.
|
@@ -8,18 +11,24 @@ module Synced
|
|
8
11
|
def initialize(model_class, options = {})
|
9
12
|
super
|
10
13
|
@initial_sync_since = options[:initial_sync_since]
|
14
|
+
timestampt_strategy_class = options[:timestamp_strategy] || Synced::Strategies::SyncedAllAtTimestampStrategy
|
15
|
+
@timestamp_strategy = timestampt_strategy_class.new(relation_scope: relation_scope, scope: @scope, model_class: model_class)
|
11
16
|
end
|
12
17
|
|
13
18
|
def perform
|
14
19
|
super.tap do |local_objects|
|
15
|
-
instrument("
|
20
|
+
instrument("update_synced_timestamp_perform.synced", model: @model_class) do
|
16
21
|
# TODO: it can't be Time.now. this value has to be fetched from the API as well
|
17
22
|
# https://github.com/BookingSync/synced/issues/29
|
18
|
-
|
23
|
+
@timestamp_strategy.update(Time.now)
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
22
27
|
|
28
|
+
def reset_synced
|
29
|
+
@timestamp_strategy.reset
|
30
|
+
end
|
31
|
+
|
23
32
|
private
|
24
33
|
|
25
34
|
def api_request_options
|
@@ -37,7 +46,7 @@ module Synced
|
|
37
46
|
|
38
47
|
def updated_since
|
39
48
|
instrument("updated_since.synced") do
|
40
|
-
[
|
49
|
+
[@timestamp_strategy.last_synced_at, initial_sync_since].compact.max
|
41
50
|
end
|
42
51
|
end
|
43
52
|
|
data/lib/synced/synchronizer.rb
CHANGED
@@ -22,8 +22,6 @@ module Synced
|
|
22
22
|
# will be synchronized. By default it's model_class.
|
23
23
|
# @option options [Symbol] id_key: attribute name under which
|
24
24
|
# remote object's ID is stored, default is :synced_id.
|
25
|
-
# @option options [Symbol] synced_all_at_key: attribute name under which
|
26
|
-
# remote object's sync time is stored, default is :synced_all_at
|
27
25
|
# @option options [Symbol] data_key: attribute name under which remote
|
28
26
|
# object's data is stored.
|
29
27
|
# @option options [Array] local_attributes: Array of attributes in the remote
|
@@ -46,29 +44,31 @@ module Synced
|
|
46
44
|
# @option options [Array|Hash] globalized_attributes: A list of attributes
|
47
45
|
# which will be mapped with their translations.
|
48
46
|
# @option options [Symbol] strategy: Strategy to be used for synchronization
|
49
|
-
# process, possible values are :full, :updated_since, :check
|
50
|
-
|
51
|
-
def initialize(model_class, options = {})
|
47
|
+
# process, possible values are :full, :updated_since, :check.
|
48
|
+
def initialize(model_class, strategy:, **options)
|
52
49
|
@model_class = model_class
|
53
|
-
@synced_all_at_key = options[:synced_all_at_key]
|
54
50
|
@only_updated = options[:only_updated]
|
55
|
-
@
|
56
|
-
@strategy = strategy_class(
|
51
|
+
@remote = options[:remote]
|
52
|
+
@strategy = strategy_class(strategy).new(model_class, options)
|
57
53
|
end
|
58
54
|
|
59
55
|
def perform
|
60
56
|
@strategy.perform
|
61
57
|
end
|
62
58
|
|
59
|
+
def reset_synced
|
60
|
+
@strategy.reset_synced
|
61
|
+
end
|
62
|
+
|
63
63
|
private
|
64
64
|
|
65
65
|
def strategy_class(name)
|
66
|
-
name
|
66
|
+
name = :full if force_full_strategy?
|
67
67
|
"Synced::Strategies::#{name.to_s.classify}".constantize
|
68
68
|
end
|
69
69
|
|
70
|
-
def
|
71
|
-
@
|
70
|
+
def force_full_strategy?
|
71
|
+
@remote
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Synced::Timestamp < ActiveRecord::Base
|
2
|
+
self.table_name = 'synced_timestamps'
|
3
|
+
belongs_to :parent_scope, polymorphic: true
|
4
|
+
scope :with_scope_and_model, ->(parent_scope, model_class) { where(parent_scope: parent_scope, model_class: model_class.to_s) }
|
5
|
+
validates :parent_scope, :model_class, :synced_at, presence: true
|
6
|
+
scope :old, -> { where('synced_at < ?', 1.week.ago) }
|
7
|
+
|
8
|
+
def model_class=(value)
|
9
|
+
write_attribute(:model_class, value.to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.last_synced_at
|
13
|
+
maximum(:synced_at)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.cleanup
|
17
|
+
old.delete_all
|
18
|
+
end
|
19
|
+
end
|
data/lib/synced/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: synced
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastien Grosjean
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-02-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -184,8 +184,11 @@ files:
|
|
184
184
|
- lib/synced/result_presenter.rb
|
185
185
|
- lib/synced/strategies/check.rb
|
186
186
|
- lib/synced/strategies/full.rb
|
187
|
+
- lib/synced/strategies/synced_all_at_timestamp_strategy.rb
|
188
|
+
- lib/synced/strategies/synced_per_scope_timestamp_strategy.rb
|
187
189
|
- lib/synced/strategies/updated_since.rb
|
188
190
|
- lib/synced/synchronizer.rb
|
191
|
+
- lib/synced/timestamp.rb
|
189
192
|
- lib/synced/version.rb
|
190
193
|
homepage: https://github.com/BookingSync/synced
|
191
194
|
licenses:
|
@@ -207,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
210
|
version: '0'
|
208
211
|
requirements: []
|
209
212
|
rubyforge_project:
|
210
|
-
rubygems_version: 2.4.
|
213
|
+
rubygems_version: 2.4.3
|
211
214
|
signing_key:
|
212
215
|
specification_version: 4
|
213
216
|
summary: Keep your BookingSync Application synced with BookingSync.
|