Skip to content
Closed
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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,16 @@ tweak the schema in the new definition and run the `update_function` migration.

## I don't need this trigger or function anymore. Make it go away.

F(x) gives you `drop_trigger` and `drop_function` too:
F(x) gives you `drop_trigger` and `drop_function` too. These support the Rails 6.1 `if_exists: true` flags

```ruby
def change
drop_function :uppercase_users_name, revert_to_version: 2
end

def up
drop_function :users_first_name, revert_to_version: 2, if_exists: true
end
```

## What if I need to use a function as the default value of a column?
Expand Down
12 changes: 7 additions & 5 deletions lib/fx/adapters/postgres.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,14 @@ def update_trigger(name, on:, sql_definition:)
# {Fx::Statements::Function#drop_function}.
#
# @param name The name of the function to drop
# @param if_exists If true, will not raise an error if the function does not exist
#
# @return [void]
def drop_function(name)
def drop_function(name, if_exists: false)
if connection.support_drop_function_without_args
execute("DROP FUNCTION #{name};")
execute("DROP FUNCTION #{if_exists ? 'IF EXISTS ' : ' '}#{name};")
else
execute("DROP FUNCTION #{name}();")
execute("DROP FUNCTION #{if_exists ? 'IF EXISTS ' : ' '}#{name}();")
end
end

Expand All @@ -139,10 +140,11 @@ def drop_function(name)
#
# @param name The name of the trigger to drop
# @param on The associated table for the trigger to drop
# @param if_exists If true, will not raise an error if the trigger does not exist
#
# @return [void]
def drop_trigger(name, on:)
execute("DROP TRIGGER #{name} ON #{on};")
def drop_trigger(name, on:, if_exists: false)
execute("DROP TRIGGER #{if_exists ? 'IF EXISTS ' : ' '}#{name} ON #{on};")
end

private
Expand Down
12 changes: 10 additions & 2 deletions lib/fx/statements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ def create_function(name, options = {})
# @example Drop a function, rolling back to version 2 on rollback
# drop_function(:uppercase_users_name, revert_to_version: 2)
#
# @example Drop a function only if it exists
# drop_function(:uppercase_users_name, if_exists: true)
#
def drop_function(name, options = {})
Fx.database.drop_function(name)
if_exists = options.fetch(:if_exists, false)
Fx.database.drop_function(name, if_exists: if_exists)
end

# Update a database function.
Expand Down Expand Up @@ -160,9 +164,13 @@ def create_trigger(name, options = {})
# @example Drop a trigger, rolling back to version 3 on rollback
# drop_trigger(:log_inserts, on: :users, revert_to_version: 3)
#
# @example Drop a trigger only if it exists
# drop_trigger(:log_inserts, on: :users, if_exists: true)
#
def drop_trigger(name, options = {})
on = options.fetch(:on)
Fx.database.drop_trigger(name, on: on)
if_exists = options.fetch(:if_exists, false)
Fx.database.drop_trigger(name, on: on, if_exists: if_exists)
end

# Update a database trigger to a new version.
Expand Down
10 changes: 10 additions & 0 deletions spec/features/functions/migrations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ def up
expect { run_migration(migration, :up) }.not_to raise_error
end

it "can run migrations that drop functions without raising an error" do
migration = Class.new(migration_class) do
def up
drop_function :test, if_exists: true # test has not been created
end
end

expect { run_migration(migration, :up) }.not_to raise_error
end

it "can run migrations that updates functions" do
connection.create_function(:test)

Expand Down
12 changes: 12 additions & 0 deletions spec/features/functions/revert_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ def change
)
end

it "can run reversible migrations for dropping functions with if_exists" do
connection.create_function(:test)

good_migration = Class.new(migration_class) do
def change
drop_function :test, revert_to_version: 1, if_exists: true
end
end

expect { run_migration(good_migration, [:up, :down]) }.not_to raise_error
end

it "can run reversible migrations for updating functions" do
connection.create_function(:test)

Expand Down
9 changes: 9 additions & 0 deletions spec/fx/adapters/postgres_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@
expect(adapter.functions.map(&:name)).not_to include("test")
end
end

context "when the function does not exist" do
it "successfully drops a function with if_exists = true" do
adapter = Fx::Adapters::Postgres.new
adapter.drop_function(:test, if_exists: true)

expect(adapter.functions.map(&:name)).not_to include("test")
end
end
end

describe "#functions" do
Expand Down
21 changes: 19 additions & 2 deletions spec/fx/statements_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,15 @@

connection.drop_function(:test)

expect(database).to have_received(:drop_function).with(:test)
expect(database).to have_received(:drop_function).with(:test, if_exists: false)
end

it "drops the function with if_exists" do
database = stubbed_database

connection.drop_function(:test, if_exists: true)

expect(database).to have_received(:drop_function).with(:test, if_exists: true)
end
end

Expand Down Expand Up @@ -134,7 +142,16 @@
connection.drop_trigger(:test, on: :users)

expect(database).to have_received(:drop_trigger)
.with(:test, on: :users)
.with(:test, on: :users, if_exists: false)
end

it "drops the trigger with if_exists" do
database = stubbed_database

connection.drop_trigger(:test, on: :users, if_exists: true)

expect(database).to have_received(:drop_trigger)
.with(:test, on: :users, if_exists: true)
end
end

Expand Down
Loading