2012-01-21 9 views
5

Sto utilizzando find_by_sql per connettersi a un database Postgres ed eseguire una funzione di database. La funzione database esegue un numero di istruzioni SQL e solleva eccezioni come richiesto.Come si accede alle informazioni di errore del database quando si utilizzano Rails e Postgres

Come si intercetta il codice di errore e il messaggio di errore generato dalla funzione Postgres in Rails?

def self.validate_email(systemuserid, emailaddress) 
    begin 
    result = (self.find_by_sql(["SELECT fn_systemuser_validate_email(?, ?) AS returncode", 
           systemuserid, emailaddress])).first 
    rescue => err 
    # I want to get access to the error code and error message here and act accordingly 
    # errno = ?? 
    # errmsg = ?? 
    if errno == 10000 
    end 
    end 
    return result[:returncode] 
end 

Ho iniziato cercando di trovare queste informazioni nell'oggetto di connessione, non è così.

Qualsiasi aiuto molto apprezzato.

risposta

0

È possibile all'utente la serie di errori del modello, come gli altri database:

errmsg = YourModel.errors [0] .full_messages

+1

Grazie per la risposta, ma ho paura che questo non aiuta davvero. –

+0

La mia comprensione è che la matrice degli errori viene utilizzata per presentare gli errori all'utente in seguito alla convalida del modello. Questo è diverso. Sto cercando l'accesso a SQLCode/SQLState restituito da Postgres come risultato di una chiamata find_by_sql. Questo si verifica molto prima di qualsiasi cosa venga aggiunta alla matrice degli errori. In realtà, il punto è che sto cercando di controllare esattamente cosa viene aggiunto all'array degli errori come risultato della chiamata della funzione SQL. –

+0

Non riesco a visualizzare alcuna documentazione in alcun modo su come ottenere l'accesso esplicito al codice di errore SQL. Sembra che l'unica opzione sia quella di manipolare le stringhe per estrarlo dal messaggio di errore. MOLTO insoddisfacente. Non posso credere che la gestione del database sia così inflessibile, quindi DEVE esserci una soluzione. –

3

record correntemente attivo sostituisce l'errore originale con una interna uno senza passare all'originale con il nuovo errore. Non capisco perché qualcuno vorrebbe questo.

Quindi l'unica soluzione in questo momento è quello di patch di scimmia;)

module ActiveRecord 
    module ConnectionAdapters 
    class AbstractAdapter 
     def translate_exception(e, message) 
     ActiveRecord::WrappedDatabaseException.new(message,e) 
     end 

     # Replaces 
     # def translate_exception(e, message) 
     # # override in derived class 
     # ActiveRecord::StatementInvalid.new(message) 
     # end 
    end 
    end 
end 

Ora è possibile ottenere l'original_exception.

def self.validate_email(systemuserid, emailaddress) 
    begin 
    result = (self.find_by_sql(["SELECT fn_systemuser_validate_email(?, ?) AS returncode", systemuserid, emailaddress])).first 
    rescue ActiveRecord::WrappedDatabaseException => e 

    pgerror = e.original_exception 

    # Exact api depends on PG version, check the docs for your version. 
    puts "Doing my stuff: #{pgerror.result.result_error_message}" 

    end 
end 

Questo funziona con pg versione 0.11 e Rails 3.0.9. Probabilmente funzionerà con le versioni successive.

+0

Se non ti piace il patch delle scimmie vai e vota questa richiesta di pull. https://github.com/rails/rails/pull/5641 – Darwin

0

L'ho lasciato andare per un po '(9 mesi!) Ma l'ho raccolto di nuovo a causa di un nuovo slancio.

ho usato la patch scimmia suggerito da Darwin (mi dispiace che la richiesta di pull non ha ancora ottenere il voto) e hanno poi scoperto che il codice ho bisogno (con riferimento alla http://deveiate.org/code/pg/PG/Result.html) è la seguente:

rescue ActiveRecord::WrappedDatabaseException => e 

    pgerror = e.original_exception 
    sqlstate = pgerror.result.error_field(PG::Result::PG_DIAG_SQLSTATE) 
end 
0

Proprio guarda .cause.

begin 
    # whatever. 
rescue => err 
    p err.cause 
end 
Problemi correlati