Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/annotate_rb/tasks/annotate_models_migrate.rake
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ if defined?(Rails::Application) && Rails.version.split(".").first.to_i >= 6
end
end

config = ::AnnotateRb::ConfigLoader.load_config

migration_tasks.each do |task|
next unless Rake::Task.task_defined?(task)
next if config[:skip_on_db_migrate]

Rake::Task[task].enhance do # This block is ran after `task` completes
task_name = Rake.application.top_level_tasks.last # The name of the task that was run, e.g. "db:migrate"
Expand Down
32 changes: 32 additions & 0 deletions spec/integration/annotate_after_migration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,36 @@
expect(annotated_test_default).to eq(expected_test_default)
end
end

context "when skip_on_db_migrate is enabled" do
before do
# Install the rake task hook
_cmd = run_command_and_stop("bin/rails g annotate_rb:install", fail_on_error: true, exit_timeout: command_timeout_seconds)

# Create config with skip_on_db_migrate enabled
write_file(".annotaterb.yml", "skip_on_db_migrate: true")
end

it "skips annotation during migration" do
reset_database

original_test_default = read_file(dummyapp_model("test_default.rb"))

# Run migration - should NOT trigger annotation due to skip_on_db_migrate
_run_migrations_cmd = run_command_and_stop("bin/rails db:migrate", fail_on_error: true, exit_timeout: command_timeout_seconds)

# File should remain unchanged
unchanged_test_default = read_file(dummyapp_model("test_default.rb"))

expect(last_command_started).to be_successfully_executed
expect(unchanged_test_default).to eq(original_test_default)

# Verify annotation still works when run manually
_manual_cmd = run_command_and_stop("bundle exec annotaterb models", fail_on_error: true, exit_timeout: command_timeout_seconds)
annotated_test_default = read_file(dummyapp_model("test_default.rb"))
expected_test_default = read_file(model_template("test_default.rb"))

expect(annotated_test_default).to eq(expected_test_default)
end
end
end
228 changes: 161 additions & 67 deletions spec/lib/tasks/annotate_models_migrate_spec.rb
Original file line number Diff line number Diff line change
@@ -1,64 +1,118 @@
RSpec.describe "ActiveRecord migration rake task hooks" do
context "single database" do
before do
Rake.application = Rake::Application.new
shared_context "spec setup with a single database" do |skip_on_db_migrate: false|
before do
allow(AnnotateRb::ConfigLoader).to receive(:load_config).and_return({skip_on_db_migrate:})

# Stub migration tasks
%w[db:migrate db:migrate:up db:migrate:down db:migrate:reset db:rollback].each do |task|
Rake::Task.define_task(task)
Rake.application = Rake::Application.new

# Stub migration tasks
%w[db:migrate db:migrate:up db:migrate:down db:migrate:reset db:rollback].each do |task|
Rake::Task.define_task(task)
end

Rake::Task.define_task("db:migrate:redo") do
Rake::Task["db:rollback"].invoke
Rake::Task["db:migrate"].invoke
end

Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake")

Rake.application.instance_variable_set(:@top_level_tasks, [subject])
end
end

context "when skip_on_db_migrate is disabled" do
include_context "spec setup with a single database", skip_on_db_migrate: false

Rake::Task.define_task("db:migrate:redo") do
Rake::Task["db:rollback"].invoke
Rake::Task["db:migrate"].invoke
describe "db:migrate" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end

Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake")
describe "db:migrate:up" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end

Rake.application.instance_variable_set(:@top_level_tasks, [subject])
end
describe "db:migrate:down" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end

describe "db:migrate" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
describe "db:migrate:reset" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end
end

describe "db:migrate:up" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
describe "db:rollback" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end
end

describe "db:migrate:down" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
describe "db:migrate:redo" do
it "should annotate model files after all migration tasks" do
# Hooked 3 times by db:rollback, db:migrate, and db:migrate:redo tasks
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")).exactly(3).times

Rake.application.top_level
end
end
end

describe "db:migrate:reset" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
context "when skip_on_db_migrate is enabled" do
include_context "spec setup with a single database", skip_on_db_migrate: true

describe "db:migrate" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end

describe "db:migrate:up" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end
end

describe "db:rollback" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
describe "db:migrate:down" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end

describe "db:migrate:reset" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end
end

describe "db:migrate:redo" do
it "should annotate model files after all migration tasks" do
# Hooked 3 times by db:rollback, db:migrate, and db:migrate:redo tasks
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models")).exactly(3).times
describe "db:rollback" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end

Rake.application.top_level
describe "db:migrate:redo" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end
end
end
Expand All @@ -77,49 +131,89 @@ def stub_rails(version, database_names)
end

allow(ActiveRecord::Tasks::DatabaseTasks).to receive(:for_each) do |databases, &block|
databases.each { |name, config| block.call(name) }
databases.each { |name, _config| block.call(name) }
end
end

before do
stub_rails "6.0.0", ["primary"]
shared_context "spec setup with multiple databases" do |skip_on_db_migrate: false|
before do
allow(AnnotateRb::ConfigLoader).to receive(:load_config).and_return({skip_on_db_migrate:})

Rake.application = Rake::Application.new
stub_rails "6.0.0", ["primary"]

%w[db:migrate db:migrate:up db:migrate:down db:rollback].each do |task|
Rake::Task.define_task("#{task}:primary")
end
Rake.application = Rake::Application.new

Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake")
%w[db:migrate db:migrate:up db:migrate:down db:rollback].each do |task|
Rake::Task.define_task("#{task}:primary")
end

Rake.application.instance_variable_set(:@top_level_tasks, [subject])
end
Rake.load_rakefile("annotate_rb/tasks/annotate_models_migrate.rake")

describe "db:migrate:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
Rake.application.instance_variable_set(:@top_level_tasks, [subject])
end
end

describe "db:migrate:up:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
context "when skip_on_db_migrate is disabled" do
include_context "spec setup with multiple databases", skip_on_db_migrate: false

describe "db:migrate:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end
end

describe "db:migrate:down:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
describe "db:migrate:up:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end

describe "db:migrate:down:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end

describe "db:rollback:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
end
end
end

describe "db:rollback:primary" do
it "should annotate model files" do
expect(AnnotateRb::Runner).to receive(:run).with(a_collection_including("models"))
Rake.application.top_level
context "when skip_on_db_migrate is enabled" do
include_context "spec setup with multiple databases", skip_on_db_migrate: true

describe "db:migrate:primary" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end

describe "db:migrate:up:primary" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end

describe "db:migrate:down:primary" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end

describe "db:rollback:primary" do
it "should not annotate model files" do
expect(AnnotateRb::Runner).not_to receive(:run)
Rake.application.top_level
end
end
end
end
Expand Down