watermelon_db_sync 0.1.0 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b9015f5a02d5c6b6e26d8a0052fb9f051ea6c8117809d31eb3b47c3e71a2534
4
- data.tar.gz: 9dfd41be7553e2ab5ba5e6446b7cfabcd7b3d0d20a191fbd0c8f8737dd50dcce
3
+ metadata.gz: 74af5a7823495e5bd4461fff2bdb28c18070dc590268988a8bdafef6b28dd639
4
+ data.tar.gz: 952be479c9fd26479dca94009db6861581b947e08e19adee1233b69902cc2e7d
5
5
  SHA512:
6
- metadata.gz: 3834629e0e18f18fd6013c4f00758187638eaf2e83e3611b9ab5a8e025143d4ca85cfafb527708a6f3f5a4aca9b9b4b3d7a507d21d0db4633f9b5aa4676d7775
7
- data.tar.gz: 07621474f58f843f13bb37d12b7ae05a63defd525f70ebca2aada8839fb1e36e691f35aba7320eec70e40227ca58fed200e3d9581ac727d0dbbd2788610d584a
6
+ metadata.gz: de9cb3d1f3ba06edf15d8049ec0af10a270f00f587d65ccdf3df41835eb87c083030fcb5f10393500d0e5ac5ea98da5fcdb2b045e0b3635af290ed4776c6ab23
7
+ data.tar.gz: 5f5b4bf1b9bf2eb979f20ab67a4f6c2a5759bb762075b72312bca358c0637c999a6acc19a39bb7b19bb0630fd755ab7b53a65e7b26da26dde3a2ad66123802ea
@@ -1,69 +1,88 @@
1
1
  module WatermelonDbSync
2
2
  class SyncPull < Sync
3
-
4
3
  attr_accessor :last_pulled_version, :models, :data
5
4
 
6
5
  def initialize(params)
7
- @last_pulled_version = params[:last_pulled_version] || 0
6
+ @last_pulled_version = params[:last_pulled_version].to_i || 0
8
7
  @push_id = params[:push_id]
9
- @format_response = {created: [], updated: [], deleted: [] }
10
8
  @models = WatermelonDbSync.configuration.sync_models
11
- @data = {last_global_seqs: 0, response: build_default_response}
9
+ @data = { last_global_seqs: 0, response: build_default_response }
12
10
  end
13
11
 
14
12
  def pull
15
- self.get_from_all
13
+ get_from_all
16
14
  end
17
15
 
18
16
  def get_from_all
19
- begin
20
- max_list = []
21
- @models.each do |model|
22
- max_list << self.query(eval(model))
23
- end
24
-
25
- @data[:last_global_seqs] = max_list.flatten.max || @last_pulled_version.to_i #Sync.last_global_seqs
26
- return true
27
- rescue => e
28
- e.message
17
+ max_versions = @models.map do |model_name|
18
+ model = model_name.constantize
19
+ query(model)
29
20
  end
30
- end
31
21
 
32
- # Filtered by push_id, for differentiate record just pushed
33
- def query(model=nil)
22
+ @data[:last_global_seqs] =
23
+ max_versions.flatten.compact.max || @last_pulled_version
34
24
 
35
- all_with_deleted = model.with_deleted.where("version_created > #{@last_pulled_version} OR version > #{@last_pulled_version}")
36
- max_list = all_with_deleted.pluck(:version, :version_created)
25
+ true
26
+ rescue => e
27
+ e.message
28
+ end
37
29
 
38
- all_with_deleted = all_with_deleted.where("push_id != ? or push_id is ?", @push_id, nil) if @push_id.present?
30
+ private
39
31
 
40
- created = all_with_deleted.where(deleted_at_server: nil).where("version_created > #{@last_pulled_version}")
32
+ def base_scope(model)
33
+ model.respond_to?(:with_deleted) ? model.with_deleted : model.all
34
+ end
41
35
 
42
- updated = all_with_deleted.where(deleted_at_server: nil).where("created_at_server != updated_at_server")
43
- new_updated = []
44
- updated.each do |obj_updated|
45
- new_updated << obj_updated unless created.map{|d|d.as_json}.include?(obj_updated.as_json)
36
+ def deleted_scope(model)
37
+ if model.respond_to?(:only_deleted)
38
+ model.only_deleted
39
+ else
40
+ model.where.not(deleted_at_server: nil)
46
41
  end
