From 58645d1bcc1368ed0332060a1a9bc8a281f0be50 Mon Sep 17 00:00:00 2001 From: Oxyless Date: Thu, 13 Jul 2023 14:43:22 +0200 Subject: [PATCH 01/12] Add specific support --- .rubocop_schema.49.yml | 35 ----- .rubocop_schema.53.yml | 38 ------ .rubocop_schema.77.yml | 41 ------ .rubocop_schema.yml | 35 ----- fix-db-schema-conflicts.gemspec | 6 - .../autocorrect_configuration.rb | 25 ---- lib/fix_db_schema_conflicts/schema_dumper.rb | 14 ++ lib/fix_db_schema_conflicts/tasks/db.rake | 12 -- spec/integration/integration_spec.rb | 61 --------- spec/spec_helper.rb | 95 ------------- spec/test-app/.gitignore | 17 --- spec/test-app/Gemfile | 8 -- spec/test-app/Gemfile.lock | 125 ------------------ spec/test-app/README.rdoc | 28 ---- spec/test-app/Rakefile | 6 - spec/test-app/app/assets/config/manifest.js | 0 spec/test-app/app/assets/images/.keep | 0 .../app/assets/javascripts/application.js | 16 --- .../app/assets/stylesheets/application.css | 15 --- .../app/controllers/application_controller.rb | 5 - spec/test-app/app/controllers/concerns/.keep | 0 .../app/helpers/application_helper.rb | 2 - spec/test-app/app/mailers/.keep | 0 spec/test-app/app/models/.keep | 0 spec/test-app/app/models/company.rb | 2 - spec/test-app/app/models/concerns/.keep | 0 spec/test-app/app/models/person.rb | 2 - .../app/views/layouts/application.html.erb | 14 -- spec/test-app/bin/bundle | 3 - spec/test-app/bin/rails | 9 -- spec/test-app/bin/rake | 9 -- spec/test-app/bin/setup | 29 ---- spec/test-app/bin/spring | 15 --- spec/test-app/config.ru | 4 - spec/test-app/config/application.rb | 26 ---- spec/test-app/config/boot.rb | 3 - spec/test-app/config/database.yml | 25 ---- spec/test-app/config/environment.rb | 5 - .../config/environments/development.rb | 41 ------ .../config/environments/production.rb | 79 ----------- spec/test-app/config/environments/test.rb | 42 ------ spec/test-app/config/initializers/assets.rb | 11 -- .../initializers/backtrace_silencers.rb | 7 - .../config/initializers/cookies_serializer.rb | 3 - .../initializers/filter_parameter_logging.rb | 4 - .../config/initializers/inflections.rb | 16 --- .../config/initializers/mime_types.rb | 4 - .../config/initializers/session_store.rb | 3 - .../config/initializers/wrap_parameters.rb | 14 -- spec/test-app/config/locales/en.yml | 23 ---- spec/test-app/config/routes.rb | 56 -------- spec/test-app/config/secrets.yml | 22 --- .../migrate/20160322223225_create_people.rb | 12 -- .../20160322223258_create_companies.rb | 19 --- spec/test-app/db/schema.rb | 38 ------ spec/test-app/db/seeds.rb | 7 - spec/test-app/lib/assets/.keep | 0 spec/test-app/lib/tasks/.keep | 0 spec/test-app/log/.keep | 0 spec/test-app/public/404.html | 67 ---------- spec/test-app/public/422.html | 67 ---------- spec/test-app/public/500.html | 66 --------- spec/test-app/public/favicon.ico | 0 spec/test-app/public/robots.txt | 5 - spec/test-app/test/controllers/.keep | 0 spec/test-app/test/fixtures/.keep | 0 spec/test-app/test/fixtures/companies.yml | 19 --- spec/test-app/test/fixtures/people.yml | 13 -- spec/test-app/test/helpers/.keep | 0 spec/test-app/test/integration/.keep | 0 spec/test-app/test/mailers/.keep | 0 spec/test-app/test/models/.keep | 0 spec/test-app/test/models/company_test.rb | 7 - spec/test-app/test/models/person_test.rb | 7 - spec/test-app/test/test_helper.rb | 10 -- spec/test-app/vendor/assets/javascripts/.keep | 0 spec/test-app/vendor/assets/stylesheets/.keep | 0 spec/unit/autocorrect_configuration_spec.rb | 35 ----- 78 files changed, 14 insertions(+), 1413 deletions(-) delete mode 100644 .rubocop_schema.49.yml delete mode 100644 .rubocop_schema.53.yml delete mode 100644 .rubocop_schema.77.yml delete mode 100644 .rubocop_schema.yml delete mode 100644 lib/fix_db_schema_conflicts/autocorrect_configuration.rb delete mode 100644 spec/integration/integration_spec.rb delete mode 100644 spec/spec_helper.rb delete mode 100644 spec/test-app/.gitignore delete mode 100644 spec/test-app/Gemfile delete mode 100644 spec/test-app/Gemfile.lock delete mode 100644 spec/test-app/README.rdoc delete mode 100644 spec/test-app/Rakefile delete mode 100644 spec/test-app/app/assets/config/manifest.js delete mode 100644 spec/test-app/app/assets/images/.keep delete mode 100644 spec/test-app/app/assets/javascripts/application.js delete mode 100644 spec/test-app/app/assets/stylesheets/application.css delete mode 100644 spec/test-app/app/controllers/application_controller.rb delete mode 100644 spec/test-app/app/controllers/concerns/.keep delete mode 100644 spec/test-app/app/helpers/application_helper.rb delete mode 100644 spec/test-app/app/mailers/.keep delete mode 100644 spec/test-app/app/models/.keep delete mode 100644 spec/test-app/app/models/company.rb delete mode 100644 spec/test-app/app/models/concerns/.keep delete mode 100644 spec/test-app/app/models/person.rb delete mode 100644 spec/test-app/app/views/layouts/application.html.erb delete mode 100755 spec/test-app/bin/bundle delete mode 100755 spec/test-app/bin/rails delete mode 100755 spec/test-app/bin/rake delete mode 100755 spec/test-app/bin/setup delete mode 100755 spec/test-app/bin/spring delete mode 100644 spec/test-app/config.ru delete mode 100644 spec/test-app/config/application.rb delete mode 100644 spec/test-app/config/boot.rb delete mode 100644 spec/test-app/config/database.yml delete mode 100644 spec/test-app/config/environment.rb delete mode 100644 spec/test-app/config/environments/development.rb delete mode 100644 spec/test-app/config/environments/production.rb delete mode 100644 spec/test-app/config/environments/test.rb delete mode 100644 spec/test-app/config/initializers/assets.rb delete mode 100644 spec/test-app/config/initializers/backtrace_silencers.rb delete mode 100644 spec/test-app/config/initializers/cookies_serializer.rb delete mode 100644 spec/test-app/config/initializers/filter_parameter_logging.rb delete mode 100644 spec/test-app/config/initializers/inflections.rb delete mode 100644 spec/test-app/config/initializers/mime_types.rb delete mode 100644 spec/test-app/config/initializers/session_store.rb delete mode 100644 spec/test-app/config/initializers/wrap_parameters.rb delete mode 100644 spec/test-app/config/locales/en.yml delete mode 100644 spec/test-app/config/routes.rb delete mode 100644 spec/test-app/config/secrets.yml delete mode 100644 spec/test-app/db/migrate/20160322223225_create_people.rb delete mode 100644 spec/test-app/db/migrate/20160322223258_create_companies.rb delete mode 100644 spec/test-app/db/schema.rb delete mode 100644 spec/test-app/db/seeds.rb delete mode 100644 spec/test-app/lib/assets/.keep delete mode 100644 spec/test-app/lib/tasks/.keep delete mode 100644 spec/test-app/log/.keep delete mode 100644 spec/test-app/public/404.html delete mode 100644 spec/test-app/public/422.html delete mode 100644 spec/test-app/public/500.html delete mode 100644 spec/test-app/public/favicon.ico delete mode 100644 spec/test-app/public/robots.txt delete mode 100644 spec/test-app/test/controllers/.keep delete mode 100644 spec/test-app/test/fixtures/.keep delete mode 100644 spec/test-app/test/fixtures/companies.yml delete mode 100644 spec/test-app/test/fixtures/people.yml delete mode 100644 spec/test-app/test/helpers/.keep delete mode 100644 spec/test-app/test/integration/.keep delete mode 100644 spec/test-app/test/mailers/.keep delete mode 100644 spec/test-app/test/models/.keep delete mode 100644 spec/test-app/test/models/company_test.rb delete mode 100644 spec/test-app/test/models/person_test.rb delete mode 100644 spec/test-app/test/test_helper.rb delete mode 100644 spec/test-app/vendor/assets/javascripts/.keep delete mode 100644 spec/test-app/vendor/assets/stylesheets/.keep delete mode 100644 spec/unit/autocorrect_configuration_spec.rb diff --git a/.rubocop_schema.49.yml b/.rubocop_schema.49.yml deleted file mode 100644 index 8996d87..0000000 --- a/.rubocop_schema.49.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Configuration for Rubocop >= 0.49.0 - -Layout/AlignHash: - EnforcedColonStyle: 'key' - EnforcedHashRocketStyle: 'key' - -Layout/ExtraSpacing: - # When true, allows most uses of extra spacing if the intent is to align - # things with the previous or next line, not counting empty lines or comment - # lines. - AllowForAlignment: false - -Layout/SpaceBeforeFirstArg: - Enabled: true - -Style/NumericLiterals: - Enabled: false - -Metrics/BlockNesting: - Max: 2 - -Style/WordArray: - Enabled: false - -Style/TrailingCommaInLiteral: - EnforcedStyleForMultiline: 'comma' - -Style/TrailingCommaInArguments: - EnforcedStyleForMultiline: 'comma' - -Style/HashSyntax: - EnforcedStyle: 'ruby19' - -Style/StringLiterals: - EnforcedStyle: double_quotes diff --git a/.rubocop_schema.53.yml b/.rubocop_schema.53.yml deleted file mode 100644 index 7d6be78..0000000 --- a/.rubocop_schema.53.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Configuration for Rubocop >= 0.53.0 - -Layout/AlignHash: - EnforcedColonStyle: 'key' - EnforcedHashRocketStyle: 'key' - -Layout/ExtraSpacing: - # When true, allows most uses of extra spacing if the intent is to align - # things with the previous or next line, not counting empty lines or comment - # lines. - AllowForAlignment: false - -Layout/SpaceBeforeFirstArg: - Enabled: true - -Style/NumericLiterals: - Enabled: false - -Metrics/BlockNesting: - Max: 2 - -Style/WordArray: - Enabled: false - -Style/TrailingCommaInArrayLiteral: - EnforcedStyleForMultiline: 'comma' - -Style/TrailingCommaInHashLiteral: - EnforcedStyleForMultiline: 'comma' - -Style/TrailingCommaInArguments: - EnforcedStyleForMultiline: 'comma' - -Style/HashSyntax: - EnforcedStyle: 'ruby19' - -Style/StringLiterals: - EnforcedStyle: double_quotes diff --git a/.rubocop_schema.77.yml b/.rubocop_schema.77.yml deleted file mode 100644 index d4b549c..0000000 --- a/.rubocop_schema.77.yml +++ /dev/null @@ -1,41 +0,0 @@ -# Configuration for Rubocop >= 0.77.0 - -Layout/ExtraSpacing: - # When true, allows most uses of extra spacing if the intent is to align - # things with the previous or next line, not counting empty lines or comment - # lines. - AllowForAlignment: false - -Layout/HashAlignment: - EnforcedColonStyle: 'key' - EnforcedHashRocketStyle: 'key' - -Layout/LineLength: - Enabled: false - -Layout/SpaceBeforeFirstArg: - Enabled: true - -Style/NumericLiterals: - Enabled: false - -Metrics/BlockNesting: - Max: 2 - -Style/WordArray: - Enabled: false - -Style/TrailingCommaInArrayLiteral: - EnforcedStyleForMultiline: 'comma' - -Style/TrailingCommaInHashLiteral: - EnforcedStyleForMultiline: 'comma' - -Style/TrailingCommaInArguments: - EnforcedStyleForMultiline: 'comma' - -Style/HashSyntax: - EnforcedStyle: 'ruby19' - -Style/StringLiterals: - EnforcedStyle: double_quotes diff --git a/.rubocop_schema.yml b/.rubocop_schema.yml deleted file mode 100644 index 09dc449..0000000 --- a/.rubocop_schema.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Configuration for Rubocop >= 0.38.0, < 0.49.0 - -Style/ExtraSpacing: - # When true, allows most uses of extra spacing if the intent is to align - # things with the previous or next line, not counting empty lines or comment - # lines. - AllowForAlignment: false - -Style/NumericLiterals: - Enabled: false - -Style/SpaceBeforeFirstArg: - Enabled: true - -Metrics/BlockNesting: - Max: 2 - -Style/AlignHash: - EnforcedColonStyle: 'key' - EnforcedHashRocketStyle: 'key' - -Style/WordArray: - Enabled: false - -Style/TrailingCommaInLiteral: - EnforcedStyleForMultiline: 'comma' - -Style/TrailingCommaInArguments: - EnforcedStyleForMultiline: 'comma' - -Style/HashSyntax: - EnforcedStyle: 'ruby19' - -Style/StringLiterals: - EnforcedStyle: double_quotes diff --git a/fix-db-schema-conflicts.gemspec b/fix-db-schema-conflicts.gemspec index 739a058..f39ecb9 100644 --- a/fix-db-schema-conflicts.gemspec +++ b/fix-db-schema-conflicts.gemspec @@ -15,16 +15,10 @@ Gem::Specification.new do |spec| spec.files = `git ls-files -z`.split("\x0") spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } - spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] spec.add_development_dependency 'bundler' spec.add_development_dependency 'rake' - spec.add_development_dependency 'rspec', '~>3.4.0' spec.add_development_dependency 'rails', '~> 4.2.0' - spec.add_development_dependency 'sqlite3', '~> 1.3.0' - - spec.add_dependency 'rubocop', '>= 0.38.0' - spec.required_ruby_version = '>= 2.0.0', '< 4' end diff --git a/lib/fix_db_schema_conflicts/autocorrect_configuration.rb b/lib/fix_db_schema_conflicts/autocorrect_configuration.rb deleted file mode 100644 index f183d89..0000000 --- a/lib/fix_db_schema_conflicts/autocorrect_configuration.rb +++ /dev/null @@ -1,25 +0,0 @@ -module FixDBSchemaConflicts - class AutocorrectConfiguration - def self.load - new.load - end - - def load - if less_than_rubocop?(49) - '.rubocop_schema.yml' - elsif less_than_rubocop?(53) - '.rubocop_schema.49.yml' - elsif less_than_rubocop?(77) - '.rubocop_schema.53.yml' - else - '.rubocop_schema.77.yml' - end - end - - private - - def less_than_rubocop?(ver) - Gem.loaded_specs['rubocop'].version < Gem::Version.new("0.#{ver}.0") - end - end -end diff --git a/lib/fix_db_schema_conflicts/schema_dumper.rb b/lib/fix_db_schema_conflicts/schema_dumper.rb index 1bcd458..1965a6f 100644 --- a/lib/fix_db_schema_conflicts/schema_dumper.rb +++ b/lib/fix_db_schema_conflicts/schema_dumper.rb @@ -26,6 +26,20 @@ def extensions(*args) end end + def tables(stream) + specific = ENV['SCHEMA'] || if defined? ActiveRecord::Tasks::DatabaseTasks + File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'specific.rb') + else + "#{Rails.root}/db/specific.rb" + end + + if File.exists?(specific) + stream.puts("\t" + File.read(specific).gsub("\n", "\n\t") + "\n\n") + end + + super(stream) + end + def table(*args) with_sorting do super(*args) diff --git a/lib/fix_db_schema_conflicts/tasks/db.rake b/lib/fix_db_schema_conflicts/tasks/db.rake index 5b33648..dbb7a7d 100644 --- a/lib/fix_db_schema_conflicts/tasks/db.rake +++ b/lib/fix_db_schema_conflicts/tasks/db.rake @@ -1,25 +1,13 @@ require 'shellwords' -require_relative '../autocorrect_configuration' namespace :db do namespace :schema do task :dump do - puts "Dumping database schema with fix-db-schema-conflicts gem" - filename = ENV['SCHEMA'] || if defined? ActiveRecord::Tasks::DatabaseTasks File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb') else "#{Rails.root}/db/schema.rb" end - autocorrect_config = FixDBSchemaConflicts::AutocorrectConfiguration.load - rubocop_yml = File.expand_path("../../../../#{autocorrect_config}", __FILE__) - auto_correct_arg = if Gem.loaded_specs['rubocop'].version >= Gem::Version.new('1.30') - 'autocorrect' - else - 'auto-correct' - end - - `bundle exec rubocop --#{auto_correct_arg} --config #{rubocop_yml} #{filename.shellescape}` end end end diff --git a/spec/integration/integration_spec.rb b/spec/integration/integration_spec.rb deleted file mode 100644 index 20f1885..0000000 --- a/spec/integration/integration_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'spec_helper' - -RSpec.describe 'Fix DB Schema Conflicts' do - - let(:expected_lines) { reference_db_schema.lines } - - it 'generates a sorted schema with no extra spacing' do - - `cd spec/test-app && rm -f db/schema.rb && rake db:migrate` - - generated_lines = File.readlines('spec/test-app/db/schema.rb') - - generated_lines.zip(expected_lines).each do |generated, expected| - next if expected.nil? - next if expected.start_with?('ActiveRecord::Schema.define') - expect(generated).to eq(expected) - end - end -end - -def reference_db_schema - <<-RUBY -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 20160322223258) do - create_table "companies", force: :cascade do |t| - t.string "addr1" - t.string "addr2" - t.string "city" - t.datetime "created_at", null: false - t.string "name" - t.string "phone" - t.string "state" - t.datetime "updated_at", null: false - t.string "zip" - end - - add_index "companies", ["city"], name: "index_companies_on_city" - add_index "companies", ["name"], name: "index_companies_on_name" - add_index "companies", ["state"], name: "index_companies_on_state" - - create_table "people", force: :cascade do |t| - t.integer "age" - t.date "birthdate" - t.datetime "created_at", null: false - t.string "first_name" - t.string "last_name" - t.datetime "updated_at", null: false - end - RUBY -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index ce9e119..0000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,95 +0,0 @@ -# This file was generated by the `rspec --init` command. Conventionally, all -# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. -# The generated `.rspec` file contains `--require spec_helper` which will cause -# this file to always be loaded, without a need to explicitly require it in any -# files. -# -# Given that it is always loaded, you are encouraged to keep this file as -# light-weight as possible. Requiring heavyweight dependencies from this file -# will add to the boot time of your test suite on EVERY test run, even for an -# individual file that may not need all of that loaded. Instead, consider making -# a separate helper file that requires the additional dependencies and performs -# the additional setup, and require it from the spec files that actually need -# it. -# -# The `.rspec` file also contains a few flags that are not defaults but that -# users commonly want. -# -# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration -RSpec.configure do |config| - # rspec-expectations config goes here. You can use an alternate - # assertion/expectation library such as wrong or the stdlib/minitest - # assertions if you prefer. - config.expect_with :rspec do |expectations| - # This option will default to `true` in RSpec 4. It makes the `description` - # and `failure_message` of custom matchers include text for helper methods - # defined using `chain`, e.g.: - # be_bigger_than(2).and_smaller_than(4).description - # # => "be bigger than 2 and smaller than 4" - # ...rather than: - # # => "be bigger than 2" - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - # rspec-mocks config goes here. You can use an alternate test double - # library (such as bogus or mocha) by changing the `mock_with` option here. - config.mock_with :rspec do |mocks| - # Prevents you from mocking or stubbing a method that does not exist on - # a real object. This is generally recommended, and will default to - # `true` in RSpec 4. - mocks.verify_partial_doubles = true - end - - # The settings below are suggested to provide a good initial experience - # with RSpec, but feel free to customize to your heart's content. - - # These two settings work together to allow you to limit a spec run - # to individual examples or groups you care about by tagging them with - # `:focus` metadata. When nothing is tagged with `:focus`, all examples - # get run. - config.filter_run :focus - config.run_all_when_everything_filtered = true - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - # config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # This setting enables warnings. It's recommended, but in some cases may - # be too noisy due to issues in dependencies. - config.warnings = true - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - # config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -end diff --git a/spec/test-app/.gitignore b/spec/test-app/.gitignore deleted file mode 100644 index 050c9d9..0000000 --- a/spec/test-app/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -# See https://help.github.com/articles/ignoring-files for more about ignoring files. -# -# If you find yourself ignoring temporary files generated by your text editor -# or operating system, you probably want to add a global ignore instead: -# git config --global core.excludesfile '~/.gitignore_global' - -# Ignore bundler config. -/.bundle - -# Ignore the default SQLite database. -/db/*.sqlite3 -/db/*.sqlite3-journal - -# Ignore all logfiles and tempfiles. -/log/* -!/log/.keep -/tmp diff --git a/spec/test-app/Gemfile b/spec/test-app/Gemfile deleted file mode 100644 index 7ab0618..0000000 --- a/spec/test-app/Gemfile +++ /dev/null @@ -1,8 +0,0 @@ -source 'https://rubygems.org' - -# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '4.2.5.2' -# Use sqlite3 as the database for Active Record -gem 'sqlite3' - -gem 'fix-db-schema-conflicts', path: '../..' diff --git a/spec/test-app/Gemfile.lock b/spec/test-app/Gemfile.lock deleted file mode 100644 index c0941b9..0000000 --- a/spec/test-app/Gemfile.lock +++ /dev/null @@ -1,125 +0,0 @@ -PATH - remote: ../.. - specs: - fix-db-schema-conflicts (1.2.0) - rubocop (>= 0.36.0) - -GEM - remote: https://rubygems.org/ - specs: - actionmailer (4.2.5.2) - actionpack (= 4.2.5.2) - actionview (= 4.2.5.2) - activejob (= 4.2.5.2) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.5.2) - actionview (= 4.2.5.2) - activesupport (= 4.2.5.2) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.5.2) - activesupport (= 4.2.5.2) - builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (4.2.5.2) - activesupport (= 4.2.5.2) - globalid (>= 0.3.0) - activemodel (4.2.5.2) - activesupport (= 4.2.5.2) - builder (~> 3.1) - activerecord (4.2.5.2) - activemodel (= 4.2.5.2) - activesupport (= 4.2.5.2) - arel (~> 6.0) - activesupport (4.2.5.2) - i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - arel (6.0.3) - ast (2.2.0) - builder (3.2.2) - concurrent-ruby (1.0.1) - erubis (2.7.0) - globalid (0.3.6) - activesupport (>= 4.1.0) - i18n (0.7.0) - json (1.8.3) - loofah (2.0.3) - nokogiri (>= 1.5.9) - mail (2.6.3) - mime-types (>= 1.16, < 3) - mime-types (2.99.1) - mini_portile2 (2.0.0) - minitest (5.8.4) - nokogiri (1.6.7.2) - mini_portile2 (~> 2.0.0.rc2) - parser (2.3.0.6) - ast (~> 2.2) - powerpack (0.1.1) - rack (1.6.4) - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.5.2) - actionmailer (= 4.2.5.2) - actionpack (= 4.2.5.2) - actionview (= 4.2.5.2) - activejob (= 4.2.5.2) - activemodel (= 4.2.5.2) - activerecord (= 4.2.5.2) - activesupport (= 4.2.5.2) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.5.2) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.7) - activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) - rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) - railties (4.2.5.2) - actionpack (= 4.2.5.2) - activesupport (= 4.2.5.2) - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rainbow (2.1.0) - rake (11.1.1) - rubocop (0.38.0) - parser (>= 2.3.0.6, < 3.0) - powerpack (~> 0.1) - rainbow (>= 1.99.1, < 3.0) - ruby-progressbar (~> 1.7) - unicode-display_width (~> 1.0, >= 1.0.1) - ruby-progressbar (1.7.5) - sprockets (3.5.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.0.4) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - sqlite3 (1.3.11) - thor (0.19.1) - thread_safe (0.3.5) - tzinfo (1.2.2) - thread_safe (~> 0.1) - unicode-display_width (1.0.2) - -PLATFORMS - ruby - -DEPENDENCIES - fix-db-schema-conflicts! - rails (= 4.2.5.2) - sqlite3 - -BUNDLED WITH - 1.10.6 diff --git a/spec/test-app/README.rdoc b/spec/test-app/README.rdoc deleted file mode 100644 index dd4e97e..0000000 --- a/spec/test-app/README.rdoc +++ /dev/null @@ -1,28 +0,0 @@ -== README - -This README would normally document whatever steps are necessary to get the -application up and running. - -Things you may want to cover: - -* Ruby version - -* System dependencies - -* Configuration - -* Database creation - -* Database initialization - -* How to run the test suite - -* Services (job queues, cache servers, search engines, etc.) - -* Deployment instructions - -* ... - - -Please feel free to use a different markup language if you do not plan to run -rake doc:app. diff --git a/spec/test-app/Rakefile b/spec/test-app/Rakefile deleted file mode 100644 index ba6b733..0000000 --- a/spec/test-app/Rakefile +++ /dev/null @@ -1,6 +0,0 @@ -# Add your own tasks in files placed in lib/tasks ending in .rake, -# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. - -require File.expand_path('../config/application', __FILE__) - -Rails.application.load_tasks diff --git a/spec/test-app/app/assets/config/manifest.js b/spec/test-app/app/assets/config/manifest.js deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/app/assets/images/.keep b/spec/test-app/app/assets/images/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/app/assets/javascripts/application.js b/spec/test-app/app/assets/javascripts/application.js deleted file mode 100644 index e07c5a8..0000000 --- a/spec/test-app/app/assets/javascripts/application.js +++ /dev/null @@ -1,16 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. -// -// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details -// about supported directives. -// -//= require jquery -//= require jquery_ujs -//= require turbolinks -//= require_tree . diff --git a/spec/test-app/app/assets/stylesheets/application.css b/spec/test-app/app/assets/stylesheets/application.css deleted file mode 100644 index f9cd5b3..0000000 --- a/spec/test-app/app/assets/stylesheets/application.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any styles - * defined in the other CSS/SCSS files in this directory. It is generally better to create a new - * file per style scope. - * - *= require_tree . - *= require_self - */ diff --git a/spec/test-app/app/controllers/application_controller.rb b/spec/test-app/app/controllers/application_controller.rb deleted file mode 100644 index d83690e..0000000 --- a/spec/test-app/app/controllers/application_controller.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ApplicationController < ActionController::Base - # Prevent CSRF attacks by raising an exception. - # For APIs, you may want to use :null_session instead. - protect_from_forgery with: :exception -end diff --git a/spec/test-app/app/controllers/concerns/.keep b/spec/test-app/app/controllers/concerns/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/app/helpers/application_helper.rb b/spec/test-app/app/helpers/application_helper.rb deleted file mode 100644 index de6be79..0000000 --- a/spec/test-app/app/helpers/application_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module ApplicationHelper -end diff --git a/spec/test-app/app/mailers/.keep b/spec/test-app/app/mailers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/app/models/.keep b/spec/test-app/app/models/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/app/models/company.rb b/spec/test-app/app/models/company.rb deleted file mode 100644 index 4ac174e..0000000 --- a/spec/test-app/app/models/company.rb +++ /dev/null @@ -1,2 +0,0 @@ -class Company < ActiveRecord::Base -end diff --git a/spec/test-app/app/models/concerns/.keep b/spec/test-app/app/models/concerns/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/app/models/person.rb b/spec/test-app/app/models/person.rb deleted file mode 100644 index 2f2e286..0000000 --- a/spec/test-app/app/models/person.rb +++ /dev/null @@ -1,2 +0,0 @@ -class Person < ActiveRecord::Base -end diff --git a/spec/test-app/app/views/layouts/application.html.erb b/spec/test-app/app/views/layouts/application.html.erb deleted file mode 100644 index 797902d..0000000 --- a/spec/test-app/app/views/layouts/application.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - - - TestApp - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> - <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> - <%= csrf_meta_tags %> - - - -<%= yield %> - - - diff --git a/spec/test-app/bin/bundle b/spec/test-app/bin/bundle deleted file mode 100755 index 66e9889..0000000 --- a/spec/test-app/bin/bundle +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -load Gem.bin_path('bundler', 'bundle') diff --git a/spec/test-app/bin/rails b/spec/test-app/bin/rails deleted file mode 100755 index 0138d79..0000000 --- a/spec/test-app/bin/rails +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -APP_PATH = File.expand_path('../../config/application', __FILE__) -require_relative '../config/boot' -require 'rails/commands' diff --git a/spec/test-app/bin/rake b/spec/test-app/bin/rake deleted file mode 100755 index d87d5f5..0000000 --- a/spec/test-app/bin/rake +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -require_relative '../config/boot' -require 'rake' -Rake.application.run diff --git a/spec/test-app/bin/setup b/spec/test-app/bin/setup deleted file mode 100755 index acdb2c1..0000000 --- a/spec/test-app/bin/setup +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env ruby -require 'pathname' - -# path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) - -Dir.chdir APP_ROOT do - # This script is a starting point to setup your application. - # Add necessary setup steps to this file: - - puts "== Installing dependencies ==" - system "gem install bundler --conservative" - system "bundle check || bundle install" - - # puts "\n== Copying sample files ==" - # unless File.exist?("config/database.yml") - # system "cp config/database.yml.sample config/database.yml" - # end - - puts "\n== Preparing database ==" - system "bin/rake db:setup" - - puts "\n== Removing old logs and tempfiles ==" - system "rm -f log/*" - system "rm -rf tmp/cache" - - puts "\n== Restarting application server ==" - system "touch tmp/restart.txt" -end diff --git a/spec/test-app/bin/spring b/spec/test-app/bin/spring deleted file mode 100755 index 7fe232c..0000000 --- a/spec/test-app/bin/spring +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env ruby - -# This file loads spring without using Bundler, in order to be fast. -# It gets overwritten when you run the `spring binstub` command. - -unless defined?(Spring) - require 'rubygems' - require 'bundler' - - if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) - Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) } - gem 'spring', match[1] - require 'spring/binstub' - end -end diff --git a/spec/test-app/config.ru b/spec/test-app/config.ru deleted file mode 100644 index bd83b25..0000000 --- a/spec/test-app/config.ru +++ /dev/null @@ -1,4 +0,0 @@ -# This file is used by Rack-based servers to start the application. - -require ::File.expand_path('../config/environment', __FILE__) -run Rails.application diff --git a/spec/test-app/config/application.rb b/spec/test-app/config/application.rb deleted file mode 100644 index bb2521d..0000000 --- a/spec/test-app/config/application.rb +++ /dev/null @@ -1,26 +0,0 @@ -require File.expand_path('../boot', __FILE__) - -require 'rails/all' - -# Require the gems listed in Gemfile, including any gems -# you've limited to :test, :development, or :production. -Bundler.require(*Rails.groups) - -module TestApp - class Application < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de - - # Do not swallow errors in after_commit/after_rollback callbacks. - config.active_record.raise_in_transactional_callbacks = true - end -end diff --git a/spec/test-app/config/boot.rb b/spec/test-app/config/boot.rb deleted file mode 100644 index 6b750f0..0000000 --- a/spec/test-app/config/boot.rb +++ /dev/null @@ -1,3 +0,0 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) - -require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/spec/test-app/config/database.yml b/spec/test-app/config/database.yml deleted file mode 100644 index 1c1a37c..0000000 --- a/spec/test-app/config/database.yml +++ /dev/null @@ -1,25 +0,0 @@ -# SQLite version 3.x -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem 'sqlite3' -# -default: &default - adapter: sqlite3 - pool: 5 - timeout: 5000 - -development: - <<: *default - database: db/development.sqlite3 - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. -test: - <<: *default - database: db/test.sqlite3 - -production: - <<: *default - database: db/production.sqlite3 diff --git a/spec/test-app/config/environment.rb b/spec/test-app/config/environment.rb deleted file mode 100644 index ee8d90d..0000000 --- a/spec/test-app/config/environment.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Load the Rails application. -require File.expand_path('../application', __FILE__) - -# Initialize the Rails application. -Rails.application.initialize! diff --git a/spec/test-app/config/environments/development.rb b/spec/test-app/config/environments/development.rb deleted file mode 100644 index b55e214..0000000 --- a/spec/test-app/config/environments/development.rb +++ /dev/null @@ -1,41 +0,0 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. - - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development - # since you don't have to restart the web server when you make code changes. - config.cache_classes = false - - # Do not eager load code on boot. - config.eager_load = false - - # Show full error reports and disable caching. - config.consider_all_requests_local = true - config.action_controller.perform_caching = false - - # Don't care if the mailer can't send. - config.action_mailer.raise_delivery_errors = false - - # Print deprecation notices to the Rails logger. - config.active_support.deprecation = :log - - # Raise an error on page load if there are pending migrations. - config.active_record.migration_error = :page_load - - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true - - # Asset digests allow you to set far-future HTTP expiration dates on all assets, - # yet still be able to expire them through the digest params. - config.assets.digest = true - - # Adds additional error checking when serving assets at runtime. - # Checks for improperly declared sprockets dependencies. - # Raises helpful error messages. - config.assets.raise_runtime_errors = true - - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true -end diff --git a/spec/test-app/config/environments/production.rb b/spec/test-app/config/environments/production.rb deleted file mode 100644 index 5c1b32e..0000000 --- a/spec/test-app/config/environments/production.rb +++ /dev/null @@ -1,79 +0,0 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. - - # Code is not reloaded between requests. - config.cache_classes = true - - # Eager load code on boot. This eager loads most of Rails and - # your application in memory, allowing both threaded web servers - # and those relying on copy on write to perform better. - # Rake tasks automatically ignore this option for performance. - config.eager_load = true - - # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false - config.action_controller.perform_caching = true - - # Enable Rack::Cache to put a simple HTTP cache in front of your application - # Add `rack-cache` to your Gemfile before enabling this. - # For large-scale production use, consider using a caching reverse proxy like - # NGINX, varnish or squid. - # config.action_dispatch.rack_cache = true - - # Disable serving static files from the `/public` folder by default since - # Apache or NGINX already handles this. - config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? - - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier - # config.assets.css_compressor = :sass - - # Do not fallback to assets pipeline if a precompiled asset is missed. - config.assets.compile = false - - # Asset digests allow you to set far-future HTTP expiration dates on all assets, - # yet still be able to expire them through the digest params. - config.assets.digest = true - - # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb - - # Specifies the header that your server uses for sending files. - # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX - - # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true - - # Use the lowest log level to ensure availability of diagnostic information - # when problems arise. - config.log_level = :debug - - # Prepend all log lines with the following tags. - # config.log_tags = [ :subdomain, :uuid ] - - # Use a different logger for distributed setups. - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) - - # Use a different cache store in production. - # config.cache_store = :mem_cache_store - - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' - - # Ignore bad email addresses and do not raise email delivery errors. - # Set this to true and configure the email server for immediate delivery to raise delivery errors. - # config.action_mailer.raise_delivery_errors = false - - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation cannot be found). - config.i18n.fallbacks = true - - # Send deprecation notices to registered listeners. - config.active_support.deprecation = :notify - - # Use default logging formatter so that PID and timestamp are not suppressed. - config.log_formatter = ::Logger::Formatter.new - - # Do not dump schema after migrations. - config.active_record.dump_schema_after_migration = false -end diff --git a/spec/test-app/config/environments/test.rb b/spec/test-app/config/environments/test.rb deleted file mode 100644 index 1c19f08..0000000 --- a/spec/test-app/config/environments/test.rb +++ /dev/null @@ -1,42 +0,0 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. - - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true - - # Do not eager load code on boot. This avoids loading your whole application - # just for the purpose of running a single test. If you are using a tool that - # preloads Rails for running tests, you may have to set it to true. - config.eager_load = false - - # Configure static file server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' - - # Show full error reports and disable caching. - config.consider_all_requests_local = true - config.action_controller.perform_caching = false - - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false - - # Disable request forgery protection in test environment. - config.action_controller.allow_forgery_protection = false - - # Tell Action Mailer not to deliver emails to the real world. - # The :test delivery method accumulates sent emails in the - # ActionMailer::Base.deliveries array. - config.action_mailer.delivery_method = :test - - # Randomize the order test cases are executed. - config.active_support.test_order = :random - - # Print deprecation notices to the stderr. - config.active_support.deprecation = :stderr - - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true -end diff --git a/spec/test-app/config/initializers/assets.rb b/spec/test-app/config/initializers/assets.rb deleted file mode 100644 index 01ef3e6..0000000 --- a/spec/test-app/config/initializers/assets.rb +++ /dev/null @@ -1,11 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' - -# Add additional assets to the asset load path -# Rails.application.config.assets.paths << Emoji.images_path - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/spec/test-app/config/initializers/backtrace_silencers.rb b/spec/test-app/config/initializers/backtrace_silencers.rb deleted file mode 100644 index 59385cd..0000000 --- a/spec/test-app/config/initializers/backtrace_silencers.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } - -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers! diff --git a/spec/test-app/config/initializers/cookies_serializer.rb b/spec/test-app/config/initializers/cookies_serializer.rb deleted file mode 100644 index 7f70458..0000000 --- a/spec/test-app/config/initializers/cookies_serializer.rb +++ /dev/null @@ -1,3 +0,0 @@ -# Be sure to restart your server when you modify this file. - -Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/spec/test-app/config/initializers/filter_parameter_logging.rb b/spec/test-app/config/initializers/filter_parameter_logging.rb deleted file mode 100644 index 4a994e1..0000000 --- a/spec/test-app/config/initializers/filter_parameter_logging.rb +++ /dev/null @@ -1,4 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password] diff --git a/spec/test-app/config/initializers/inflections.rb b/spec/test-app/config/initializers/inflections.rb deleted file mode 100644 index ac033bf..0000000 --- a/spec/test-app/config/initializers/inflections.rb +++ /dev/null @@ -1,16 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new inflection rules using the following format. Inflections -# are locale specific, and you may define rules for as many different -# locales as you wish. All of these examples are active by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' -# inflect.uncountable %w( fish sheep ) -# end - -# These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' -# end diff --git a/spec/test-app/config/initializers/mime_types.rb b/spec/test-app/config/initializers/mime_types.rb deleted file mode 100644 index dc18996..0000000 --- a/spec/test-app/config/initializers/mime_types.rb +++ /dev/null @@ -1,4 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new mime types for use in respond_to blocks: -# Mime::Type.register "text/richtext", :rtf diff --git a/spec/test-app/config/initializers/session_store.rb b/spec/test-app/config/initializers/session_store.rb deleted file mode 100644 index f7a5e72..0000000 --- a/spec/test-app/config/initializers/session_store.rb +++ /dev/null @@ -1,3 +0,0 @@ -# Be sure to restart your server when you modify this file. - -Rails.application.config.session_store :cookie_store, key: '_test-app_session' diff --git a/spec/test-app/config/initializers/wrap_parameters.rb b/spec/test-app/config/initializers/wrap_parameters.rb deleted file mode 100644 index 33725e9..0000000 --- a/spec/test-app/config/initializers/wrap_parameters.rb +++ /dev/null @@ -1,14 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# This file contains settings for ActionController::ParamsWrapper which -# is enabled by default. - -# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. -ActiveSupport.on_load(:action_controller) do - wrap_parameters format: [:json] if respond_to?(:wrap_parameters) -end - -# To enable root element in JSON for ActiveRecord objects. -# ActiveSupport.on_load(:active_record) do -# self.include_root_in_json = true -# end diff --git a/spec/test-app/config/locales/en.yml b/spec/test-app/config/locales/en.yml deleted file mode 100644 index 0653957..0000000 --- a/spec/test-app/config/locales/en.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Files in the config/locales directory are used for internationalization -# and are automatically loaded by Rails. If you want to use locales other -# than English, add the necessary files in this directory. -# -# To use the locales, use `I18n.t`: -# -# I18n.t 'hello' -# -# In views, this is aliased to just `t`: -# -# <%= t('hello') %> -# -# To use a different locale, set it with `I18n.locale`: -# -# I18n.locale = :es -# -# This would use the information in config/locales/es.yml. -# -# To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. - -en: - hello: "Hello world" diff --git a/spec/test-app/config/routes.rb b/spec/test-app/config/routes.rb deleted file mode 100644 index 3f66539..0000000 --- a/spec/test-app/config/routes.rb +++ /dev/null @@ -1,56 +0,0 @@ -Rails.application.routes.draw do - # The priority is based upon order of creation: first created -> highest priority. - # See how all your routes lay out with "rake routes". - - # You can have the root of your site routed with "root" - # root 'welcome#index' - - # Example of regular route: - # get 'products/:id' => 'catalog#view' - - # Example of named route that can be invoked with purchase_url(id: product.id) - # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase - - # Example resource route (maps HTTP verbs to controller actions automatically): - # resources :products - - # Example resource route with options: - # resources :products do - # member do - # get 'short' - # post 'toggle' - # end - # - # collection do - # get 'sold' - # end - # end - - # Example resource route with sub-resources: - # resources :products do - # resources :comments, :sales - # resource :seller - # end - - # Example resource route with more complex sub-resources: - # resources :products do - # resources :comments - # resources :sales do - # get 'recent', on: :collection - # end - # end - - # Example resource route with concerns: - # concern :toggleable do - # post 'toggle' - # end - # resources :posts, concerns: :toggleable - # resources :photos, concerns: :toggleable - - # Example resource route within a namespace: - # namespace :admin do - # # Directs /admin/products/* to Admin::ProductsController - # # (app/controllers/admin/products_controller.rb) - # resources :products - # end -end diff --git a/spec/test-app/config/secrets.yml b/spec/test-app/config/secrets.yml deleted file mode 100644 index 610a74a..0000000 --- a/spec/test-app/config/secrets.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Your secret key is used for verifying the integrity of signed cookies. -# If you change this key, all old signed cookies will become invalid! - -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -# You can use `rake secret` to generate a secure secret key. - -# Make sure the secrets in this file are kept private -# if you're sharing your code publicly. - -development: - secret_key_base: 42f1f3aadb7149074086ad031755d0cec758b41cf5cb06ea0494ff3be4c308769bfccf9a31bbdd27641630c10a48e4bb4cfffd8aacaf66dd7db0d8336f909721 - -test: - secret_key_base: b090287580ff0ffd7955f76626eea0a64a9e0d3a02352abfadf99e4fcfca5097fe3c7d28426bcf50bf73621ac24eec0bfc8268d61e0d6c3ff51f7ea19bd1f23b - -# Do not keep production secrets in the repository, -# instead read values from the environment. -production: - secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/spec/test-app/db/migrate/20160322223225_create_people.rb b/spec/test-app/db/migrate/20160322223225_create_people.rb deleted file mode 100644 index 74ab5a3..0000000 --- a/spec/test-app/db/migrate/20160322223225_create_people.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreatePeople < ActiveRecord::Migration - def change - create_table :people do |t| - t.string :first_name - t.string :last_name - t.integer :age - t.date :birthdate - - t.timestamps null: false - end - end -end diff --git a/spec/test-app/db/migrate/20160322223258_create_companies.rb b/spec/test-app/db/migrate/20160322223258_create_companies.rb deleted file mode 100644 index b3d0de0..0000000 --- a/spec/test-app/db/migrate/20160322223258_create_companies.rb +++ /dev/null @@ -1,19 +0,0 @@ -class CreateCompanies < ActiveRecord::Migration - def change - create_table :companies do |t| - t.string :name - t.string :addr1 - t.string :addr2 - t.string :city - t.string :state - t.string :zip - t.string :phone - - t.timestamps null: false - end - - add_index :companies, :name - add_index :companies, :city - add_index :companies, :state - end -end diff --git a/spec/test-app/db/schema.rb b/spec/test-app/db/schema.rb deleted file mode 100644 index d1311a0..0000000 --- a/spec/test-app/db/schema.rb +++ /dev/null @@ -1,38 +0,0 @@ -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 20160322223258) do - create_table "companies", force: :cascade do |t| - t.string "addr1" - t.string "addr2" - t.string "city" - t.datetime "created_at", null: false - t.string "name" - t.string "phone" - t.string "state" - t.datetime "updated_at", null: false - t.string "zip" - end - - add_index "companies", ["city"], name: "index_companies_on_city" - add_index "companies", ["name"], name: "index_companies_on_name" - add_index "companies", ["state"], name: "index_companies_on_state" - - create_table "people", force: :cascade do |t| - t.integer "age" - t.date "birthdate" - t.datetime "created_at", null: false - t.string "first_name" - t.string "last_name" - t.datetime "updated_at", null: false - end -end diff --git a/spec/test-app/db/seeds.rb b/spec/test-app/db/seeds.rb deleted file mode 100644 index 4edb1e8..0000000 --- a/spec/test-app/db/seeds.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). -# -# Examples: -# -# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) -# Mayor.create(name: 'Emanuel', city: cities.first) diff --git a/spec/test-app/lib/assets/.keep b/spec/test-app/lib/assets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/lib/tasks/.keep b/spec/test-app/lib/tasks/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/log/.keep b/spec/test-app/log/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/public/404.html b/spec/test-app/public/404.html deleted file mode 100644 index b612547..0000000 --- a/spec/test-app/public/404.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - The page you were looking for doesn't exist (404) - - - - - - -
-
-

