Skip to content

Commit

Permalink
Merge pull request #441 from alpaca-tc/support-rails-7-1
Browse files Browse the repository at this point in the history
Support rails 7.1
  • Loading branch information
winebarrel committed Oct 22, 2023
2 parents 153049a + 1c86ac3 commit d43f8de
Show file tree
Hide file tree
Showing 20 changed files with 643 additions and 14 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ jobs:
fail-fast: false
matrix:
ruby:
- "2.7.6"
- "3.0.4"
- "3.1.2"
- "2.7.8"
- "3.0.6"
- "3.1.4"
- "3.2.2"
env:
- MYSQL57=1
Expand All @@ -34,6 +34,7 @@ jobs:
gemfile:
- gemfiles/activerecord_6.1.gemfile
- gemfiles/activerecord_7.0.gemfile
- gemfiles/activerecord_7.1.gemfile
env:
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
steps:
Expand Down
4 changes: 4 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ end
appraise 'activerecord-7.0' do
gem 'activerecord', '~> 7.0.4'
end

appraise 'activerecord-7.1' do
gem 'activerecord', '~> 7.1.0'
end
7 changes: 7 additions & 0 deletions gemfiles/activerecord_7.1.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "activerecord", "~> 7.1.0"

gemspec path: "../"
84 changes: 84 additions & 0 deletions lib/ridgepole/delta.rb
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,18 @@ def append_create_table(table_name, attrs, buf, post_buf_for_fk)
end
end

unless (exclusion_constraints = attrs[:exclusion_constraints] || {}).empty?
exclusion_constraints.each do |_, exclusion_constraint_attrs|
append_add_exclusion_constraint(table_name, exclusion_constraint_attrs, buf, true)
end
end

unless (unique_constraints = attrs[:unique_constraints] || {}).empty?
unique_constraints.each do |_, unique_constraint_attrs|
append_add_unique_constraint(table_name, unique_constraint_attrs, buf, true)
end
end

buf.puts(<<-RUBY)
end
RUBY
Expand Down Expand Up @@ -322,6 +334,8 @@ def append_change(table_name, attrs, buf, pre_buf_for_fk, post_buf_for_fk)
indices = attrs[:indices] || {}
foreign_keys = attrs[:foreign_keys] || {}
check_constraints = attrs[:check_constraints] || {}
exclusion_constraints = attrs[:exclusion_constraints] || {}
unique_constraints = attrs[:unique_constraints] || {}
table_options = attrs[:table_options]
table_charset = attrs[:table_charset]
table_collation = attrs[:table_collation]
Expand All @@ -338,6 +352,8 @@ def append_change(table_name, attrs, buf, pre_buf_for_fk, post_buf_for_fk)

append_change_foreign_keys(table_name, foreign_keys, pre_buf_for_fk, post_buf_for_fk, @options) unless foreign_keys.empty?
append_change_check_constraints(table_name, check_constraints, buf) unless check_constraints.empty?
append_change_exclusion_constraints(table_name, exclusion_constraints, buf) unless exclusion_constraints.empty?
append_change_unique_constraints(table_name, unique_constraints, buf) unless unique_constraints.empty?

