synced 1.0.2 → 1.0.3
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 +51 -0
- data/lib/synced/model.rb +29 -23
- data/lib/synced/synchronizer.rb +42 -26
- data/lib/synced/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e53235ec845a40357c1ae3610807ca571cec8807
|
4
|
+
data.tar.gz: 9e1b1289380aafc9a0a08b8f940a773b4308ade2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30fb365ace28a5d26c29601a42d0f308c6a43fdafb0d872968bd797aea799da796a250a8eca45f02c2e43033f5ff8598a5162cb7361119e59777a372e58dcc34
|
7
|
+
data.tar.gz: 004235ba0a34d878c544665ba580bdf0fd643eac9d84e71421f783aaef5901095359923975608a5588ee7362867470faf615a496e513300a059c0faca57735d0
|
data/README.md
CHANGED
@@ -168,6 +168,39 @@ class Rental < ActiveRecord::Base
|
|
168
168
|
end
|
169
169
|
```
|
170
170
|
|
171
|
+
### Globalized attributes
|
172
|
+
|
173
|
+
Some of the API endpoints return strings in multiple languages.
|
174
|
+
When your app is also multilingual you might want take advantage of it
|
175
|
+
and import translations straight to model translations.
|
176
|
+
|
177
|
+
In order to import translations use `:globalized_attributes` attribute. It
|
178
|
+
assumes that your app is using Globalize 3 or newer and `:headline` is already
|
179
|
+
a translated attribute.
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
class Rental < ActiveRecord::Base
|
183
|
+
synced globalized_attributes: :headline
|
184
|
+
translates :headline
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
Now headline will be saved for all translations provided by the API.
|
189
|
+
If given translation will be removed on the API side, it will set to nil
|
190
|
+
locally.
|
191
|
+
|
192
|
+
If you want to map remote field to a different local attribute,
|
193
|
+
specify mapping as a Hash instead of an Array.
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
class Rental < ActiveRecord::Base
|
197
|
+
synced globalized_attributes: {headline: :description}
|
198
|
+
translates :headline
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
This will map remote `:description` to local `:headline` attribute.
|
203
|
+
|
171
204
|
## Partial updates (using updated since parameter)
|
172
205
|
|
173
206
|
Partial updates mean that first synchronization will copy all of the remote
|
@@ -182,6 +215,24 @@ NOTE: In order it to work, given endpoint needs to support updated_since
|
|
182
215
|
parameter. Check [API documentation](http://docs.api.bookingsync.com/reference/)
|
183
216
|
for given endpoint.
|
184
217
|
|
218
|
+
### Forcing local objects to be re-synced with the API
|
219
|
+
|
220
|
+
When you add a new column or change something in the synced attributes and you
|
221
|
+
are using partial updates, old local objects will not be re-synced with API
|
222
|
+
automatically. You need to reset `synced_all_at` column in order to force
|
223
|
+
re-syncing objects again on the next synchronization. In order to do that use
|
224
|
+
`reset_synced` method.
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
Rental.reset_synced
|
228
|
+
```
|
229
|
+
|
230
|
+
You can use this method on a relation as well.
|
231
|
+
|
232
|
+
```ruby
|
233
|
+
account.rentals.reset_synced
|
234
|
+
```
|
235
|
+
|
185
236
|
## Disabling saving whole synced_data
|
186
237
|
|
187
238
|
If you don't need whole remote object to be stored in local object skip
|
data/lib/synced/model.rb
CHANGED
@@ -16,7 +16,7 @@ module Synced
|
|
16
16
|
# remote objects
|
17
17
|
# @option options [Symbol] data_key: attribute name under which remote
|
18
18
|
# object's data is stored.
|
19
|
-
# @option options [Array] local_attributes: Array of attributes in the remote
|
19
|
+
# @option options [Array|Hash] local_attributes: Array of attributes in the remote
|
20
20
|
# object which will be mapped to local object attributes.
|
21
21
|
# @option options [Boolean|Symbol] remove: If it's true all local objects
|
22
22
|
# within current scope which are not present in the remote array will be
|
@@ -27,27 +27,32 @@ module Synced
|
|
27
27
|
# if it's missing, all will be destroyed with destroy_all.
|
28
28
|
# You can also force method to remove local objects by passing it
|
29
29
|
# to remove: :mark_as_missing.
|
30
|
+
# @option options [Array|Hash] globalized_attributes: A list of attributes
|
31
|
+
# which will be mapped with their translations.
|
30
32
|
def synced(options = {})
|
31
33
|
options.symbolize_keys!
|
32
|
-
options.assert_valid_keys(:associations, :data_key, :fields,
|
33
|
-
:
|
34
|
-
:synced_all_at_key)
|
34
|
+
options.assert_valid_keys(:associations, :data_key, :fields,
|
35
|
+
:globalized_attributes, :id_key, :include, :local_attributes, :mapper,
|
36
|
+
:only_updated, :remove, :synced_all_at_key)
|
35
37
|
class_attribute :synced_id_key, :synced_all_at_key, :synced_data_key,
|
36
38
|
:synced_local_attributes, :synced_associations, :synced_only_updated,
|
37
|
-
:synced_mapper, :synced_remove, :synced_include, :synced_fields
|
38
|
-
|
39
|
-
self.
|
39
|
+
:synced_mapper, :synced_remove, :synced_include, :synced_fields,
|
40
|
+
:synced_globalized_attributes
|
41
|
+
self.synced_id_key = options.fetch(:id_key, :synced_id)
|
42
|
+
self.synced_all_at_key = options.fetch(:synced_all_at_key,
|
40
43
|
synced_column_presence(:synced_all_at))
|
41
|
-
self.synced_data_key
|
44
|
+
self.synced_data_key = options.fetch(:data_key,
|
42
45
|
synced_column_presence(:synced_data))
|
43
|
-
self.synced_local_attributes
|
44
|
-
self.synced_associations
|
45
|
-
self.synced_only_updated
|
46
|
+
self.synced_local_attributes = options.fetch(:local_attributes, [])
|
47
|
+
self.synced_associations = options.fetch(:associations, [])
|
48
|
+
self.synced_only_updated = options.fetch(:only_updated,
|
46
49
|
column_names.include?(synced_all_at_key.to_s))
|
47
|
-
self.synced_mapper
|
48
|
-
self.synced_remove
|
49
|
-
self.synced_include
|
50
|
-
self.synced_fields
|
50
|
+
self.synced_mapper = options.fetch(:mapper, nil)
|
51
|
+
self.synced_remove = options.fetch(:remove, false)
|
52
|
+
self.synced_include = options.fetch(:include, [])
|
53
|
+
self.synced_fields = options.fetch(:fields, [])
|
54
|
+
self.synced_globalized_attributes = options.fetch(:globalized_attributes,
|
55
|
+
[])
|
51
56
|
include Synced::HasSyncedData
|
52
57
|
end
|
53
58
|
|
@@ -88,14 +93,15 @@ module Synced
|
|
88
93
|
options[:include] = Array(synced_include) unless options.has_key?(:include)
|
89
94
|
options[:fields] = Array(synced_fields) unless options.has_key?(:fields)
|
90
95
|
options.merge!({
|
91
|
-
id_key:
|
92
|
-
synced_data_key:
|
93
|
-
synced_all_at_key:
|
94
|
-
data_key:
|
95
|
-
local_attributes:
|
96
|
-
associations:
|
97
|
-
only_updated:
|
98
|
-
mapper:
|
96
|
+
id_key: synced_id_key,
|
97
|
+
synced_data_key: synced_data_key,
|
98
|
+
synced_all_at_key: synced_all_at_key,
|
99
|
+
data_key: synced_data_key,
|
100
|
+
local_attributes: synced_local_attributes,
|
101
|
+
associations: synced_associations,
|
102
|
+
only_updated: synced_only_updated,
|
103
|
+
mapper: synced_mapper,
|
104
|
+
globalized_attributes: synced_globalized_attributes
|
99
105
|
})
|
100
106
|
Synced::Synchronizer.new(self, options).perform
|
101
107
|
end
|
data/lib/synced/synchronizer.rb
CHANGED
@@ -37,24 +37,27 @@ module Synced
|
|
37
37
|
# remote objects
|
38
38
|
# @option options [Module] mapper: Module class which will be used for
|
39
39
|
# mapping remote objects attributes into local object attributes
|
40
|
+
# @option options [Array|Hash] globalized_attributes: A list of attributes
|
41
|
+
# which will be mapped with their translations.
|
40
42
|
def initialize(model_class, options = {})
|
41
|
-
@model_class
|
42
|
-
@scope
|
43
|
-
@id_key
|
44
|
-
@synced_all_at_key
|
45
|
-
@data_key
|
46
|
-
@remove
|
47
|
-
@only_updated
|
48
|
-
@include
|
49
|
-
@local_attributes
|
50
|
-
@api
|
51
|
-
@mapper
|
52
|
-
|
53
|
-
@fields
|
54
|
-
@remove
|
55
|
-
@associations
|
56
|
-
@remote_objects
|
57
|
-
@request_performed
|
43
|
+
@model_class = model_class
|
44
|
+
@scope = options[:scope]
|
45
|
+
@id_key = options[:id_key]
|
46
|
+
@synced_all_at_key = options[:synced_all_at_key]
|
47
|
+
@data_key = options[:data_key]
|
48
|
+
@remove = options[:remove]
|
49
|
+
@only_updated = options[:only_updated]
|
50
|
+
@include = options[:include]
|
51
|
+
@local_attributes = attributes_as_hash(options[:local_attributes])
|
52
|
+
@api = options[:api]
|
53
|
+
@mapper = options[:mapper].respond_to?(:call) ?
|
54
|
+
options[:mapper].call : options[:mapper]
|
55
|
+
@fields = options[:fields]
|
56
|
+
@remove = options[:remove]
|
57
|
+
@associations = Array(options[:associations])
|
58
|
+
@remote_objects = Array(options[:remote]) unless options[:remote].nil?
|
59
|
+
@request_performed = false
|
60
|
+
@globalized_attributes = attributes_as_hash(options[:globalized_attributes])
|
58
61
|
end
|
59
62
|
|
60
63
|
def perform
|
@@ -69,6 +72,10 @@ module Synced
|
|
69
72
|
local_object = local_object_by_remote_id(remote.id) || relation_scope.new
|
70
73
|
local_object.attributes = default_attributes_mapping(remote)
|
71
74
|
local_object.attributes = local_attributes_mapping(remote)
|
75
|
+
if @globalized_attributes.present?
|
76
|
+
local_object.attributes = globalized_attributes_mapping(remote,
|
77
|
+
local_object.translations.translated_locales)
|
78
|
+
end
|
72
79
|
local_object.save! if local_object.changed?
|
73
80
|
local_object.tap do |local_object|
|
74
81
|
@associations.each do |association|
|
@@ -92,15 +99,9 @@ module Synced
|
|
92
99
|
private
|
93
100
|
|
94
101
|
def local_attributes_mapping(remote)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
[k, v.respond_to?(:call) ? v.call(remote) : remote.send(v)]
|
99
|
-
end
|
100
|
-
]
|
101
|
-
else
|
102
|
-
Hash[Array(@local_attributes).map { |k| [k, remote.send(k)] }]
|
103
|
-
end
|
102
|
+
Hash[@local_attributes.map do |k, v|
|
103
|
+
[k, v.respond_to?(:call) ? v.call(remote) : remote.send(v)]
|
104
|
+
end]
|
104
105
|
end
|
105
106
|
|
106
107
|
def default_attributes_mapping(remote)
|
@@ -110,6 +111,16 @@ module Synced
|
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
114
|
+
def globalized_attributes_mapping(remote, used_locales)
|
115
|
+
empty = Hash[used_locales.map { |locale| [locale.to_s, nil] }]
|
116
|
+
{}.tap do |attributes|
|
117
|
+
@globalized_attributes.each do |local_attr, remote_attr|
|
118
|
+
translations = empty.merge(remote.send(remote_attr) || {})
|
119
|
+
attributes["#{local_attr}_translations"] = translations
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
113
124
|
# Returns relation within which local objects are created/edited and removed
|
114
125
|
# If no scope is provided, the relation_scope will be class on which
|
115
126
|
# .synchronize method is called.
|
@@ -213,6 +224,11 @@ module Synced
|
|
213
224
|
Synced.instrumenter.instrument(*args, &block)
|
214
225
|
end
|
215
226
|
|
227
|
+
def attributes_as_hash(attributes)
|
228
|
+
return attributes if attributes.is_a?(Hash)
|
229
|
+
Hash[Array(attributes).map { |name| [name, name] }]
|
230
|
+
end
|
231
|
+
|
216
232
|
class MissingAPIClient < StandardError
|
217
233
|
def initialize(scope, model_class)
|
218
234
|
@scope = scope
|
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.0.
|
4
|
+
version: 1.0.3
|
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: 2014-
|
12
|
+
date: 2014-09-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -137,6 +137,20 @@ dependencies:
|
|
137
137
|
- - '>='
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: globalize
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ~>
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 4.0.2
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ~>
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 4.0.2
|
140
154
|
description: Keep your BookingSync Application synced with BookingSync.
|
141
155
|
email:
|
142
156
|
- dev@bookingsync.com
|