Skip to content
Draft
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
44 changes: 43 additions & 1 deletion lib/chrono_model/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# methods adding support for temporal extensions. It inherits from the Postgres
# adapter for a clean override of its methods using super.
#
class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter

Check failure on line 17 in lib/chrono_model/adapter.rb

View workflow job for this annotation

GitHub Actions / RuboCop

Metrics/ClassLength: Class has too many lines. [114/100]
include ChronoModel::Adapter::Migrations
include ChronoModel::Adapter::DDL
include ChronoModel::Adapter::Indexes
Expand All @@ -41,6 +41,20 @@
end
end

class TableDefinition < ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition
def foreign_key(to_table, **options)
if !@conn.is_schema_qualified?(to_table) && (@conn.current_schema == TEMPORAL_SCHEMA) != @conn.is_chrono?(to_table)
to_table = @conn.qualified_table_name(to_table)
end

super
end
end

def create_table_definition(name, **options)
ChronoModel::Adapter::TableDefinition.new(self, name, **options)
end

# Returns true whether the connection adapter supports our
# implementation of temporal tables. Currently, Chronomodel
# is supported starting with PostgreSQL 9.3 (90300 in PostgreSQL's
Expand Down Expand Up @@ -112,13 +126,18 @@

# Evaluates the given block in the given +schema+ search path.
#
# Recursion works by saving the old_path the function closure
# Recursion works by saving the old_path in the method closure
# at each recursive call.
#
# @original_schema is set to the current schema on the first call,
# and restored to +nil+ when the recursion ends. Use outer_schema()
# to get the original schema.
#
# See specs for examples and behaviour.
#
def on_schema(schema, recurse: :follow)
old_path = schema_search_path
@original_schema ||= current_schema

count_recursions do
if (recurse == :follow) || (Thread.current['recursions'] == 1)
Expand All @@ -144,6 +163,29 @@
else
self.schema_search_path = old_path
end

@original_schema = nil if Thread.current['recursions'].zero?
end

# The current schema or the schema that was the current schema before
# on_schema() was called.
#
def outer_schema
@original_schema || current_schema
end

def foreign_key_column_for(table_name, *args) # :nodoc:
_schema, table_name = extract_schema_qualified_name(table_name)
super
end

def qualified_table_name(table_name)
schema = is_chrono?(table_name) ? TEMPORAL_SCHEMA : outer_schema
"#{schema}.#{table_name}"
end

def is_schema_qualified?(name)
name.to_s.include?('.')
end

# Returns true if the given name references a temporal table.
Expand Down
20 changes: 20 additions & 0 deletions lib/chrono_model/adapter/migrations_modules/stable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ def remove_index(table_name, column_name = nil, **options)
on_history_schema { super }
end
end

def add_foreign_key(from_table, to_table, **options)
if !is_schema_qualified?(to_table) && is_chrono?(to_table) != is_chrono?(from_table)
to_table = qualified_table_name(to_table)
end

return super unless is_chrono?(from_table)

on_temporal_schema { super }
end

def remove_foreign_key(from_table, to_table = nil, **options)
if !is_schema_qualified?(to_table) && is_chrono?(to_table) != is_chrono?(from_table)
to_table = qualified_table_name(to_table)
end

return super unless is_chrono?(from_table)

on_temporal_schema { super }
end
end
end
end
Expand Down
18 changes: 18 additions & 0 deletions spec/chrono_model/adapter/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@
end
end

describe '.outer_schema' do
subject(:outer_schema) { adapter.outer_schema }

context 'when outside of on_schema()' do
it { is_expected.to eq(adapter.current_schema) }
end

context 'when inside on_schema()' do
it 'returns the original schema' do
original_schema = adapter.current_schema

adapter.on_schema('test_schema') do
expect(outer_schema).to eq(original_schema)
end
end
end
end

describe '.is_chrono?' do
subject(:is_chrono?) { adapter.is_chrono?(table) }

Expand Down
Loading
Loading