47
-
48
- deleted = all_with_deleted.only_deleted
49
- deleted = deleted.pluck(:id)
50
-
51
- @data[:response][model.table_name.to_sym][:created] = created&.as_json
52
- @data[:response][model.table_name.to_sym][:updated] = new_updated&.as_json
53
- @data[:response][model.table_name.to_sym][:deleted] = deleted&.as_json
54
-
55
- max_list
42
+ end
43
+
44
+ def query(model)
45
+ scope = base_scope(model)
46
+ .where("version_created > ? OR version > ?",
47
+ @last_pulled_version, @last_pulled_version)
48
+
49
+ scope = scope.where("push_id != ? OR push_id IS NULL", @push_id) if @push_id.present?
50
+
51
+ created = scope
52
+ .where(deleted_at_server: nil)
53
+ .where("version_created > ?", @last_pulled_version)
54
+
55
+ updated = scope
56
+ .where(deleted_at_server: nil)
57
+ .where("version > ? AND version_created <= ?",
58
+ @last_pulled_version, @last_pulled_version)
59
+
60
+ deleted = deleted_scope(model)
61
+ .where("version > ?", @last_pulled_version)
62
+ .pluck(:id)
63
+
64
+ table = model.table_name.to_sym
65
+
66
+ @data[:response][table][:created] = created.as_json
67
+ @data[:response][table][:updated] = updated.as_json
68
+ @data[:response][table][:deleted] = deleted
69
+
70
+ scope.pluck(:version, :version_created)
56
71
  end
57
72
 
58
73
  def build_default_response
59
- default = Hash.new { |hash, key| hash[key] = {} }
60
- @models.each do |model|
61
- default[eval(model).table_name.to_sym][:created] = {}
62
- default[eval(model).table_name.to_sym][:deleted] = {}
63
- default[eval(model).table_name.to_sym][:updated] = {}
74
+ default = {}
75
+
76
+ @models.each do |model_name|
77
+ table = model_name.constantize.table_name.to_sym
78
+ default[table] = {
79
+ created: [],
80
+ updated: [],
81
+ deleted: []
82
+ }
64
83
  end
84
+
65
85
  default
66
86
  end
67
-
68
87
  end
69
88
  end
@@ -1,110 +1,112 @@
1
1
  module WatermelonDbSync
2
2
  class SyncPush < Sync
3
-
4
3
  attr_accessor :models, :data, :params
5
4
 
6
5
  def initialize(params)
7
6
  @models = WatermelonDbSync.configuration.sync_models
8
7
  @params = params
9
- @data = {last_global_seqs:0}
8
+ @data = { last_global_seqs: 0 }
10
9
  @push_id = rand(1..1_000_000_000)
11
10
  end
12
11
 
13
12
  def push
14
- begin
15
- if has_conflict_version?
16
- @data[:error_code] = "WDBS2"
17
- raise StandardError.new("the data has a conflict version, please pull first")
18
- else
19
- ActiveRecord::Base.transaction do
20
- @models.each do |model|
21
- self.submit_records!(model) if @params.keys.include? eval(model).table_name
22
- end
23
- @data[:success] = true
24
- sync_pull = SyncPull.new(last_pulled_version: @params["last_pulled_version"], push_id: @push_id)
25
- sync_pull.pull
26
- @data[:response] = sync_pull.data[:response]
27
- @data[:last_global_seqs] = sync_pull.data[:last_global_seqs]
28
- end
29
- end
30
- rescue StandardError => e
13
+ if has_conflict_version?
31
14
  @data[:success] = false
32
- @data[:message] = e.message
15
+ @data[:error_code] = "WDBS2"
16
+ @data[:message] = "Conflict version detected. Please pull first."
17
+ return
33
18
  end
34
- end
35
19
 
20
+ ActiveRecord::Base.transaction do
21
+ @models.each do |model_name|
22
+ model = model_name.constantize
23
+ next unless @params.key?(model.table_name)
36
24
 
37
- def submit_records!(model)
38
- table = @params[model.tableize]
39
- table["created"]&.each do |data|
40
- data = except_data(data)
41
- data["push_id"] = @push_id
42
-
43
- find_or_new = eval(model).find(data["id"]) rescue nil
44
- if find_or_new.blank?
45
- find_or_new = eval(model).new(data)
46
- find_or_new.id = data["id"]
47
- find_or_new.created_at = data["created_at"]
48
- find_or_new.updated_at = data["updated_at"]
49
- find_or_new.save!
50
- else
51
- find_or_new.update!(data)
25
+ submit_records!(model)
52
26
  end
27
+
28
+ sync_pull = SyncPull.new(
29
+ last_pulled_version: @params["last_pulled_version"],
30
+ push_id: @push_id
31
+ )
32
+
33
+ sync_pull.pull
34
+
35
+ @data[:success] = true
36
+ @data[:response] = sync_pull.data[:response]
37
+ @data[:last_global_seqs] = sync_pull.data[:last_global_seqs]
53
38
  end
39
+ rescue => e
40
+ @data[:success] = false
41
+ @data[:message] = e.message
42
+ end
54
43
 
55
- table["updated"]&.each do |data|
56
- data = except_data(data)
57
- data["push_id"] = @push_id
44
+ private
58
45
 
