Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Commit

Permalink
Merge 13d3dff into 59ea144
Browse files Browse the repository at this point in the history
  • Loading branch information
konjoot committed Feb 1, 2015
2 parents 59ea144 + 13d3dff commit 9b9d03b
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ForeignKeyDefinition < ::ActiveRecord::ConnectionAdapters::ForeignKeyDefin

ACTIONS = { :cascade => "CASCADE", :restrict => "RESTRICT", :set_null => "SET NULL", :set_default => "SET DEFAULT", :no_action => "NO ACTION" }.freeze

def initialize(from_table, to_table, options)
def initialize(from_table, to_table, options)
super
@from_table = unquote(from_table)
@to_table = unquote(to_table)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ def add_index_options_with_schema_plus(table_name, column_name, options = {})
end

def self.add_index_exception_handler(connection, table, columns, options, e) #:nodoc:
raise unless e.message.match(/["']([^"']+)["'].*already exists/)
raise unless e.message.match(/already exists|DuplicateTable|CREATE INDEX/)
e.message.match(/["']([^"']+)["'].*/)
name = $1
existing = connection.indexes(table).find{|i| i.name == name}
attempted = ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table, columns, options.merge(:name => name))
attempted = ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table, columns, options.merge(:name => name))
raise if attempted != existing
::ActiveRecord::Base.logger.warn "[schema_plus] Index name #{name.inspect}' on table #{table.inspect} already exists. Skipping."
end
Expand Down
13 changes: 12 additions & 1 deletion lib/schema_plus/active_record/schema_dumper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ def break_fk_cycles #:nodoc:
end
end

def fix_backref_fks_for(table)
@backref_fks[table].each do |fk|
@dumped_tables.include?(fk.table_name) ||
@backref_fks[fk.table_name].push(@backref_fks[table].delete(fk))
end
end

def tables_with_schema_plus(stream) #:nodoc:
@table_dumps = {}
@inline_fks = Hash.new{ |h, k| h[k] = [] }
Expand Down Expand Up @@ -100,12 +107,16 @@ def tables_with_schema_plus(stream) #:nodoc:
# won't let you create cycles in the first place.)
break_fk_cycles while strongly_connected_components.any?{|component| component.size > 1}

@dumped_tables = []

tsort().each do |table|
table_dump = @table_dumps[table]
if i = (table_dump =~ /^\s*[e]nd\s*$/)
table_dump.insert i, dump_indexes(table) + dump_foreign_keys(@inline_fks[table], :inline => true)
end
stream.print table_dump
@dumped_tables << table
fix_backref_fks_for(table)
stream.puts dump_foreign_keys(@backref_fks[table], :inline => false)+"\n" if @backref_fks[table].any?
end

Expand Down Expand Up @@ -149,7 +160,7 @@ def dump_indexes(table) #:nodoc:
dump << " :name => #{index.name.inspect}"
dump << ", :unique => true" if index.unique
dump << ", :kind => \"#{index.kind}\"" unless index.kind.blank?
unless index.columns.blank?
unless index.columns.blank?
dump << ", :case_sensitive => false" unless index.case_sensitive?
dump << ", :conditions => #{index.conditions.inspect}" unless index.conditions.blank?
index_lengths = index.lengths.compact if index.lengths.is_a?(Array)
Expand Down
4 changes: 2 additions & 2 deletions spec/named_schemas_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def connection
begin
ActiveRecord::Base.connection.execute newdb
rescue ActiveRecord::StatementInvalid => e
raise unless e.message =~ /already exists/
raise unless e.message =~ /already exists|DuplicateSchema|CREATE SCHEMA/
end

class User < ::ActiveRecord::Base ; end
Expand Down Expand Up @@ -184,7 +184,7 @@ class Member < ::ActiveRecord::Base
begin
connection.execute "CREATE SCHEMA postgis"
rescue ActiveRecord::StatementInvalid => e
raise unless e.message =~ /already exists/
raise unless e.message =~ /already exists|DuplicateSchema|CREATE SCHEMA/
end
end

Expand Down
97 changes: 96 additions & 1 deletion spec/schema_dumper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class ::Comment < ActiveRecord::Base ; end
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id"], :name => "custom_name"}))
end
end

