Skip to content

Commit 69164a2

Browse files
authored
Merge pull request #35 from Invoca/TECH-4971_declareschema_treat_integer_limit_8_and_bigint_types_identically
Tech 4971 declareschema treat integer limit 8 and bigint types identically
2 parents 77f1c59 + 4ff01fa commit 69164a2

File tree

6 files changed

+111
-10
lines changed

6 files changed

+111
-10
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Inspired by [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
44

55
Note: this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [0.6.0] - Unreleased
8+
### Added
9+
- Fields may now be declared with `:bigint` type which is identical to `:integer, limit 8`
10+
711
## [0.5.0] - 2020-12-21
812
### Added
913
- Added support for configuring the character set and collation for MySQL databases
@@ -73,6 +77,7 @@ using the appropriate Rails configuration attributes.
7377
### Added
7478
- Initial version from https://github.com/Invoca/hobo_fields v4.1.0.
7579

80+
[0.6.0]: https://github.com/Invoca/declare_schema/compare/v0.5.0...v0.6.0
7681
[0.5.0]: https://github.com/Invoca/declare_schema/compare/v0.4.2...v0.5.0
7782
[0.4.2]: https://github.com/Invoca/declare_schema/compare/v0.4.1...v0.4.2
7883
[0.4.1]: https://github.com/Invoca/declare_schema/compare/v0.4.0...v0.4.1

lib/declare_schema/model.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def declare_field(name, type, *args)
8888
add_formatting_for_field(name, type)
8989
add_validations_for_field(name, type, args, options)
9090
add_index_for_field(name, args, options)
91-
field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, options)
91+
field_specs[name] = ::DeclareSchema::Model::FieldSpec.new(self, name, type, position: field_specs.size, **options)
9292
attr_order << name unless attr_order.include?(name)
9393
end
9494

lib/declare_schema/model/field_spec.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ def round_up_mysql_text_limit(limit)
3333

3434
attr_reader :model, :name, :type, :position, :options
3535

36-
def initialize(model, name, type, options = {})
36+
def initialize(model, name, type, position: 0, **options)
37+
# TODO: TECH-5116
3738
# Invoca change - searching for the primary key was causing an additional database read on every model load. Assume
3839
# "id" which works for invoca.
3940
# raise ArgumentError, "you cannot provide a field spec for the primary key" if name == model.primary_key
@@ -43,9 +44,8 @@ def initialize(model, name, type, options = {})
4344
@name = name.to_sym
4445
type.is_a?(Symbol) or raise ArgumentError, "type must be a Symbol; got #{type.inspect}"
4546
@type = type
46-
position_option = options.delete(:position)
47+
@position = position
4748
@options = options
48-
4949
case type
5050
when :text
5151
@options[:default] and raise "default may not be given for :text field #{model}##{@name}"
@@ -54,11 +54,15 @@ def initialize(model, name, type, options = {})
5454
end
5555
when :string
5656
@options[:limit] or raise "limit must be given for :string field #{model}##{@name}: #{@options.inspect}; do you want `limit: 255`?"
57-
else
57+
when :bigint
58+
@type = :integer
59+
@options = options.merge(limit: 8)
60+
end
61+
62+
unless type.in?([:text, :string])
5863
@options[:collation] and raise "collation may only given for :string and :text fields"
5964
@options[:charset] and raise "charset may only given for :string and :text fields"
6065
end
61-
@position = position_option || model.field_specs.length
6266
end
6367

6468
TYPE_SYNONYMS = { timestamp: :datetime }.freeze

lib/generators/declare_schema/migration/migrator.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@ def table_exists?
3737

3838
def field_specs
3939
i = 0
40-
foreign_keys.reduce({}) do |h, v|
41-
# some trickery to avoid an infinite loop when FieldSpec#initialize tries to call model.field_specs
42-
h[v] = ::DeclareSchema::Model::FieldSpec.new(self, v, :integer, position: i, null: false)
40+
foreign_keys.each_with_object({}) do |v, result|
41+
result[v] = ::DeclareSchema::Model::FieldSpec.new(self, v, :integer, position: i, null: false)
4342
i += 1
44-
h
4543
end
4644
end
4745

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe 'DeclareSchema Model FieldSpec' do
4+
before do
5+
load File.expand_path('prepare_testapp.rb', __dir__)
6+
end
7+
8+
context 'There are no model columns to change' do
9+
it '#different_to should return false for int8 == int8' do
10+
subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
11+
12+
case Rails::VERSION::MAJOR
13+
when 4
14+
cast_type = ActiveRecord::Type::Integer.new(limit: 8)
15+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
16+
else
17+
sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
18+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
19+
end
20+
21+
expect(subject.different_to?(subject.name, col)).to eq(false)
22+
end
23+
24+
it '#different_to should return false for bigint == bigint' do
25+
subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
26+
27+
case Rails::VERSION::MAJOR
28+
when 4
29+
cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
30+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
31+
else
32+
sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
33+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
34+
end
35+
36+
expect(subject.different_to?(subject.name, col)).to eq(false)
37+
end
38+
39+
it '#different_to should return false for int8 == bigint' do
40+
subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :integer, limit: 8, null: false, position: 0)
41+
42+
case Rails::VERSION::MAJOR
43+
when 4
44+
cast_type = ActiveRecord::Type::BigInteger.new(limit: 8)
45+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "bigint(20)", false)
46+
else
47+
sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "bigint(20)", type: :integer, limit: 8)
48+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
49+
end
50+
51+
expect(subject.different_to?(subject.name, col)).to eq(false)
52+
end
53+
54+
it '#different_to should return false for bigint == int8' do
55+
subject = DeclareSchema::Model::FieldSpec.new(Object, :price, :bigint, null: false, position: 0)
56+
57+
case Rails::VERSION::MAJOR
58+
when 4
59+
cast_type = ActiveRecord::Type::Integer.new(limit: 8)
60+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, cast_type, "integer(8)", false)
61+
else
62+
sql_type_metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(sql_type: "integer(8)", type: :integer, limit: 8)
63+
col = ActiveRecord::ConnectionAdapters::Column.new("price", nil, sql_type_metadata, false, "adverts")
64+
end
65+
66+
expect(subject.different_to?(subject.name, col)).to eq(false)
67+
end
68+
end
69+
end

spec/lib/declare_schema/migration_generator_spec.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,4 +1093,29 @@ class Advert < active_record_base_class.constantize
10931093
expect(base_class).to eq("(Rails::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[4.2] : ActiveRecord::Migration)")
10941094
end
10951095
end
1096+
1097+
context 'Does not generate migrations' do
1098+
it 'for aliased fields bigint -> integer limit 8' do
1099+
if Rails::VERSION::MAJOR >= 5 || !ActiveRecord::Base.connection.class.name.match?(/SQLite3Adapter/)
1100+
class Advert < active_record_base_class.constantize
1101+
fields do
1102+
price :bigint
1103+
end
1104+
end
1105+
1106+
generate_migrations '-n', '-m'
1107+
1108+
migrations = Dir.glob('db/migrate/*declare_schema_migration*.rb')
1109+
expect(migrations.size).to eq(1), migrations.inspect
1110+
1111+
class Advert < active_record_base_class.constantize
1112+
fields do
1113+
price :integer, limit: 8
1114+
end
1115+
end
1116+
1117+
expect { generate_migrations '-n', '-g' }.to output("Database and models match -- nothing to change\n").to_stdout
1118+
end
1119+
end
1120+
end
10961121
end

0 commit comments

Comments
 (0)