How do I create a trigger in a Rails migration?

By : Dave
Source: Stackoverflow.com
Question!

I’m trying to add some triggers to my PostgreSQL (v 9) db and I would like to create a Rails migration (using v 4.2.7) to satisfy this goal. So I created a migration with this content

class CreateDeleteAddressTriggers < ActiveRecord::Migration
  def change
    execute <<-SQL
      CREATE OR REPLACE FUNCTION remove_address() RETURNS trigger
        LANGUAGE plpgsql AS
        $$BEGIN
          DELETE FROM public.addresses WHERE id = OLD.address_id;
      END;$$;

      CREATE TRIGGER remove_my_object_address
        AFTER DELETE ON public.my_objects FOR EACH ROW
        EXECUTE TRIGGER remove_address()

      CREATE TRIGGER remove_user_address
        AFTER DELETE ON public.users FOR EACH ROW
        EXECUTE TRIGGER remove_address()
    SQL
  end
end

Unfortunately when I run the “rake db:migrate” task, I get the following error

davea$ rake db:migrate
== 20160928184431 CreateDeleteAddressTriggers: migrating ======================
-- execute("      CREATE OR REPLACE FUNCTION remove_address() RETURNS trigger\n        LANGUAGE plpgsql AS\n        $$BEGIN\n          DELETE FROM public.addresses WHERE id =  OLD.address_id;\n      END;$$;\n\n      CREATE TRIGGER remove_my_object_address\n        AFTER DELETE ON public.my_objects FOR EACH ROW\n        EXECUTE TRIGGER remove_address()\n\n       CREATE TRIGGER remove_user_address\n        AFTER DELETE ON public.users FOR EACH ROW\n        EXECUTE TRIGGER remove_address()\n")
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::SyntaxError: ERROR:  syntax error at or near "TRIGGER"
LINE 9:         EXECUTE TRIGGER remove_address()
                        ^
:       CREATE OR REPLACE FUNCTION remove_address() RETURNS trigger
        LANGUAGE plpgsql AS
        $$BEGIN
          DELETE FROM public.addresses WHERE id = OLD.address_id;
      END;$$;

      CREATE TRIGGER remove_my_object_address
        AFTER DELETE ON public.my_objects FOR EACH ROW
        EXECUTE TRIGGER remove_address()

      CREATE TRIGGER remove_user_address
        AFTER DELETE ON public.users FOR EACH ROW
        EXECUTE TRIGGER remove_address()
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec'
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `block in execute'
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract_adapter.rb:484:in `block in log'
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.7.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/abstract_adapter.rb:478:in `log'
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:154:in `execute'
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/migration.rb:665:in `block in method_missing'
/Users/davea/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7.1/lib/active_record/migration.rb:634:in `block in say_with_time'

How can I correct my migration in order to run the triggers properly?

Edit: In response to the answer given, this was the error generated ...

ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR:  syntax error at or near "CREATE"
LINE 11:       CREATE TRIGGER remove_user_address
By : Dave


Answers

You're using the wrong syntax in your SQL. You need EXECUTE PROCEDURE, not EXECUTE TRIGGER.

You should have

  CREATE TRIGGER remove_my_object_address
    AFTER DELETE ON public.my_objects FOR EACH ROW
    EXECUTE PROCEDURE remove_address()
            ^^^^^^^^^

and

 CREATE TRIGGER remove_user_address
    AFTER DELETE ON public.users FOR EACH ROW
    EXECUTE PROCEDURE remove_address()
            ^^^^^^^^^

Source: The PostgreSQL docs.

By : meagar


You should be able to add your chain your methods on to the end of:

// add the links and the arrows
var path = svg.append("svg:g").selectAll("path")
    .data(force.links())
    .enter().append("svg:path")
    .attr("class", "link")
    .attr("marker-end", "url(#end)");

It's approx line 73 of the sample code



This video can help you solving your question :)
By: admin