Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog
All notable changes to this project will be documented in this file.

## [6.9.2] - 2025-10-03
### Fixed
- Fix of all types taking type cast into account

## [6.9.1] - 2025-10-02
### Fixed
- DateTime can be String now
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
table_sync (6.9.1)
table_sync (6.9.2)
memery
rabbit_messaging (>= 1.7.0)
rails
Expand Down
5 changes: 2 additions & 3 deletions lib/table_sync/utils/schema/builder/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ def type(value)
ActiveModel::Type::Date,
ActiveModel::Type::Time
Type::DATETIME
when ActiveModel::Type::Integer
Type::INTEGER
when ActiveModel::Type::Decimal,
when ActiveModel::Type::Integer,
ActiveModel::Type::Decimal,
ActiveModel::Type::Float,
ActiveModel::Type::BigInteger
Type::DECIMAL
Expand Down
4 changes: 1 addition & 3 deletions lib/table_sync/utils/schema/builder/sequel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ def type(value)
Type::STRING
when :datetime, :date, :time
Type::DATETIME
when :integer
Type::INTEGER
when :decimal, :float
when :integer, :decimal, :float
Type::DECIMAL
when :boolean
Type::BOOLEAN
Expand Down
46 changes: 37 additions & 9 deletions lib/table_sync/utils/schema/validator/type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,53 @@
class TableSync::Utils::Schema
class Validator
class Type
class Decimal < Type
def valid?(value)
!Float(value, exception: false).nil?
end
end

class DateTime < Type
def valid?(value)
Date._parse(value.to_s).any?
end
end

class Boolean < Type
def valid?(value)
%w[true false t f 0 1 on off].include?(value.to_s.downcase)
end
end

class Text < Type
def valid?(value)
return true if value.is_a?(::String)
return true if value.is_a?(::Symbol)
return true if Type::DECIMAL.valid?(value)
return true if Type::BOOLEAN.valid?(value)
return true if Type::DATETIME.valid?(value)
false
end
end

attr_reader :display_name
attr_reader :klasses

def initialize(display_name, klasses)
def initialize(display_name)
@display_name = display_name
@klasses = klasses
end

# @!method valid?

# rubocop:disable Layout/ClassStructure
STRING = new("String", [String]).freeze
DATETIME = new("DateTime", [String, ::Sequel::SQLTime, Date, Time, DateTime]).freeze
INTEGER = new("Integer", [Integer]).freeze
DECIMAL = new("Decimal", [Numeric]).freeze
BOOLEAN = new("Boolean", [TrueClass, FalseClass]).freeze
DECIMAL = Decimal.new("Decimal")
DATETIME = DateTime.new("DateTime")
BOOLEAN = Boolean.new("Boolean")
STRING = Text.new("String")
# rubocop:enable Layout/ClassStructure

def validate(value)
return if value.nil?
return if klasses.any? { |klass| value.is_a?(klass) }
return if valid?(value)
"expected #{display_name}, got: #{value.class}"
end

Expand Down
2 changes: 1 addition & 1 deletion lib/table_sync/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module TableSync
VERSION = "6.9.1"
VERSION = "6.9.2"
end
97 changes: 78 additions & 19 deletions spec/receiving/models_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -592,29 +592,88 @@
end

describe "#validate_types" do
let(:data) do
[
id: 1,
string: nil,
datetime: "string",
integer: 10.5,
decimal: "string",
array: "string",
boolean: "string",
version: 123.456,
shared_examples "returns success" do |field, value|
context "with #{value}" do
specify do
result = types_test.validate_types([id: 1, field => value])
expect(result).to be_nil
end
end
end

shared_examples "returns error" do |field, value, got|
context "with #{value}" do
specify do
result = types_test.validate_types([id: 1, field => value])
expect(result[field]).to include("got: #{got}")
end
end
end

context "Decimal" do
values = ["1.5", 1.5, 1, "-1.567", BigDecimal("1.5"), Time.current]
values.each do |value|
it_behaves_like "returns success", :decimal, value
end

it_behaves_like "returns error", :decimal, {}, "Hash"
it_behaves_like "returns error", :decimal, [], "Array"
it_behaves_like "returns error", :decimal, "test", "String"
it_behaves_like "returns error", :decimal, true, "TrueClass"
end

context "DateTime" do
values = [
"01.01.2010",
Time.current, Date.current, DateTime.current,
Sequel::SQLTime.date,
123, 123.5, BigDecimal("123.5")
]
values.each do |value|
it_behaves_like "returns success", :datetime, value
end

it_behaves_like "returns error", :datetime, {}, "Hash"
it_behaves_like "returns error", :datetime, [], "Array"
it_behaves_like "returns error", :datetime, "test", "String"
it_behaves_like "returns error", :datetime, true, "TrueClass"
it_behaves_like "returns error", :datetime, 0, "Integer"
it_behaves_like "returns error", :datetime, 0.1, "Float"
end
let(:error) do
{
integer: "expected Integer, got: Float",
decimal: "expected Decimal, got: String",
boolean: "expected Boolean, got: String",
}

context "Boolean" do
values = [
true, false,
0, 1,
"true", "false", "TRUE", "False", "tRuE", "t", "f", "on", "off", "0", "1"
]
values.each do |value|
it_behaves_like "returns success", :boolean, value
end

it_behaves_like "returns error", :boolean, {}, "Hash"
it_behaves_like "returns error", :boolean, [], "Array"
it_behaves_like "returns error", :boolean, "test", "String"
it_behaves_like "returns error", :boolean, 10, "Integer"
it_behaves_like "returns error", :boolean, -1, "Integer"
it_behaves_like "returns error", :boolean, 1.5, "Float"
it_behaves_like "returns error", :boolean, Time.current, "Time"
end

it "raises TableSync::DataError" do
result = types_test.validate_types(data)
expect(result).to eq(error)
context "String" do
values = [
true, false,
"asfdnk", "1.5", "-1", "t", "f", :test,
BigDecimal(45435), 1, 1.5, -1, 0,
Time.current, Sequel::SQLTime.date
]
values.each do |value|
it_behaves_like "returns success", :string, value
end

it_behaves_like "returns error", :string, {}, "Hash"
it_behaves_like "returns error", :string, [], "Array"
it_behaves_like "returns error", :string, String, "Class"
end
end

Expand Down