Como migrar suas Stored Procedures no ambiente de teste


Leia em 1 minuto

Normalmente, evito utilizar Stored Procedures e Functions até onde posso, mas no Spesa, não foi possível, devido uma quantidade de consultas "avançadas" que são feitas. Se não as utilizasse, a repetição de código seria absurdamente grande e, por conseguinte, seria impossível de se fazer eventuais modificações. Como estou refatorando o código do Spesa e escrevendo testes para cada item do sistema, caí em um problema um pouco incômodo na hora da migração.

Não sei se você sabe, mas toda vez que você quer sincronizar o seu banco de testes com o de desenvolvimento, basta executar o comando rake db:test:prepare. O grande problema deste comando é que ele não leva em consideração os arquivos de migração, mas sim o arquivo schema.rb, que não adiciona queries executadas através do método execute. Para corrigir isto, basta executar o comando rake db:migrate RAILS_ENV="test".

Update: depois de fazer alguns testes, vi que as stored procedures continuavam a serem excluídas. O único jeito foi estender o ActiveRecord para ele fazer o dump das funções e salvá-las no arquivo schema.rb. Basta adicionar o código abaixo no arquivo environment.rb.

module ActiveRecord
  class SchemaDumper
    def dump(stream)
      header(stream)
      tables(stream)
      functions(stream)
      trailer(stream)
      stream
    end

    private
      def functions(stream)
        result = @connection.execute <<QUERY
        SELECT
          ROUTINE_NAME AS name
        FROM
          INFORMATION_SCHEMA.ROUTINES
        WHERE
          ROUTINE_TYPE='FUNCTION' AND
          ROUTINE_SCHEMA='#{@connection.current_database}'
QUERY
        result.each do |row|
          stream = function(row[0], stream)
        end
      end

      def function(name, stream)
        result = @connection.execute "SHOW CREATE FUNCTION #{name}"
        fields = result.fetch_hash
        func = fields['Create Function'].gsub(/CREATE DEFINER.*? FUNCTION/, "CREATE FUNCTION")

        stream.puts <<FUNCTION
execute <<QUERY
  #{func}
QUERY

FUNCTION
        stream
      end
  end
end