The page you were looking for doesn't exist.

-

You may have mistyped the address or the page may have moved.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/spec/test-app/public/422.html b/spec/test-app/public/422.html deleted file mode 100644 index a21f82b..0000000 --- a/spec/test-app/public/422.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - The change you wanted was rejected (422) - - - - - - -
-
-

The change you wanted was rejected.

-

Maybe you tried to change something you didn't have access to.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/spec/test-app/public/500.html b/spec/test-app/public/500.html deleted file mode 100644 index 061abc5..0000000 --- a/spec/test-app/public/500.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - We're sorry, but something went wrong (500) - - - - - - -
-
-

We're sorry, but something went wrong.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/spec/test-app/public/favicon.ico b/spec/test-app/public/favicon.ico deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/public/robots.txt b/spec/test-app/public/robots.txt deleted file mode 100644 index 3c9c7c0..0000000 --- a/spec/test-app/public/robots.txt +++ /dev/null @@ -1,5 +0,0 @@ -# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file -# -# To ban all spiders from the entire site uncomment the next two lines: -# User-agent: * -# Disallow: / diff --git a/spec/test-app/test/controllers/.keep b/spec/test-app/test/controllers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/test/fixtures/.keep b/spec/test-app/test/fixtures/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/test/fixtures/companies.yml b/spec/test-app/test/fixtures/companies.yml deleted file mode 100644 index b4147d1..0000000 --- a/spec/test-app/test/fixtures/companies.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -one: - name: MyString - addr1: MyString - addr2: MyString - city: MyString - state: MyString - zip: MyString - phone: MyString - -two: - name: MyString - addr1: MyString - addr2: MyString - city: MyString - state: MyString - zip: MyString - phone: MyString diff --git a/spec/test-app/test/fixtures/people.yml b/spec/test-app/test/fixtures/people.yml deleted file mode 100644 index 21be9fc..0000000 --- a/spec/test-app/test/fixtures/people.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -one: - first_name: MyString - last_name: MyString - age: 1 - birthdate: 2016-03-22 - -two: - first_name: MyString - last_name: MyString - age: 1 - birthdate: 2016-03-22 diff --git a/spec/test-app/test/helpers/.keep b/spec/test-app/test/helpers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/test/integration/.keep b/spec/test-app/test/integration/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/test/mailers/.keep b/spec/test-app/test/mailers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/test/models/.keep b/spec/test-app/test/models/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/test/models/company_test.rb b/spec/test-app/test/models/company_test.rb deleted file mode 100644 index 492faef..0000000 --- a/spec/test-app/test/models/company_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'test_helper' - -class CompanyTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/spec/test-app/test/models/person_test.rb b/spec/test-app/test/models/person_test.rb deleted file mode 100644 index ad04ed8..0000000 --- a/spec/test-app/test/models/person_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'test_helper' - -class PersonTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/spec/test-app/test/test_helper.rb b/spec/test-app/test/test_helper.rb deleted file mode 100644 index 92e39b2..0000000 --- a/spec/test-app/test/test_helper.rb +++ /dev/null @@ -1,10 +0,0 @@ -ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../../config/environment', __FILE__) -require 'rails/test_help' - -class ActiveSupport::TestCase - # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. - fixtures :all - - # Add more helper methods to be used by all tests here... -end diff --git a/spec/test-app/vendor/assets/javascripts/.keep b/spec/test-app/vendor/assets/javascripts/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/test-app/vendor/assets/stylesheets/.keep b/spec/test-app/vendor/assets/stylesheets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/spec/unit/autocorrect_configuration_spec.rb b/spec/unit/autocorrect_configuration_spec.rb deleted file mode 100644 index c91bfa8..0000000 --- a/spec/unit/autocorrect_configuration_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper' -require 'fix_db_schema_conflicts/autocorrect_configuration' - -RSpec.describe FixDBSchemaConflicts::AutocorrectConfiguration do - subject(:autocorrect_config) { described_class } - - it 'for versions up to 0.49.0' do - installed_rubocop(version: '0.39.0') - - expect(autocorrect_config.load).to eq('.rubocop_schema.yml') - end - - it 'for versions 0.49.0 and above' do - installed_rubocop(version: '0.49.0') - - expect(autocorrect_config.load).to eq('.rubocop_schema.49.yml') - end - - it 'for versions 0.53.0 and above' do - installed_rubocop(version: '0.53.0') - - expect(autocorrect_config.load).to eq('.rubocop_schema.53.yml') - end - - it 'for versions 0.77.0 and above' do - installed_rubocop(version: '0.77.0') - - expect(autocorrect_config.load).to eq('.rubocop_schema.77.yml') - end - - def installed_rubocop(version:) - allow(Gem).to receive_message_chain(:loaded_specs, :[], :version) - .and_return(Gem::Version.new(version)) - end -end From 49ff72529854c950b2fdc500c3173e1e2028f7c8 Mon Sep 17 00:00:00 2001 From: Oxyless Date: Mon, 2 Dec 2024 17:36:53 +0100 Subject: [PATCH 02/12] Rails 7 portability --- lib/fix_db_schema_conflicts/schema_dumper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fix_db_schema_conflicts/schema_dumper.rb b/lib/fix_db_schema_conflicts/schema_dumper.rb index 1965a6f..a764b2f 100644 --- a/lib/fix_db_schema_conflicts/schema_dumper.rb +++ b/lib/fix_db_schema_conflicts/schema_dumper.rb @@ -33,7 +33,7 @@ def tables(stream) "#{Rails.root}/db/specific.rb" end - if File.exists?(specific) + if File.exist?(specific) stream.puts("\t" + File.read(specific).gsub("\n", "\n\t") + "\n\n") end From 697770555d1405cd5047b6bb48fc7764bed1515a Mon Sep 17 00:00:00 2001 From: agultekin Date: Tue, 24 Dec 2024 15:49:16 +0100 Subject: [PATCH 03/12] First commit --- lib/fix_db_schema_conflicts/schema_dumper.rb | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/fix_db_schema_conflicts/schema_dumper.rb b/lib/fix_db_schema_conflicts/schema_dumper.rb index a764b2f..21ff2ec 100644 --- a/lib/fix_db_schema_conflicts/schema_dumper.rb +++ b/lib/fix_db_schema_conflicts/schema_dumper.rb @@ -18,6 +18,11 @@ def indexes(table) def foreign_keys(table) __getobj__.indexes(table).sort_by(&:name) end + + def triggers(trigger) + puts "triggers in class" + __getobj__.triggers(trigger).sort_by(&:name) + end end def extensions(*args) @@ -40,12 +45,34 @@ def tables(stream) super(stream) end + def triggers(stream) + triggers = ENV['SCHEMA'] || if defined? ActiveRecord::Tasks::DatabaseTasks + File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'triggers.rb') + else + "#{Rails.root}/db/triggers.rb" + end + + if File.exist?(triggers) + stream.puts("\t" + File.read(triggers).gsub("\n", "\n\t") + "\n\n") + end + + super(stream) + end + def table(*args) with_sorting do super(*args) end end + def trigger(*args) + puts "trigger" + puts args + with_sorting do + super(*args) + end + end + def with_sorting old, @connection = @connection, ConnectionWithSorting.new(@connection) result = yield From 544f55d930530678ded3c8b872265392d82dcc71 Mon Sep 17 00:00:00 2001 From: agultekin Date: Tue, 24 Dec 2024 16:06:07 +0100 Subject: [PATCH 04/12] trying to access to triggers --- lib/fix_db_schema_conflicts/schema_dumper.rb | 25 ++++---------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/lib/fix_db_schema_conflicts/schema_dumper.rb b/lib/fix_db_schema_conflicts/schema_dumper.rb index 21ff2ec..3581018 100644 --- a/lib/fix_db_schema_conflicts/schema_dumper.rb +++ b/lib/fix_db_schema_conflicts/schema_dumper.rb @@ -19,9 +19,9 @@ def foreign_keys(table) __getobj__.indexes(table).sort_by(&:name) end - def triggers(trigger) - puts "triggers in class" - __getobj__.triggers(trigger).sort_by(&:name) + def triggers(table) + puts "called triggers" + __getobj__.triggers(table).sort_by(&:name) end end @@ -45,29 +45,14 @@ def tables(stream) super(stream) end - def triggers(stream) - triggers = ENV['SCHEMA'] || if defined? ActiveRecord::Tasks::DatabaseTasks - File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'triggers.rb') - else - "#{Rails.root}/db/triggers.rb" - end - - if File.exist?(triggers) - stream.puts("\t" + File.read(triggers).gsub("\n", "\n\t") + "\n\n") - end - - super(stream) - end - def table(*args) with_sorting do super(*args) end end - def trigger(*args) - puts "trigger" - puts args + def triggers(*args) + puts "main triggers" with_sorting do super(*args) end From ff3245ba19bc781d054d5b6990a76921e6f4bf3e Mon Sep 17 00:00:00 2001 From: agultekin Date: Mon, 30 Dec 2024 16:25:31 +0100 Subject: [PATCH 05/12] - Adding trigger extractor - Adding pg functions extractor - Adding pg types extractors --- Gemfile | 1 + .../postgres_details_extractor.rb | 91 +++++++++++++++++++ .../postgres_schema_info_extractor.rb | 86 ++++++++++++++++++ lib/fix_db_schema_conflicts/schema_dumper.rb | 78 ++++++++++++---- .../triggers_operations.rb | 46 ++++++++++ 5 files changed, 283 insertions(+), 19 deletions(-) create mode 100644 lib/fix_db_schema_conflicts/postgres_details_extractor.rb create mode 100644 lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb create mode 100644 lib/fix_db_schema_conflicts/triggers_operations.rb diff --git a/Gemfile b/Gemfile index af743cd..d67c727 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,4 @@ source 'https://rubygems.org' # Specify your gem's dependencies in fix-db-schema-conflicts.gemspec gemspec +gem "pg" diff --git a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb new file mode 100644 index 0000000..8818e5e --- /dev/null +++ b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +module FixDBSchemaConflicts + class PostgresDetailsExtractor + def initialize(connection) + @connection = connection + @pg_enum_types = @connection.fetch_enum_types + @pg_functions = @connection.pg_functions + @pg_fts_configurations = @connection.fts_configurations + end + + def create_types(stream) + stream.puts(" execute <<-SQL") + @pg_enum_types.each do |enum| + stream.puts "DO $$ BEGIN " \ + "IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '#{enum.name}') THEN " \ + "CREATE TYPE #{enum.name} AS ENUM (#{enum.enum_values}); " \ + "END IF; " \ + "END $$;" + end + + if @pg_composite_types.present? + @pg_composite_types.each do |composite| + stream.puts "DO $$ BEGIN " \ + "IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '#{composite.name}') THEN " \ + "CREATE TYPE #{composite.name} AS (#{composite.attributes}); " \ + "END IF; " \ + "END $$;" + end + end + stream.puts(" SQL") + end + + def create_functions(stream) + @pg_functions.each do |row| + # Extract function components + function_name = row.name + arguments = row.arguments + return_type = row.return_type + language_name = row.language_name + + # Ensure function body doesn't have trailing semicolons + function_body = row.body.strip.sub(/;+\z/, '') + + # Check if the function body starts with 'BEGIN' + starts_with_begin = function_body.match?(/^\s*BEGIN/i) + + # Handle functions correctly based on whether they require a procedural block + if starts_with_begin + # PL/pgSQL function with BEGIN...END already in the body + stream.write(<<~SQL) + execute <<~EOSQL + CREATE OR REPLACE FUNCTION #{function_name}(#{arguments}) + RETURNS #{return_type} AS $$ + #{function_body}; + $$ LANGUAGE #{language_name} #{row.volatility}; + EOSQL + SQL + + else + # Add BEGIN...END for procedural logic + stream.write(<<~SQL) + execute <<~EOSQL + CREATE OR REPLACE FUNCTION #{function_name}(#{arguments}) + RETURNS #{return_type} AS $$ + BEGIN + #{function_body}; + END; + $$ LANGUAGE plpgsql #{row.volatility}; + EOSQL + SQL + end + + end + end + + def create_fts_configurations(stream) + unless @pg_fts_configurations.empty? + stream.puts(" execute <<-SQL") + @pg_fts_configurations.each do |fts_configuration| + stream.puts "DO $$ BEGIN " \ + "IF NOT EXISTS (SELECT 1 FROM pg_ts_config WHERE cfgname = '#{fts_configuration.name}') THEN " \ + "CREATE TEXT SEARCH CONFIGURATION #{fts_configuration.name} (COPY = simple); " \ + "END IF; " \ + "END $$;" + end + stream.puts(" SQL") + end + end + end +end diff --git a/lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb b/lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb new file mode 100644 index 0000000..5e11900 --- /dev/null +++ b/lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true +require 'delegate' +require 'fix-db-schema-conflicts' +require 'rails' + +module FixDBSchemaConflicts + class PostgresSchemaInfoExtractor + def initialize(connection) + @connection = connection + end + + def pg_functions + query = <<-SQL + SELECT + proname AS function_name, + pg_get_function_arguments(pg_proc.oid) AS arguments, + pg_get_function_result(pg_proc.oid) AS return_type, + CASE + WHEN prosrc IS NOT NULL THEN prosrc + ELSE 'Invalid Function Body' + END AS function_body, + CASE provolatile + WHEN 'i' THEN 'IMMUTABLE' + WHEN 's' THEN 'STABLE' + WHEN 'v' THEN 'VOLATILE' + ELSE 'UNKNOWN' + END AS volatility, + pg_language.lanname AS language_name + FROM pg_proc + JOIN pg_namespace ON pg_namespace.oid = pg_proc.pronamespace + JOIN pg_language ON pg_language.oid = pg_proc.prolang + WHERE pg_language.lanname IN ('sql', 'plpgsql') + AND pg_namespace.nspname NOT IN ('pg_catalog', 'information_schema') + AND proname NOT LIKE 'pg_%' + ORDER BY function_name; + SQL + + @connection.execute(query).map do |row| + OpenStruct.new( + name: row['function_name'], + arguments: row['arguments'], + return_type: row['return_type'], + body: row['function_body'], + volatility: row['volatility'], + language_name: row['language_name'] + ) + end + end + + def fetch_enum_types + query = <<-SQL + SELECT t.typname AS type_name, + string_agg(quote_literal(e.enumlabel), ', ') AS enum_values + FROM pg_type t + JOIN pg_enum e ON t.oid = e.enumtypid + WHERE t.typcategory = 'E' + GROUP BY t.typname; + SQL + + @connection.execute(query).map do |row| + OpenStruct.new( + name: row['type_name'], + enum_values: row['enum_values'] + ) + end + end + + def fts_configurations + query = <<-SQL + SELECT + nspname AS schema_name, + cfgname AS configuration_name + FROM + pg_ts_config + JOIN + pg_namespace ON pg_ts_config.cfgnamespace = pg_namespace.oid + ORDER BY + schema_name, configuration_name; + SQL + + @connection.execute(query).map do |row| + OpenStruct.new(schema: row['schema_name'], name: row['configuration_name']) + end + end + end +end diff --git a/lib/fix_db_schema_conflicts/schema_dumper.rb b/lib/fix_db_schema_conflicts/schema_dumper.rb index 3581018..2760773 100644 --- a/lib/fix_db_schema_conflicts/schema_dumper.rb +++ b/lib/fix_db_schema_conflicts/schema_dumper.rb @@ -1,8 +1,16 @@ require 'delegate' +require_relative 'postgres_schema_info_extractor' +require 'fix_db_schema_conflicts/triggers_operations' +require 'fix_db_schema_conflicts/postgres_details_extractor' module FixDBSchemaConflicts module SchemaDumper class ConnectionWithSorting < SimpleDelegator + def initialize(connection) + super(connection) + @schema_info_extractor = FixDBSchemaConflicts::PostgresSchemaInfoExtractor.new(__getobj__) + end + def extensions __getobj__.extensions.sort end @@ -16,12 +24,36 @@ def indexes(table) end def foreign_keys(table) - __getobj__.indexes(table).sort_by(&:name) + __getobj__.foreign_keys(table).sort_by(&:name) + end + + def pg_functions + @schema_info_extractor.pg_functions + end + + def fetch_enum_types + @schema_info_extractor.fetch_enum_types end def triggers(table) - puts "called triggers" - __getobj__.triggers(table).sort_by(&:name) + query = <<-SQL + SELECT tgname AS name, pg_get_triggerdef(oid) AS definition + FROM pg_trigger + WHERE tgrelid = '#{table}'::regclass AND NOT tgisinternal; + SQL + + __getobj__.execute(query).map do |row| + sanitized_sql = sanitize_trigger_definition(row['definition']) + OpenStruct.new(name: row['name'], definition: sanitized_sql) + end + end + + def sanitize_trigger_definition(definition) + definition.gsub(/ON\s+(\w+\.)?(\w+\.)?/, 'ON ') + end + + def fts_configurations + @schema_info_extractor.fts_configurations end end @@ -33,36 +65,44 @@ def extensions(*args) def tables(stream) specific = ENV['SCHEMA'] || if defined? ActiveRecord::Tasks::DatabaseTasks - File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'specific.rb') - else - "#{Rails.root}/db/specific.rb" - end + File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'specific.rb') + else + "#{Rails.root}/db/specific.rb" + end if File.exist?(specific) stream.puts("\t" + File.read(specific).gsub("\n", "\n\t") + "\n\n") end - super(stream) - end - - def table(*args) with_sorting do - super(*args) + @details_operations = FixDBSchemaConflicts::PostgresDetailsExtractor.new(@connection) + @details_operations.create_types(stream) + @details_operations.create_functions(stream) + @details_operations.create_fts_configurations(stream) end + super(stream) end - def triggers(*args) - puts "main triggers" + def table(table_name, stream, *args) with_sorting do - super(*args) + super(table_name, stream, *args) + + if @triggers_operations.nil? + @triggers_operations = FixDBSchemaConflicts::TriggersOperations.new(@connection) + @triggers_operations.reset_triggers_folder + end + @triggers_operations.triggers_creation(table_name, stream) end end def with_sorting - old, @connection = @connection, ConnectionWithSorting.new(@connection) - result = yield - @connection = old - result + old_connection = @connection + @connection = ConnectionWithSorting.new(old_connection) + begin + yield + ensure + @connection = old_connection + end end end end diff --git a/lib/fix_db_schema_conflicts/triggers_operations.rb b/lib/fix_db_schema_conflicts/triggers_operations.rb new file mode 100644 index 0000000..211ebc1 --- /dev/null +++ b/lib/fix_db_schema_conflicts/triggers_operations.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true +require 'delegate' + +module FixDBSchemaConflicts + class TriggersOperations + def initialize(connection) + @connection = connection + @reset_done = false + end + + def triggers_creation(table_name, stream, *args) + triggers = @connection.triggers(table_name) + unless triggers.empty? + stream.puts(" execute <<-SQL") + triggers.each do |trigger| + stream.puts("#{trigger.definition} ;") + add_triggers_in_file(table_name, trigger.definition) + end + stream.puts(" SQL") + end + end + + def reset_triggers_folder + return if @reset_done + + dir_path = Rails.root.join('app', 'triggers') + FileUtils.rm_rf Dir.glob("#{dir_path}/*") if dir_path.present? + @reset_done = true + end + + private + + def add_triggers_in_file(file_name, trigger_content) + triggers_path = Rails.root.join('app', 'triggers') + FileUtils.mkdir_p triggers_path unless triggers_path.exist? + file_path = triggers_path.join("#{file_name}.sql") + File.open(file_path, "w") {} unless File.exist?(file_path) + File.open(file_path, 'a') do |file| + formatted_sql = trigger_content.gsub(/(?=\b(AFTER|FOR EACH ROW|WHEN|EXECUTE FUNCTION)\b)/, "\n") + file.write(formatted_sql + ";") + file.puts + file.puts + end + end + end +end From 779be0d0114dca319edc19e4a8b73e03b6b946e5 Mon Sep 17 00:00:00 2001 From: agultekin Date: Mon, 6 Jan 2025 18:02:34 +0100 Subject: [PATCH 06/12] Improvement of the types, functions and triggers extractions in the db folder --- .../postgres_details_extractor.rb | 139 ++++++++++++------ .../triggers_operations.rb | 5 +- 2 files changed, 96 insertions(+), 48 deletions(-) diff --git a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb index 8818e5e..224e252 100644 --- a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb +++ b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb @@ -12,20 +12,16 @@ def initialize(connection) def create_types(stream) stream.puts(" execute <<-SQL") @pg_enum_types.each do |enum| - stream.puts "DO $$ BEGIN " \ - "IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '#{enum.name}') THEN " \ - "CREATE TYPE #{enum.name} AS ENUM (#{enum.enum_values}); " \ - "END IF; " \ - "END $$;" + exttracted_values = extract_types_components(enum) + stream.puts exttracted_values + types_in_file(exttracted_values) end if @pg_composite_types.present? @pg_composite_types.each do |composite| - stream.puts "DO $$ BEGIN " \ - "IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '#{composite.name}') THEN " \ - "CREATE TYPE #{composite.name} AS (#{composite.attributes}); " \ - "END IF; " \ - "END $$;" + exttracted_values = extract_types_components(composite) + stream.puts extract_types_components(exttracted_values) + types_in_file(exttracted_values) end end stream.puts(" SQL") @@ -33,44 +29,14 @@ def create_types(stream) def create_functions(stream) @pg_functions.each do |row| - # Extract function components - function_name = row.name - arguments = row.arguments - return_type = row.return_type - language_name = row.language_name - - # Ensure function body doesn't have trailing semicolons - function_body = row.body.strip.sub(/;+\z/, '') - - # Check if the function body starts with 'BEGIN' - starts_with_begin = function_body.match?(/^\s*BEGIN/i) - - # Handle functions correctly based on whether they require a procedural block - if starts_with_begin - # PL/pgSQL function with BEGIN...END already in the body - stream.write(<<~SQL) - execute <<~EOSQL - CREATE OR REPLACE FUNCTION #{function_name}(#{arguments}) - RETURNS #{return_type} AS $$ - #{function_body}; - $$ LANGUAGE #{language_name} #{row.volatility}; - EOSQL - SQL - - else - # Add BEGIN...END for procedural logic - stream.write(<<~SQL) - execute <<~EOSQL - CREATE OR REPLACE FUNCTION #{function_name}(#{arguments}) - RETURNS #{return_type} AS $$ - BEGIN - #{function_body}; - END; - $$ LANGUAGE plpgsql #{row.volatility}; - EOSQL - SQL - end + function_content, function_name = extract_function_components(row) + stream.write(<<~SQL) + execute <<~EOSQL + #{function_content} + EOSQL + SQL + functions_in_file(function_name, function_content) end end @@ -87,5 +53,84 @@ def create_fts_configurations(stream) stream.puts(" SQL") end end + + private + + def extract_function_components(row) + # Extract function components + function_name = row.name + arguments = row.arguments + return_type = row.return_type + language_name = row.language_name + + # Ensure function body doesn't have trailing semicolons + function_body = row.body.strip.sub(/;+\z/, '') + + # Check if the function body starts with 'BEGIN' + starts_with_begin = function_body.match?(/^\s*BEGIN/i) + + if starts_with_begin + function_content = <<~SQL + CREATE OR REPLACE FUNCTION #{function_name}(#{arguments}) + RETURNS #{return_type} AS $$ + #{function_body}; + $$ LANGUAGE #{language_name} #{row.volatility}; + SQL + else + function_content = <<~SQL + CREATE OR REPLACE FUNCTION #{function_name}(#{arguments}) + RETURNS #{return_type} AS $$ + BEGIN + #{function_body}; + END; + $$ LANGUAGE plpgsql #{row.volatility}; + SQL + end + [function_content, function_name] + end + + def extract_types_components(row) + <<~SQL + DO $$ + BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '#{row.name}') THEN + CREATE TYPE #{row.name} AS (#{row.attributes}); + END IF; + END + $$; + SQL + end + + def functions_in_file(file_name,function_content) + function_file_path = Rails.root.join('db', 'functions') + file_name = function_file_path.join("#{file_name}.sql") + FileUtils.mkdir_p function_file_path unless function_file_path.exist? + File.open(file_name, "w") {} unless File.exist?(file_name) + File.open(file_name, 'a') do |file| + function_content = function_content.gsub(/\n+/, "\n") + .gsub(/^\s+/m, '') + .strip + formatted_sql = function_content.gsub(/(?=\b(AS|BEGIN|END|LANGUAGE)\b)/, "\n") + file.write(formatted_sql + ";") + file.puts + file.puts + end + end + + def types_in_file(type_content) + type_file_path = Rails.root.join('db', 'types') + file_name = type_file_path.join("types.sql") + FileUtils.mkdir_p type_file_path unless type_file_path.exist? + File.open(file_name, "w") {} unless File.exist?(file_name) + File.open(file_name, 'a') do |file| + type_content = type_content.gsub(/\n+/, "\n") + .gsub(/^\s+/m, '') + .strip + formatted_sql = type_content.gsub(/(?=\b(AS|BEGIN|END|LANGUAGE|CREATE)\b)/, "\n") + file.write(formatted_sql + ";") + file.puts + file.puts + end + end end end diff --git a/lib/fix_db_schema_conflicts/triggers_operations.rb b/lib/fix_db_schema_conflicts/triggers_operations.rb index 211ebc1..26c756b 100644 --- a/lib/fix_db_schema_conflicts/triggers_operations.rb +++ b/lib/fix_db_schema_conflicts/triggers_operations.rb @@ -31,11 +31,14 @@ def reset_triggers_folder private def add_triggers_in_file(file_name, trigger_content) - triggers_path = Rails.root.join('app', 'triggers') + triggers_path = Rails.root.join('db', 'triggers') FileUtils.mkdir_p triggers_path unless triggers_path.exist? file_path = triggers_path.join("#{file_name}.sql") File.open(file_path, "w") {} unless File.exist?(file_path) File.open(file_path, 'a') do |file| + trigger_content = trigger_content.gsub(/\n+/, "\n") # Remove extra blank lines + .gsub(/^\s+/m, '') # Trim leading spaces for each line + .strip # Remove leading/trailing blank lines formatted_sql = trigger_content.gsub(/(?=\b(AFTER|FOR EACH ROW|WHEN|EXECUTE FUNCTION)\b)/, "\n") file.write(formatted_sql + ";") file.puts From ae7135a847be13c6d536924d24a926dd28abd8af Mon Sep 17 00:00:00 2001 From: agultekin Date: Tue, 7 Jan 2025 09:53:28 +0100 Subject: [PATCH 07/12] Reset files for recreation --- lib/fix_db_schema_conflicts/postgres_details_extractor.rb | 4 ++-- lib/fix_db_schema_conflicts/triggers_operations.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb index 224e252..f0a43f6 100644 --- a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb +++ b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb @@ -105,7 +105,7 @@ def functions_in_file(file_name,function_content) function_file_path = Rails.root.join('db', 'functions') file_name = function_file_path.join("#{file_name}.sql") FileUtils.mkdir_p function_file_path unless function_file_path.exist? - File.open(file_name, "w") {} unless File.exist?(file_name) + File.open(file_name, "w") {} File.open(file_name, 'a') do |file| function_content = function_content.gsub(/\n+/, "\n") .gsub(/^\s+/m, '') @@ -121,7 +121,7 @@ def types_in_file(type_content) type_file_path = Rails.root.join('db', 'types') file_name = type_file_path.join("types.sql") FileUtils.mkdir_p type_file_path unless type_file_path.exist? - File.open(file_name, "w") {} unless File.exist?(file_name) + File.open(file_name, "w") {} File.open(file_name, 'a') do |file| type_content = type_content.gsub(/\n+/, "\n") .gsub(/^\s+/m, '') diff --git a/lib/fix_db_schema_conflicts/triggers_operations.rb b/lib/fix_db_schema_conflicts/triggers_operations.rb index 26c756b..ee68569 100644 --- a/lib/fix_db_schema_conflicts/triggers_operations.rb +++ b/lib/fix_db_schema_conflicts/triggers_operations.rb @@ -34,7 +34,7 @@ def add_triggers_in_file(file_name, trigger_content) triggers_path = Rails.root.join('db', 'triggers') FileUtils.mkdir_p triggers_path unless triggers_path.exist? file_path = triggers_path.join("#{file_name}.sql") - File.open(file_path, "w") {} unless File.exist?(file_path) + File.open(file_path, "w") {} File.open(file_path, 'a') do |file| trigger_content = trigger_content.gsub(/\n+/, "\n") # Remove extra blank lines .gsub(/^\s+/m, '') # Trim leading spaces for each line From d58b8e792cf85e9e3c1412dfa8557f14c9666cf3 Mon Sep 17 00:00:00 2001 From: agultekin Date: Fri, 10 Jan 2025 17:13:05 +0100 Subject: [PATCH 08/12] PR Requested changes -> Schema has now a light version --- .../postgres_details_extractor.rb | 47 ++++++++++++------- .../triggers_operations.rb | 21 +++++---- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb index f0a43f6..7ad77ee 100644 --- a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb +++ b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb @@ -7,50 +7,55 @@ def initialize(connection) @pg_enum_types = @connection.fetch_enum_types @pg_functions = @connection.pg_functions @pg_fts_configurations = @connection.fts_configurations + type_file_path = Rails.root.join('db', 'others') + file_name = type_file_path.join("types.sql") + FileUtils.mkdir_p type_file_path unless type_file_path.exist? + File.open(file_name, "w") {} + fts_file_path = Rails.root.join('db', 'others', 'fts.sql') + File.open(fts_file_path, "w") {} end def create_types(stream) - stream.puts(" execute <<-SQL") @pg_enum_types.each do |enum| exttracted_values = extract_types_components(enum) - stream.puts exttracted_values types_in_file(exttracted_values) end if @pg_composite_types.present? @pg_composite_types.each do |composite| exttracted_values = extract_types_components(composite) - stream.puts extract_types_components(exttracted_values) types_in_file(exttracted_values) end end - stream.puts(" SQL") + stream.puts("\tfile = Rails.root.join('db', 'others', 'types.sql')") + stream.puts("\tfile_content = File.read(file)") + stream.puts("\texecute file_content") end def create_functions(stream) @pg_functions.each do |row| function_content, function_name = extract_function_components(row) - stream.write(<<~SQL) - execute <<~EOSQL - #{function_content} - EOSQL - SQL + stream.puts("\tfile = Rails.root.join('db', 'functions', \"#{function_name}.sql\")") + stream.puts("\tfile_content = File.read(file)") + stream.puts("\texecute file_content") functions_in_file(function_name, function_content) end end def create_fts_configurations(stream) unless @pg_fts_configurations.empty? - stream.puts(" execute <<-SQL") @pg_fts_configurations.each do |fts_configuration| - stream.puts "DO $$ BEGIN " \ + sql_code = "DO $$ BEGIN " \ "IF NOT EXISTS (SELECT 1 FROM pg_ts_config WHERE cfgname = '#{fts_configuration.name}') THEN " \ "CREATE TEXT SEARCH CONFIGURATION #{fts_configuration.name} (COPY = simple); " \ "END IF; " \ "END $$;" + extract_fts_configurations(sql_code) end - stream.puts(" SQL") + stream.puts("\tfile = Rails.root.join('db', 'others', 'fts.sql')") + stream.puts("\tfile_content = File.read(file)") + stream.puts("\texecute file_content") end end @@ -110,7 +115,7 @@ def functions_in_file(file_name,function_content) function_content = function_content.gsub(/\n+/, "\n") .gsub(/^\s+/m, '') .strip - formatted_sql = function_content.gsub(/(?=\b(AS|BEGIN|END|LANGUAGE)\b)/, "\n") + formatted_sql = function_content.gsub(/(?=\b(BEGIN|END|LANGUAGE|SET|WHERE)\b)/, "\n") file.write(formatted_sql + ";") file.puts file.puts @@ -118,10 +123,7 @@ def functions_in_file(file_name,function_content) end def types_in_file(type_content) - type_file_path = Rails.root.join('db', 'types') - file_name = type_file_path.join("types.sql") - FileUtils.mkdir_p type_file_path unless type_file_path.exist? - File.open(file_name, "w") {} + file_name = Rails.root.join('db', 'others', "types.sql") File.open(file_name, 'a') do |file| type_content = type_content.gsub(/\n+/, "\n") .gsub(/^\s+/m, '') @@ -132,5 +134,16 @@ def types_in_file(type_content) file.puts end end + + def extract_fts_configurations(fts_content) + file_name = Rails.root.join('db', 'others', "fts.sql") + File.open(file_name, 'a') do |file| + fts_content = fts_content.strip + formatted_sql = fts_content.gsub(/(?=\b(AS|BEGIN|END|LANGUAGE|CREATE)\b)/, "\n") + file.write(formatted_sql + ";") + file.puts + file.puts + end + end end end diff --git a/lib/fix_db_schema_conflicts/triggers_operations.rb b/lib/fix_db_schema_conflicts/triggers_operations.rb index ee68569..dfc1086 100644 --- a/lib/fix_db_schema_conflicts/triggers_operations.rb +++ b/lib/fix_db_schema_conflicts/triggers_operations.rb @@ -11,12 +11,9 @@ def initialize(connection) def triggers_creation(table_name, stream, *args) triggers = @connection.triggers(table_name) unless triggers.empty? - stream.puts(" execute <<-SQL") - triggers.each do |trigger| - stream.puts("#{trigger.definition} ;") - add_triggers_in_file(table_name, trigger.definition) - end - stream.puts(" SQL") + stream.puts("\ttrigger_file = Rails.root.join('db', 'triggers', \"#{table_name}.sql\")") + stream.puts("\tfile_content = File.read(trigger_file)") + stream.puts("\texecute file_content") end end @@ -36,14 +33,18 @@ def add_triggers_in_file(file_name, trigger_content) file_path = triggers_path.join("#{file_name}.sql") File.open(file_path, "w") {} File.open(file_path, 'a') do |file| - trigger_content = trigger_content.gsub(/\n+/, "\n") # Remove extra blank lines - .gsub(/^\s+/m, '') # Trim leading spaces for each line - .strip # Remove leading/trailing blank lines - formatted_sql = trigger_content.gsub(/(?=\b(AFTER|FOR EACH ROW|WHEN|EXECUTE FUNCTION)\b)/, "\n") + formatted_sql = format_trigger(trigger_content) file.write(formatted_sql + ";") file.puts file.puts end end + + def format_trigger(trigger_content) + trigger_content = trigger_content.gsub(/\n+/, "\n") # Remove extra blank lines + .gsub(/^\s+/m, '') # Trim leading spaces for each line + .strip # Remove leading/trailing blank lines + trigger_content.gsub(/(?=\b(AFTER|BEFORE|FOR EACH ROW|WHEN|EXECUTE FUNCTION)\b)/, "\n") + end end end From a73d38a4ae5f76f86f53530d7c7d494d18d09332 Mon Sep 17 00:00:00 2001 From: agultekin Date: Fri, 10 Jan 2025 17:45:29 +0100 Subject: [PATCH 09/12] Triggers files --- lib/fix_db_schema_conflicts/triggers_operations.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/fix_db_schema_conflicts/triggers_operations.rb b/lib/fix_db_schema_conflicts/triggers_operations.rb index dfc1086..4a2495c 100644 --- a/lib/fix_db_schema_conflicts/triggers_operations.rb +++ b/lib/fix_db_schema_conflicts/triggers_operations.rb @@ -11,6 +11,9 @@ def initialize(connection) def triggers_creation(table_name, stream, *args) triggers = @connection.triggers(table_name) unless triggers.empty? + triggers.each do |trigger| + add_triggers_in_file(table_name, trigger.definition) + end stream.puts("\ttrigger_file = Rails.root.join('db', 'triggers', \"#{table_name}.sql\")") stream.puts("\tfile_content = File.read(trigger_file)") stream.puts("\texecute file_content") From a2363336b033b431b7fda531ab74067078fa6250 Mon Sep 17 00:00:00 2001 From: agultekin Date: Mon, 13 Jan 2025 15:11:47 +0100 Subject: [PATCH 10/12] trigger schema modifcation --- lib/fix_db_schema_conflicts/schema_dumper.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/fix_db_schema_conflicts/schema_dumper.rb b/lib/fix_db_schema_conflicts/schema_dumper.rb index 2760773..91b2a18 100644 --- a/lib/fix_db_schema_conflicts/schema_dumper.rb +++ b/lib/fix_db_schema_conflicts/schema_dumper.rb @@ -49,7 +49,9 @@ def triggers(table) end def sanitize_trigger_definition(definition) - definition.gsub(/ON\s+(\w+\.)?(\w+\.)?/, 'ON ') + new_definition = definition.gsub(/ON\s+(\w+\.)?(\w+\.)?/, 'ON ') + new_definition.gsub!(/\bwizville\./, 'public.') + new_definition end def fts_configurations From 326252528b031b24e2d5228f806adfeec436bc70 Mon Sep 17 00:00:00 2001 From: agultekin Date: Mon, 13 Jan 2025 22:05:29 +0100 Subject: [PATCH 11/12] Aggregates implementations --- .../postgres_details_extractor.rb | 70 +++++++++++++++++-- .../postgres_schema_info_extractor.rb | 69 ++++++++++++++++++ lib/fix_db_schema_conflicts/schema_dumper.rb | 11 +++ 3 files changed, 143 insertions(+), 7 deletions(-) diff --git a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb index 7ad77ee..fb968f8 100644 --- a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb +++ b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb @@ -7,12 +7,15 @@ def initialize(connection) @pg_enum_types = @connection.fetch_enum_types @pg_functions = @connection.pg_functions @pg_fts_configurations = @connection.fts_configurations + @pg_aggregates = @connection.all_aggregates type_file_path = Rails.root.join('db', 'others') file_name = type_file_path.join("types.sql") FileUtils.mkdir_p type_file_path unless type_file_path.exist? File.open(file_name, "w") {} fts_file_path = Rails.root.join('db', 'others', 'fts.sql') File.open(fts_file_path, "w") {} + aggreagte_file_path = Rails.root.join('db', 'others', 'aggregates.sql') + File.open(aggreagte_file_path, "w") {} end def create_types(stream) @@ -32,15 +35,29 @@ def create_types(stream) stream.puts("\texecute file_content") end + def create_aggregates(stream) + return if @pg_aggregates.empty? + + @pg_aggregates.each do |aggregate| + aggregates_in_file(aggregate.definition) + end + stream.puts("\taggregate_file = Rails.root.join('db', 'others', 'aggregates.sql')") + stream.puts("\taggregate_content = File.read(aggregate_file)") + stream.puts("\texecute aggregate_content") + end + def create_functions(stream) @pg_functions.each do |row| function_content, function_name = extract_function_components(row) - - stream.puts("\tfile = Rails.root.join('db', 'functions', \"#{function_name}.sql\")") - stream.puts("\tfile_content = File.read(file)") - stream.puts("\texecute file_content") functions_in_file(function_name, function_content) end + + stream.puts("\tfunction_files_path = Rails.root.join('db', 'functions')") + stream.puts("\tsql_files = Dir.glob(File.join(function_files_path, '*.sql')).sort") + stream.puts("\tsql_files.sort.each do |file|") + stream.puts("\t sql = File.read(file)") + stream.puts("\t execute sql") + stream.puts("\tend") end def create_fts_configurations(stream) @@ -53,9 +70,9 @@ def create_fts_configurations(stream) "END $$;" extract_fts_configurations(sql_code) end - stream.puts("\tfile = Rails.root.join('db', 'others', 'fts.sql')") - stream.puts("\tfile_content = File.read(file)") - stream.puts("\texecute file_content") + stream.puts("\tfts_file = Rails.root.join('db', 'others', 'fts.sql')") + stream.puts("\tfts_content = File.read(fts_file)") + stream.puts("\texecute fts_content") end end @@ -145,5 +162,44 @@ def extract_fts_configurations(fts_content) file.puts end end + + def aggregates_in_file(aggregate_content) + file_name = Rails.root.join('db', 'others', "aggregates.sql") + File.open(file_name, 'a') do |file| + aggregate_content = sanitize_aggregate_definition(aggregate_content) + formatted_sql = aggregate_content.gsub(/(?=\b(AS|BEGIN|END|LANGUAGE|CREATE)\b)/, "\n") + file.write(formatted_sql + ";") + file.puts + file.puts + end + end + + def sanitize_aggregate_definition(sql) + # Remove invalid or empty clauses completely + sql = sql.gsub(/,\s*FINALFUNC\s*=\s*[^,\)\n]*/, '') + .gsub(/,\s*FINALFUNC_MODIFY\s*=\s*[^,\)\n]*/, '') + .gsub(/,\s*MFINALFUNC_MODIFY\s*=\s*[^,\)\n]*/, '') + .gsub(/,\s*COMBINEFUNC\s*=\s*[^,\)\n]*/, '') + .gsub(/,\s*SERIALFUNC\s*=\s*[^,\)\n]*/, '') + .gsub(/,\s*DESERIALFUNC\s*=\s*[^,\)\n]*/, '') + + # Remove dangling empty clauses + sql = sql.gsub(/\b(FINALFUNC|FINALFUNC_MODIFY|MFINALFUNC_MODIFY|COMBINEFUNC|SERIALFUNC|DESERIALFUNC)\s*=\s*[^,\)\n]*/, '') + + # Add missing commas between SFUNC and STYPE + sql.gsub!(/(SFUNC\s*=\s*[^\s,]+)\s+(STYPE\s*=\s*[^\s,]+)/, '\1, \2') + + # Remove trailing commas before closing parentheses + sql.gsub!(/,\s*\)/, ')') + + # Remove unnecessary semicolons + sql.gsub!(/;;$/, ';') + + # Ensure proper formatting by removing extra spaces + sql.gsub!(/\s{2,}/, ' ') # Replace multiple spaces with a single space + + # Final cleanup + sql.strip + end end end diff --git a/lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb b/lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb index 5e11900..e54b44f 100644 --- a/lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb +++ b/lib/fix_db_schema_conflicts/postgres_schema_info_extractor.rb @@ -82,5 +82,74 @@ def fts_configurations OpenStruct.new(schema: row['schema_name'], name: row['configuration_name']) end end + + def aggregates + query = <<-SQL + SELECT + p.proname AS name, + format_type(a.aggtranstype, NULL) AS state_type, + (SELECT proname FROM pg_proc WHERE oid = a.aggtransfn) AS transition_function, + (SELECT proname FROM pg_proc WHERE oid = a.aggfinalfn) AS final_function, + (SELECT proname FROM pg_proc WHERE oid = a.aggcombinefn) AS combine_function, + (SELECT proname FROM pg_proc WHERE oid = a.aggserialfn) AS serialize_function, + (SELECT proname FROM pg_proc WHERE oid = a.aggdeserialfn) AS deserialize_function, + a.agginitval AS initial_value, + a.aggfinalmodify AS finalfunc_modify, + a.aggmfinalmodify AS mfinalfunc_modify, + a.aggkind AS aggregate_kind + FROM + pg_aggregate a + JOIN + pg_proc p ON a.aggfnoid = p.oid + JOIN + pg_namespace n ON p.pronamespace = n.oid + WHERE + n.nspname = 'wizville' + ORDER BY + p.proname; + SQL + + @connection.execute(query).map do |row| + # Start building the SQL string dynamically + sql_parts = [] + sql_parts << "CREATE AGGREGATE public.#{row['name']} (#{row['state_type']}) (" + sql_parts << "SFUNC = #{row['transition_function']}" + sql_parts << "STYPE = #{row['state_type']}" + + # Add optional clauses only if valid + sql_parts << "FINALFUNC = #{row['final_function']}" unless row['final_function'] == "-" + sql_parts << "FINALFUNC_MODIFY = #{row['finalfunc_modify']}" if row['finalfunc_modify'] + sql_parts << "MFINALFUNC_MODIFY = #{row['mfinalfunc_modify']}" if row['mfinalfunc_modify'] + sql_parts << "COMBINEFUNC = #{row['combine_function']}" unless row['combine_function'] == "-" + sql_parts << "SERIALFUNC = #{row['serialize_function']}" unless row['serialize_function'] == "-" + sql_parts << "DESERIALFUNC = #{row['deserialize_function']}" unless row['deserialize_function'] == "-" + sql_parts << "INITCOND = '#{row['initial_value']}'" if row['initial_value'] + + # Close the SQL statement + sql_parts << ");" + + # Join all parts into a single string + create_aggregate_sql = sql_parts.join("\n ") + + # Sanitize or validate the SQL if needed + sanitized_sql = sanitize_aggregate_definition(create_aggregate_sql) + + OpenStruct.new(name: row['name'], definition: sanitized_sql) + end + end + + def sanitize_aggregate_definition(sql) + # Remove invalid or empty clauses + sql = sql.gsub(/, FINALFUNC =\s*\w*/, '') + .gsub(/, FINALFUNC_MODIFY =\s*\w*/, '') + .gsub(/, MFINALFUNC_MODIFY =\s*\w*/, '') + .gsub(/, COMBINEFUNC =\s*\w*/, '') + .gsub(/, SERIALFUNC =\s*\w*/, '') + .gsub(/, DESERIALFUNC =\s*\w*/, '') + + # Remove trailing commas and clean up the SQL + sql.gsub!(/,\s*\)/, ')') + sql.strip + end end end diff --git a/lib/fix_db_schema_conflicts/schema_dumper.rb b/lib/fix_db_schema_conflicts/schema_dumper.rb index 91b2a18..666d7a9 100644 --- a/lib/fix_db_schema_conflicts/schema_dumper.rb +++ b/lib/fix_db_schema_conflicts/schema_dumper.rb @@ -57,6 +57,10 @@ def sanitize_trigger_definition(definition) def fts_configurations @schema_info_extractor.fts_configurations end + + def all_aggregates + @schema_info_extractor.aggregates + end end def extensions(*args) @@ -76,11 +80,13 @@ def tables(stream) stream.puts("\t" + File.read(specific).gsub("\n", "\n\t") + "\n\n") end + aggreagates_fetched = false with_sorting do @details_operations = FixDBSchemaConflicts::PostgresDetailsExtractor.new(@connection) @details_operations.create_types(stream) @details_operations.create_functions(stream) @details_operations.create_fts_configurations(stream) + @details_operations.create_aggregates(stream) unless aggreagates_fetched end super(stream) end @@ -106,6 +112,11 @@ def with_sorting @connection = old_connection end end + + def sanitize_aggregate_definition(definition) + # Sanitize or format the definition as needed + definition.strip + end end end From 0c329a6e06c6ead4968699899c38660d07d6c74b Mon Sep 17 00:00:00 2001 From: agultekin Date: Tue, 14 Jan 2025 10:52:16 +0100 Subject: [PATCH 12/12] function files modifications --- .../postgres_details_extractor.rb | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb index fb968f8..cd7baaa 100644 --- a/lib/fix_db_schema_conflicts/postgres_details_extractor.rb +++ b/lib/fix_db_schema_conflicts/postgres_details_extractor.rb @@ -8,14 +8,7 @@ def initialize(connection) @pg_functions = @connection.pg_functions @pg_fts_configurations = @connection.fts_configurations @pg_aggregates = @connection.all_aggregates - type_file_path = Rails.root.join('db', 'others') - file_name = type_file_path.join("types.sql") - FileUtils.mkdir_p type_file_path unless type_file_path.exist? - File.open(file_name, "w") {} - fts_file_path = Rails.root.join('db', 'others', 'fts.sql') - File.open(fts_file_path, "w") {} - aggreagte_file_path = Rails.root.join('db', 'others', 'aggregates.sql') - File.open(aggreagte_file_path, "w") {} + files_verif_and_reset end def create_types(stream) @@ -49,7 +42,7 @@ def create_aggregates(stream) def create_functions(stream) @pg_functions.each do |row| function_content, function_name = extract_function_components(row) - functions_in_file(function_name, function_content) + functions_in_file(function_name, function_content) end stream.puts("\tfunction_files_path = Rails.root.join('db', 'functions')") @@ -78,6 +71,19 @@ def create_fts_configurations(stream) private + def files_verif_and_reset + type_file_path = Rails.root.join('db', 'others') + file_name = type_file_path.join("types.sql") + FileUtils.mkdir_p type_file_path unless type_file_path.exist? + File.open(file_name, "w") {} + fts_file_path = Rails.root.join('db', 'others', 'fts.sql') + File.open(fts_file_path, "w") {} + aggreagte_file_path = Rails.root.join('db', 'others', 'aggregates.sql') + File.open(aggreagte_file_path, "w") {} + function_files = Rails.root.join('db', 'functions') + FileUtils.rm_rf(Dir.glob("#{function_files}/*")) if function_files.present? + end + def extract_function_components(row) # Extract function components function_name = row.name @@ -123,11 +129,11 @@ def extract_types_components(row) SQL end - def functions_in_file(file_name,function_content) + def functions_in_file(file_name, function_content) function_file_path = Rails.root.join('db', 'functions') file_name = function_file_path.join("#{file_name}.sql") FileUtils.mkdir_p function_file_path unless function_file_path.exist? - File.open(file_name, "w") {} + File.open(file_name, "w") {} unless File.exist?(file_name) File.open(file_name, 'a') do |file| function_content = function_content.gsub(/\n+/, "\n") .gsub(/^\s+/m, '')