table_sync 6.8.0 → 6.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5a835e891243ac8adecc1e4fd83c9689ec4f2082eb17667beaf103a863d78ec
4
- data.tar.gz: 590bdc2445a3624f5c650518abc53b33fc6d478cbf0994a91a221184d2feeb51
3
+ metadata.gz: 238a612ebdd5b85291cb3ba0c6675125a19880c83ce9deeea32454a2691a3127
4
+ data.tar.gz: 5cb1b9c0c7ce04af3ac19e12935c9f385a820d5c037a7d9f112ac27fbf334951
5
5
  SHA512:
6
- metadata.gz: 844982d049022ca0e885392d65cd1ebeaf58d994a0f8de239ed4acb4d48a7faad83e85516c0abc840a80ed0c6ccb049430ed49af699e8b313894c66d8ab383f9
7
- data.tar.gz: 464b8edcdcc22869e4797a4a3236bae8287915815a05eb51243afc00a0fdd99964cb6a45ff53cdcee927f930647031cae28c2089b60407e2dd497b38dd788cdd
6
+ metadata.gz: 02746efdbdc881da38b0a7db32495ee4e97cb79edaa019d84d56396f366fc985f387e14207465a7ab02e4bde1d28249488c96857cead2fba78160109c7d74949
7
+ data.tar.gz: 40a67f153d5ad41df0c54935c756e93f819b2c63a1d688e867bd01797fe3da32f0990cf35f759cb9b27b1c8148b9b791f2ba114111878b0cc36957de025b6aeb
data/CHANGELOG.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [6.9.3] - 2025-10-09
5
+ ### Fixed
6
+ - Add validate_types to model interface
7
+
8
+ ## [6.9.2] - 2025-10-03
9
+ ### Fixed
10
+ - Fix of all types taking type cast into account
11
+
12
+ ## [6.9.1] - 2025-10-02
13
+ ### Fixed
14
+ - DateTime can be String now
15
+
16
+ ## [6.9.0] - 2025-10-02
17
+ ### Added
18
+ - Add check of data scalar types in order to provide readable error text
19
+
4
20
  ## [6.8.0] - 2025-08-25
5
21
  ### Changed
6
22
  - Updated `rabbit_messaging` gem version to `1.7.0`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- table_sync (6.8.0)
4
+ table_sync (6.9.3)
5
5
  memery
6
6
  rabbit_messaging (>= 1.7.0)
7
7
  rails
@@ -131,12 +131,20 @@ class TableSync::Receiving::Handler < Rabbit::EventHandler
131
131
  end
132
132
  end
133
133
 
134
+ def validate_data_types(model, data)
135
+ errors = model.validate_types(data)
136
+ return if errors.nil?
137
+
138
+ raise TableSync::DataError.new(data, errors.keys, errors.to_json)
139
+ end
140
+
134
141
  def perform(config, params)
135
142
  model = config.model
136
143
 
137
144
  model.transaction do
138
145
  results = if event == :update
139
146
  config.before_update(**params)
147
+ validate_data_types(model, params[:data])
140
148
  model.upsert(**params)
141
149
  else
142
150
  config.before_destroy(**params)
@@ -25,6 +25,7 @@ module TableSync::Receiving::Model
25
25
  self.table_name = table_name
26
26
  self.inheritance_column = nil
27
27
  end
28
+ @types_validator = TableSync::Utils::Schema::Builder::ActiveRecord.build(@raw_model)
28
29
 
29
30
  model_naming = ::TableSync::NamingResolver::ActiveRecord.new(table_name:)
30
31
 
@@ -105,6 +106,10 @@ module TableSync::Receiving::Model
105
106
  result
106
107
  end
107
108
 
109
+ def validate_types(data)
110
+ types_validator.validate(data)
111
+ end
112
+
108
113
  def transaction(&)
109
114
  ::ActiveRecord::Base.transaction(&)
110
115
  end
@@ -115,7 +120,7 @@ module TableSync::Receiving::Model
115
120
 
116
121
  private
117
122
 