if table_options || table_charset || table_collation
append_change_table_raw_options(table_name, table_options, table_charset, table_collation,
Expand Down Expand Up @@ -553,6 +569,74 @@ def append_remove_check_constraint(table_name, attrs, buf)
RUBY
end

def append_change_exclusion_constraints(table_name, delta, buf)
(delta[:delete] || {}).each do |_, attrs|
append_remove_exclusion_constraint(table_name, attrs, buf)
end

(delta[:add] || {}).each do |_, attrs|
append_add_exclusion_constraint(table_name, attrs, buf)
end
end

def append_add_exclusion_constraint(table_name, attrs, buf, force_bulk_change = false)
expression = attrs.fetch(:expression)
attrs_options = attrs[:options] || {}

if force_bulk_change
buf.puts(<<-RUBY)
t.exclusion_constraint(#{expression.inspect}, **#{attrs_options.inspect})
RUBY
else
buf.puts(<<-RUBY)
add_exclusion_constraint(#{table_name.inspect}, #{expression.inspect}, **#{attrs_options.inspect})
RUBY
end
end

def append_remove_exclusion_constraint(table_name, attrs, buf)
expression = attrs.fetch(:expression)
attrs_options = attrs[:options] || {}

buf.puts(<<-RUBY)
remove_exclusion_constraint(#{table_name.inspect}, #{expression.inspect}, **#{attrs_options.inspect})
RUBY
end

def append_change_unique_constraints(table_name, delta, buf)
(delta[:delete] || {}).each do |_, attrs|
append_remove_unique_constraint(table_name, attrs, buf)
end

(delta[:add] || {}).each do |_, attrs|
append_add_unique_constraint(table_name, attrs, buf)
end
end

def append_add_unique_constraint(table_name, attrs, buf, force_bulk_change = false)
column_name = attrs.fetch(:column_name)
attrs_options = attrs[:options] || {}

if force_bulk_change
buf.puts(<<-RUBY)
t.unique_constraint(#{column_name.inspect}, **#{attrs_options.inspect})
RUBY
else
buf.puts(<<-RUBY)
add_unique_constraint(#{table_name.inspect}, #{column_name.inspect}, **#{attrs_options.inspect})
RUBY
end
end

def append_remove_unique_constraint(table_name, attrs, buf)
column_name = attrs.fetch(:column_name)
attrs_options = attrs[:options] || {}

buf.puts(<<-RUBY)
remove_unique_constraint(#{table_name.inspect}, #{column_name.inspect}, **#{attrs_options.inspect})
RUBY
end

def delta_execute
@delta[:execute] || []
end
Expand Down
66 changes: 66 additions & 0 deletions lib/ridgepole/diff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ def scan_change(table_name, from, to, delta)
scan_indices_change(from[:indices], to[:indices], to[:definition], table_delta, from[:options], to[:options])
scan_foreign_keys_change(from[:foreign_keys], to[:foreign_keys], table_delta, @options)
scan_check_constraints_change(from[:check_constraints], to[:check_constraints], table_delta)
scan_exclusion_constraints_change(from[:exclusion_constraints], to[:exclusion_constraints], table_delta)
scan_unique_constraints_change(from[:unique_constraints], to[:unique_constraints], table_delta)

unless table_delta.empty?
delta[:change] ||= {}
Expand Down Expand Up @@ -505,6 +507,70 @@ def scan_check_constraints_change(from, to, table_delta)
table_delta[:check_constraints] = check_constraints_delta unless check_constraints_delta.empty?
end

def scan_exclusion_constraints_change(from, to, table_delta)
from = (from || {}).dup
to = (to || {}).dup
exclusion_constraints_delta = {}

to.each do |name, to_attrs|
from_attrs = from.delete(name)

if from_attrs
if from_attrs != to_attrs
exclusion_constraints_delta[:add] ||= {}
exclusion_constraints_delta[:add][name] = to_attrs

exclusion_constraints_delta[:delete] ||= {}
exclusion_constraints_delta[:delete][name] = from_attrs
end
else
exclusion_constraints_delta[:add] ||= {}
exclusion_constraints_delta[:add][name] = to_attrs
end
end

unless @options[:merge]
from.each do |name, from_attrs|
exclusion_constraints_delta[:delete] ||= {}
exclusion_constraints_delta[:delete][name] = from_attrs
end
end

table_delta[:exclusion_constraints] = exclusion_constraints_delta unless exclusion_constraints_delta.empty?
end

def scan_unique_constraints_change(from, to, table_delta)
from = (from || {}).dup
to = (to || {}).dup
unique_constraints_delta = {}

to.each do |name, to_attrs|
from_attrs = from.delete(name)

if from_attrs
if from_attrs != to_attrs
unique_constraints_delta[:add] ||= {}
unique_constraints_delta[:add][name] = to_attrs

unique_constraints_delta[:delete] ||= {}
unique_constraints_delta[:delete][name] = from_attrs
end
else
unique_constraints_delta[:add] ||= {}
unique_constraints_delta[:add][name] = to_attrs
end
end

unless @options[:merge]
from.each do |name, from_attrs|
unique_constraints_delta[:delete] ||= {}
unique_constraints_delta[:delete][name] = from_attrs
end
end

table_delta[:unique_constraints] = unique_constraints_delta unless unique_constraints_delta.empty?
end

# XXX: MySQL only?
# https://github.com/rails/rails/blob/v4.2.1/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#L760
# https://github.com/rails/rails/blob/v4.2.1/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb#L102
Expand Down
30 changes: 30 additions & 0 deletions lib/ridgepole/dsl_parser/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,36 @@ def add_check_constraint(table_name, expression, options = {})
}
end

def add_exclusion_constraint(table_name, expression, options = {})
table_name = table_name.to_s
expression = expression.to_s
options[:name] = options[:name].to_s if options[:name]

idx = options[:name] || expression

@__definition[table_name] ||= {}
@__definition[table_name][:exclusion_constraints] ||= {}
@__definition[table_name][:exclusion_constraints][idx] = {
expression: expression,
options: options,
}
end

def add_unique_constraint(table_name, column_name, options = {})
table_name = table_name.to_s
column_name = Array(column_name).map(&:to_sym)
options[:name] = options[:name].to_s if options[:name]

idx = options[:name] || column_name

@__definition[table_name] ||= {}
@__definition[table_name][:unique_constraints] ||= {}
@__definition[table_name][:unique_constraints][idx] = {
column_name: column_name,
options: options,
}
end

def require(file)
schemafile = %r{\A/}.match?(file) ? file : File.join(@__working_dir, file)

Expand Down
8 changes: 8 additions & 0 deletions lib/ridgepole/dsl_parser/table_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ def references(*args)
def check_constraint(expression, options = {})
@base.add_check_constraint(@table_name, expression, options)
end

def exclusion_constraint(expression, options = {})
@base.add_exclusion_constraint(@table_name, expression, options)
end

def unique_constraint(column_name, options = {})
@base.add_unique_constraint(@table_name, column_name, options)
end
end
end
end
12 changes: 11 additions & 1 deletion lib/ridgepole/ext/schema_dumper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def foreign_keys(table, stream)
remove_prefix_and_suffix(foreign_key.to_table).inspect
]

parts << "column: #{foreign_key.column.inspect}" if foreign_key.column != @connection.foreign_key_column_for(foreign_key.to_table)
parts << "column: #{foreign_key.column.inspect}" if foreign_key.column != foreign_key_column_for(foreign_key)

parts << "primary_key: #{foreign_key.primary_key.inspect}" if foreign_key.custom_primary_key?

Expand All @@ -45,6 +45,16 @@ def foreign_keys(table, stream)
stream.puts add_foreign_key_statements.sort.join("\n")
end
end

private

def foreign_key_column_for(foreign_key)
if ActiveRecord.gem_version < Gem::Version.new('7.1.0')
@connection.foreign_key_column_for(foreign_key.to_table)
else
@connection.foreign_key_column_for(foreign_key.to_table, 'id')
end
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion ridgepole.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Gem::Specification.new do |spec|

spec.required_ruby_version = Gem::Requirement.new('>= 2.7')

spec.add_dependency 'activerecord', '>= 6.1', '< 7.1'
spec.add_dependency 'activerecord', '>= 6.1', '< 7.2'
spec.add_dependency 'diffy'

spec.add_development_dependency 'appraisal', '>= 2.2.0'
Expand Down
9 changes: 7 additions & 2 deletions spec/mysql/collation/collation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
t.integer "emp_no", null: false
t.integer "club_id", null: false, unsigned: true
t.string "string", null: false, collation: "ascii_bin"
t.text "text", null: false, collation: nil
t.text "text", null: false, collation: <%= i cond(">= 7.1", ":no_collation", 'nil') %>
end
ERB
end
Expand All @@ -67,7 +67,12 @@
expect(delta.differ?).to be_truthy
expect(subject.dump).to match_ruby actual_dsl
delta.migrate
expect(subject.dump).to match_ruby expected_dsl.gsub(', collation: nil', '') # for AR 7.0.4

if ActiveRecord.gem_version < Gem::Version.new('7.1.0')
expect(subject.dump).to match_ruby expected_dsl.gsub(', collation: nil', '') # for AR 7.0.4
else
expect(subject.dump).to match_ruby expected_dsl.gsub(', collation: :no_collation', '') # for AR 7.1.0
end
end
end

Expand Down
4 changes: 2 additions & 2 deletions spec/postgresql/fk/migrate_create_fk_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
end
create_table "child", force: :cascade do |t|
t.integer "parent_id", unsigned: true
t.integer "parent_id"
t.index ["parent_id"], name: "par_id"
end
Expand Down Expand Up @@ -93,7 +93,7 @@
end
create_table "child", force: :cascade do |t|
t.integer "parent_id", unsigned: true
t.integer "parent_id"
t.index ["parent_id"], name: "par_id"
end
Expand Down
4 changes: 2 additions & 2 deletions spec/postgresql/fk/migrate_drop_fk_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
end
create_table "child", force: :cascade do |t|
t.integer "parent_id", unsigned: true
t.integer "parent_id"
t.index ["parent_id"], name: "par_id"
end
Expand Down Expand Up @@ -161,7 +161,7 @@
end
create_table "child", force: :cascade do |t|
t.integer "parent_id", unsigned: true
t.integer "parent_id"
t.index ["parent_id"], name: "par_id"
end
Expand Down
Loading

0 comments on commit d43f8de

Please sign in to comment.