synced 1.1.3 → 1.2.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.
- 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.
|