118
- attr_reader :raw_model
123
+ attr_reader :raw_model, :types_validator
119
124
 
120
125
  def db
121
126
  raw_model.connection
@@ -6,6 +6,7 @@ module TableSync::Receiving::Model
6
6
 
7
7
  def initialize(table_name)
8
8
  @raw_model = Class.new(::Sequel::Model(table_name)).tap(&:unrestrict_primary_key)
9
+ @types_validator = TableSync::Utils::Schema::Builder::Sequel.build(@raw_model)
9
10
 
10
11
  model_naming = ::TableSync::NamingResolver::Sequel.new(
11
12
  table_name:,
@@ -52,6 +53,10 @@ module TableSync::Receiving::Model
52
53
  result
53
54
  end
54
55
 
56
+ def validate_types(data)
57
+ types_validator.validate(data)
58
+ end
59
+
55
60
  def transaction(&)
56
61
  db.transaction(&)
57
62
  end
@@ -62,7 +67,7 @@ module TableSync::Receiving::Model
62
67
 
63
68
  private
64
69
 
65
- attr_reader :raw_model
70
+ attr_reader :raw_model, :types_validator
66
71
 
67
72
  def dataset
68
73
  raw_model.dataset
@@ -101,3 +101,8 @@ __END__
101
101
  :schema:
102
102
  :parameters: []
103
103
  :description: "returns an instance of Symbol"
104
+ :validate_types:
105
+ :parameters:
106
+ - - :req
107
+ - :data
108
+ :description: "validate types of receiving data to make more readable errors"
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TableSync::Utils::Schema
4
+ module Builder
5
+ class ActiveRecord
6
+ class << self
7
+ Type = TableSync::Utils::Schema::Validator::Type
8
+
9
+ def build(model)
10
+ TableSync::Utils::Schema.new(schema(model))
11
+ end
12
+
13
+ private
14
+
15
+ def schema(model)
16
+ model.attribute_types.to_h do |key, value|
17
+ next [nil, nil] unless (type = type(value))
18
+ [key.to_sym, TableSync::Utils::Schema::Validator.new(type)]
19
+ end.tap(&:compact!)
20
+ end
21
+
22
+ def type(value)
23
+ case value
24
+ when ActiveModel::Type::String,
25
+ ActiveModel::Type::ImmutableString
26
+ Type::STRING
27
+ when ActiveModel::Type::DateTime,
28
+ ActiveModel::Type::Date,
29
+ ActiveModel::Type::Time
30
+ Type::DATETIME
31
+ when ActiveModel::Type::Integer,
32
+ ActiveModel::Type::Decimal,
33
+ ActiveModel::Type::Float,
34
+ ActiveModel::Type::BigInteger
35
+ Type::DECIMAL
36
+ when ActiveModel::Type::Boolean
37
+ Type::BOOLEAN
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TableSync::Utils::Schema
4
+ module Builder
5
+ class Sequel
6
+ class << self
7
+ Type = TableSync::Utils::Schema::Validator::Type
8
+
9
+ def build(model)
10
+ TableSync::Utils::Schema.new(schema(model))
11
+ end
12
+
13
+ private
14
+
15
+ def schema(model)
16
+ model.db_schema.transform_values do |value|
17
+ next unless (type = type(value))
18
+ TableSync::Utils::Schema::Validator.new(type)
19
+ end.tap(&:compact!)
20
+ end
21
+
22
+ def type(value)
23
+ case value[:type]
24
+ when :string
25
+ Type::STRING
26
+ when :datetime, :date, :time
27
+ Type::DATETIME
28
+ when :integer, :decimal, :float
29
+ Type::DECIMAL
30
+ when :boolean
31
+ Type::BOOLEAN
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "validator"
4
+ require_relative "builder/sequel"
5
+ require_relative "builder/active_record"
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TableSync::Utils::Schema
4
+ class Validator
5
+ class Type
6
+ class Decimal < Type
7
+ def valid?(value)
8
+ !Float(value, exception: false).nil?
9
+ end
10
+ end
11
+
12
+ class DateTime < Type
13
+ def valid?(value)
14
+ Date._parse(value.to_s).any?
15
+ end
16
+ end
17
+
18
+ class Boolean < Type
19
+ def valid?(value)
20
+ %w[true false t f 0 1 on off].include?(value.to_s.downcase)
21
+ end
22
+ end
23
+
24
+ class Text < Type
25
+ def valid?(value)
26
+ return true if value.is_a?(::String)
27
+ return true if value.is_a?(::Symbol)
28
+ return true if Type::DECIMAL.valid?(value)
29
+ return true if Type::BOOLEAN.valid?(value)
30
+ return true if Type::DATETIME.valid?(value)
31
+ false
32
+ end
33
+ end
34
+
35
+ attr_reader :display_name
36
+
37
+ def initialize(display_name)
38
+ @display_name = display_name
39
+ end
40
+
41
+ # @!method valid?
42
+
43
+ # rubocop:disable Layout/ClassStructure
44
+ DECIMAL = Decimal.new("Decimal")
45
+ DATETIME = DateTime.new("DateTime")
46
+ BOOLEAN = Boolean.new("Boolean")
47
+ STRING = Text.new("String")
48
+ # rubocop:enable Layout/ClassStructure
49
+
50
+ def validate(value)
51
+ return if value.nil?
52
+ return if valid?(value)
53
+ "expected #{display_name}, got: #{value.class}"
54
+ end
55
+
56
+ def inspect
57
+ display_name.inspect
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "validator/type"
4
+
5
+ class TableSync::Utils::Schema
6
+ class Validator
7
+ attr_reader :type
8
+
9
+ def initialize(type)
10
+ @type = type
11
+ end
12
+
13
+ def validate(value)
14
+ type.validate(value)
15
+ end
16
+
17
+ def inspect
18
+ type.inspect
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Next code checks that hash values have required data types
4
+
5
+ require_relative "schema/builder"
6
+
7
+ class TableSync::Utils::Schema
8
+ attr_reader :schema
9
+
10
+ def initialize(schema)
11
+ @schema = schema
12
+ end
13
+
14
+ def validate(data)
15
+ errors = nil
16
+ data.each do |row|
17
+ schema.each do |key, value|
18
+ if (error = value.validate(row[key]))
19
+ errors ||= {}
20
+ errors[key] = error
21
+ end
22
+ end
23
+
24
+ return errors.freeze unless errors.nil?
25
+ end
26
+ errors
27
+ end
28
+ end
@@ -6,5 +6,6 @@ module TableSync
6
6
  require_relative "utils/proc_keywords_resolver"
7
7
  require_relative "utils/interface_checker"
8
8
  require_relative "utils/required_validator"
9
+ require_relative "utils/schema"
9
10
  end
10
11
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TableSync
4
- VERSION = "6.8.0"
4
+ VERSION = "6.9.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: table_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.8.0
4
+ version: 6.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umbrellio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-10 00:00:00.000000000 Z
11
+ date: 2025-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: memery
@@ -128,6 +128,12 @@ files:
128
128
  - lib/table_sync/utils/proc_array.rb
129
129
  - lib/table_sync/utils/proc_keywords_resolver.rb
130
130
  - lib/table_sync/utils/required_validator.rb
131
+ - lib/table_sync/utils/schema.rb
132
+ - lib/table_sync/utils/schema/builder.rb
133
+ - lib/table_sync/utils/schema/builder/active_record.rb
134
+ - lib/table_sync/utils/schema/builder/sequel.rb
135
+ - lib/table_sync/utils/schema/validator.rb
136
+ - lib/table_sync/utils/schema/validator/type.rb
131
137
  - lib/table_sync/version.rb
132
138
  - log/.keep
133
139
  - table_sync.gemspec
@@ -150,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
156
  - !ruby/object:Gem::Version
151
157
  version: '0'
152
158
  requirements: []
153
- rubygems_version: 3.5.3
159
+ rubygems_version: 3.3.27
154
160
  signing_key:
155
161
  specification_version: 4
156
162
  summary: DB Table synchronization between microservices based on Model's event system