it "should define unique index" do
with_index Post, :user_id, :name => "posts_user_id_index", :unique => true do
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id"], :name => "posts_user_id_index", :unique => true}))
Expand Down Expand Up @@ -278,6 +278,101 @@ class ::Comment < ActiveRecord::Base ; end
expect(dump_schema).to match(%r{create_table "users".*foreign_key.*\["commenter_id"\], "users", \["id"\]}m)
expect(dump_schema).to match(%r{create_table "users".*foreign_key.*\["user_id"\], "users", \["id"\]}m)
end

context 'with complicated schemas' do
before(:all) do

SchemaPlus.setup do |config|
config.foreign_keys.auto_create = false
end
ActiveRecord::Migration.suppress_messages do
ActiveRecord::Schema.define do
connection.tables.each do |table| drop_table table, :cascade => true end

create_table :period_types, force: true do |t|
t.string :name
end

create_table :grade_systems, force: true do |t|
t.string :name
t.integer :school_id
t.integer :parent_id
t.integer :profile_id
end

create_table :schools, force: true do |t|
t.string :name
t.integer :default_grade_system_id
end

create_table :academic_years, force: true do |t|
t.string :name
t.integer :school_id
t.integer :period_type_id
end

create_table :buildings, force: true do |t|
t.string :name
t.integer :school_id
end

create_table :publishing_houses, force: true do |t|
t.string :name
end

create_table :profiles, force: true do |t|
t.integer :school_id
t.integer :publishing_house_id
t.integer :building_id
end

create_table :class_units, force: true do |t|
t.string :name
t.integer :school_id
t.integer :mentor_id
t.integer :building_id
end
end
end

class ::AcademicYear < ActiveRecord::Base ; end
class ::Building < ActiveRecord::Base ; end
class ::ClassUnit < ActiveRecord::Base ; end
class ::GradeSystem < ActiveRecord::Base ; end
class ::Profile < ActiveRecord::Base ; end
class ::PublishingHouse < ActiveRecord::Base ; end
class ::PeriodType < ActiveRecord::Base ; end
class ::School < ActiveRecord::Base ; end

ActiveRecord::Base.connection.add_foreign_key(School.table_name, :default_grade_system_id, GradeSystem.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(GradeSystem.table_name, :school_id, School.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(GradeSystem.table_name, :parent_id, GradeSystem.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(GradeSystem.table_name, :profile_id, Profile.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(Profile.table_name, :building_id, Building.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(Profile.table_name, :school_id, School.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(ClassUnit.table_name, :school_id, School.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(ClassUnit.table_name, :building_id, Building.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(ClassUnit.table_name, :mentor_id, Profile.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(Building.table_name, :school_id, School.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(AcademicYear.table_name, :school_id, School.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(AcademicYear.table_name, :period_type_id, PeriodType.table_name, :id)
ActiveRecord::Base.connection.add_foreign_key(Profile.table_name, :publishing_house_id, PublishingHouse.table_name, :id)
end

it "should not raise an error" do
expect { dump_schema }.to_not raise_error
end

it "should dump each constraint after both related tables were defined" do
expect(dump_schema).to match(%r{create_table "buildings".*add_foreign_key\s+"buildings".*\["school_id"\], "schools", \["id"\]}m)
expect(dump_schema).to match(%r{create_table "grade_systems".*add_foreign_key\s+"grade_systems".*\["parent_id"\], "grade_systems", \["id"\]}m)
expect(dump_schema).to match(%r{create_table "grade_systems".*add_foreign_key\s+"grade_systems".*\["school_id"\], "schools", \["id"\]}m)
expect(dump_schema).to match(%r{create_table "grade_systems".*add_foreign_key\s+"grade_systems".*\["profile_id"\], "profiles", \["id"\]}m)
expect(dump_schema).to match(%r{create_table "profiles".*add_foreign_key\s+"grade_systems".*\["profile_id"\], "profiles", \["id"\]}m)
expect(dump_schema).to match(%r{create_table "schools".*add_foreign_key\s+"buildings".*\["school_id"\], "schools", \["id"\]}m)
expect(dump_schema).to match(%r{create_table "schools".*add_foreign_key\s+"grade_systems".*\["school_id"\], "schools", \["id"\]}m)
end
end
end

context 'with enum', :postgresql => :only do
Expand Down

0 comments on commit 9b9d03b

Please sign in to comment.