5

Uso Rails 4.2.3 con un database PostGre. Voglio una colonna nel mio database per memorizzare un numero di millisecondi - nota, NON un timestamp, ma piuttosto una durata in millisecondi. Così ho creato la mia colonna in questo modoIl "valore" 3000002000 "non è compreso nell'intervallo per il tipo intero"

time_in_ms | bigint 

Tuttavia, quando vado a memorizzare un valore in Rails, ottengo l'errore sotto

ActiveRecord::StatementInvalid (PG::NumericValueOutOfRange: ERROR: value "3000002000" is out of range for type integer 
: INSERT INTO "my_object_times" ("time_in_ms", "my_object_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"): 
    app/controllers/my_objects_controller.rb:31:in `update' 

Sembrerebbe il numero, “3.000.002 mila” è più piccolo il valore massimo per la colonna (che sto leggendo è "9223372036854775807"), quindi mi chiedo che altro sta andando storto e come posso aggiustarlo.

Edit: per fornire ulteriori informazioni, nel mio file db/schema.rb, la colonna in questione è descritto questa convenzione ...

create_table "my_object_times", force: :cascade do |t| 
    ... 
    t.integer "time_in_ms",  limit: 8 

Edit 2: Ecco l'output di creare tavolo in PSQL

CREATE TABLE my_object_times (
    id integer NOT NULL, 
    first_name character varying, 
    last_name character varying, 
    time_in_ms bigint, 
    created_at timestamp without time zone NOT NULL, 
    updated_at timestamp without time zone NOT NULL, 
    name character varying, 
    age integer, 
    city character varying, 
    state_id integer, 
    country_id integer, 
    overall_rank integer, 
    age_group_rank integer, 
    gender_rank integer 
); 
+1

controllare una volta il tipo di dati della colonna nel file schema.rb di nuovo? –

+2

Il messaggio di errore suggerisce che la colonna è in realtà un 'int'. Cosa dice il tuo 'schema.rb'? Cosa dice '\ d my_object_times 'da dentro' psql'? –

+2

In una nota a margine, è necessario memorizzare le durate con il tipo di dati 'interval', non un' bigint'. È un intero a 64 bit internamente, come 'bigint', ma se si usa' interval' è più semanticamente utile e si ha accesso a tutti i tipi di operatori a portata di mano. –

risposta

5

ho dovuto accadere a me prima dove quando ho inizialmente provo a creare un campo bigint nel db, per qualche motivo il modello pensa che sia un numero intero invece, anche quando lo schema e il file di migrazione lo specificano come bigint.

Per esempio: ho avuto questo file di migrazione

class CreateSecureUserTokens < ActiveRecord::Migration 
    def change 
    create_table :secure_user_tokens do |t| 
     t.integer :sso_id, null: false, length: 8 
     t.string :token, null: false 

     t.timestamps null: false 
    end 
    end 
end 

nota, ha la lunghezza incluso: 8 requisito per fare un intero un bigint. Tuttavia, dopo aver eseguito la migrazione, ho riscontrato lo stesso problema. Alla fine ho appena creato un'altra migrazione per provare a risolvere il problema, e ha funzionato. Ecco la migrazione che ho usato per risolvere il problema:

class ModifySecureTokensForLargerSsoIdSizes < ActiveRecord::Migration 
    def change 
    change_column :secure_user_tokens, :sso_id, :integer, limit: 8 
    end 
end 

Quindi, se abbiamo cambiato che per soddisfare le vostre esigenze, sarebbe:

class ObjectTimesBigInt < ActiveRecord::Migration 
    def change 
    change_column :my_object_times, :time_in_ms, :integer, limit: 8 
    end 
end 

Speranza che aiuta! -Charlie

-4

bigint è a 64 bit, mentre Rails è 32 bit.

3000002000 è maggiore di 2^32. Ecco perché la conversione in un numero intero a 32 bit fallisce con NumericValueOutOfRange.

+1

Eh? Il messaggio di errore suggerisce che il database si sta lamentando e l'OP afferma di aver creato la colonna come 'bigint' a 64 bit. –

+0

@muistooshort 'PG :: NumericValueOutOfRange' - suggerisce che si tratta del problema di conversione relativo all'intervallo, esattamente il problema che spiego nella mia risposta;) –

+1

L'errore proviene dal database, non da Rails. Ruby aggiornerà gli interi in bignum secondo necessità. Il Ruby in uso quasi sicuramente a 64 bit visto che questo è il 2016. –

1

edit: Ho appena riletto questa e la mia risposta originale in realtà non ha senso nel tuo caso. Credo che sia necessario guardare fuori da quella colonna per una risposta, e confermare ogni bit di ciò che pensi di sapere sullo stato di esso, manualmente. Qualsiasi aggiunta di dettagli ci aiuterebbe a trovare una risposta corretta. Impostare i punti di interruzione per passo attraverso la richiesta e vedere se è possibile individuare le integer

CREATE_TABLE "my_object_times", forza:: cascata do | t | ... t.integer "time_in_ms", limite: 8

t.integer - Questo appare come la vostra colpevole a me. ... Beh, ci ho provato, il mio ultimo pensiero è che deve essere correlato a qualche tipo di middleware di richiesta di Rails, ma non sono a conoscenza di quali potrebbero essere le specifiche. Qualcosa nel percorso della richiesta pensa che la colonna sia un intero. Non capivo come funzionassero i datagrammi di migrazione di Rails fino ad ora, quindi ho imparato qualcosa. (E sono andato a pesca tutto il giorno, quindi valuterò questo giorno una vittoria.) Buona fortuna!

+0

Non capisco cosa vuoi che faccia. Quali ulteriori informazioni sono utili? – Dave

+1

Onestamente non lo so, sto solo cercando di pensare a cosa farei. Vorrei confermare lo schema dei dati mostra un bigint sulla colonna DB effettiva per time_in_milliseconds. Il messaggio di errore indica sicuramente parte del sistema (non sono un esperto di rotaie, ma Active Record sembra che lo stia dicendo) crede che il valore dovrebbe essere un numero intero non bigint ... pubblica il tuo modello, semi, migrazioni e la struttura della tabella prodotta da PostGre, forse? –

+0

Ho incluso il db/schema.rb nella mia domanda e anche nella mia domanda è stata inclusa la definizione "\ d my_object_times" da PostGresdb. – Dave

1

Immagino che la tabella my_object_times non possa essere creata dal file schema.rb o che potrebbe essere sovrascritta in altri file di migrazione. Perché nella colonna intera del file di migrazione con limite 8 è a sua volta un bigint. Quindi dovresti eseguire un controllo incrociato della definizione della tabella da PG-admin.Se la colonna non è di tipo bigint quindi eseguire il seguente migrazione

class ChangeTimeInMsToBigint < ActiveRecord::Migration 
    def change 
    execute <<-SQL 
    ALTER TABLE my_object_times 
    ALTER COLUMN time_in_ms TYPE bigint USING time_in_ms::bigint 
    SQL 
end 
end 
Problemi correlati