59
- find_record = eval(model).find(data["id"]) rescue nil
46
+ def base_scope(model)
47
+ model.respond_to?(:with_deleted) ? model.with_deleted : model.all
48
+ end
60
49
 
61
- if find_record.nil? && eval(model).only_deleted.find(data["id"])
62
- @data[:error_code] = "WDBS1"
63
- raise StandardError.new("id=#{data["id"]} of the #{model} was deleted, please pull first")
64
- end
65
- find_record.update!(data.except("id"))
50
+ def submit_records!(model)
51
+ table = @params[model.table_name]
52
+
53
+ table["created"]&.each do |record|
54
+ record = sanitize(record)
55
+ record["push_id"] = @push_id
56
+
57
+ obj = model.find_by(id: record["id"]) || model.new
58
+ obj.assign_attributes(record)
59
+ obj.save!
66
60
  end
67
61
 
68
- table["deleted"]&.each do |data|
69
- find_record = eval(model).find(data) rescue nil
62
+ table["updated"]&.each do |record|
63
+ record = sanitize(record)
64
+ record["push_id"] = @push_id
70
65
 
71
- if find_record.present?
72
- find_record.update_column(:push_id, @push_id)
73
- find_record.destroy
74
- end
66
+ obj = model.find(record["id"])
67
+ obj.update!(record.except("id"))
68
+ end
69
+
70
+ table["deleted"]&.each do |id|
71
+ obj = model.find_by(id: id)
72
+ next unless obj
73
+
74
+ obj.update_column(:push_id, @push_id)
75
+ obj.destroy
75
76
  end
76
-
77
77
  end
78
78
 
79
- def except_data(data)
80
- data.except("version", "version_created", "created_at_server", "updated_at_server", "deleted_at_server", "push_id", "_status", "_changed")
79
+ def sanitize(data)
80
+ data.except(
81
+ "version",
82
+ "version_created",
83
+ "created_at_server",
84
+ "updated_at_server",
85
+ "deleted_at_server",
86
+ "push_id",
87
+ "_status",
88
+ "_changed"
89
+ )
81
90
  end
82
91
 
83
92
  def has_conflict_version?
84
- conflict = false
85
- @models.each do |model|
86
-
87
- #keep original object @params
88
- params = Marshal.load(Marshal.dump(@params))
89
- table = params[model.tableize]
90
- if (params.keys.include? eval(model).table_name)
91
- collect_ids = table["created"]
92
-
93
- if table["updated"].present?
94
- updated = table["updated"]
95
- collect_ids.concat(updated)
96
- end
97
-
98
- collect_ids = collect_ids&.map{|d|d["id"]}
99
- collect_ids.concat(table["deleted"]) if table["deleted"].present?
100
- conflict = eval(model).with_deleted
101
- .where(id: collect_ids)
102
- .where("version_created > #{@params["last_pulled_version"]} OR version > #{@params["last_pulled_version"]}").exists?
103
- end
104
- break if conflict
105
- end
106
- return conflict
93
+ @models.any? do |model_name|
94
+ model = model_name.constantize
95
+ table = @params[model.table_name]
96
+ next false unless table
97
+
98
+ ids = []
99
+ ids += table["created"]&.map { |d| d["id"] } || []
100
+ ids += table["updated"]&.map { |d| d["id"] } || []
101
+ ids += table["deleted"] || []
102
+
103
+ base_scope(model)
104
+ .where(id: ids)
105
+ .where("version_created > ? OR version > ?",
106
+ @params["last_pulled_version"].to_i,
107
+ @params["last_pulled_version"].to_i)
108
+ .exists?
109
+ end
107
110
  end
108
-
109
111
  end
110
112
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WatermelonDbSync
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
Binary file
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: watermelon_db_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasfi
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-09-11 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rspec
@@ -104,13 +103,13 @@ files:
104
103
  - lib/watermelon_db_sync/sync_push.rb
105
104
  - lib/watermelon_db_sync/version.rb
106
105
  - sig/watermelon_db_sync.rbs
106
+ - watermelon_db_sync-0.1.0.gem
107
107
  homepage: https://github.com/aapiw/watermelon_db_sync
108
108
  licenses: []
109
109
  metadata:
110
110
  homepage_uri: https://github.com/aapiw/watermelon_db_sync
111
111
  source_code_uri: https://github.com/aapiw/watermelon_db_sync
112
112
  changelog_uri: https://github.com/aapiw/watermelon_db_sync
113
- post_install_message:
114
113
  rdoc_options: []
115
114
  require_paths:
116
115
  - lib
@@ -125,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
124
  - !ruby/object:Gem::Version
126
125
  version: '0'
127
126
  requirements: []
128
- rubygems_version: 3.3.7
129
- signing_key:
127
+ rubygems_version: 4.0.7
130
128
  specification_version: 4
131
129
  summary: Make synchronize pull & push easier & faster.
132
130
  test_files: []