5

Ich verwende Rails 4.2.3 mit einer PostGre-Datenbank. Ich möchte eine Spalte in meiner Datenbank eine Anzahl von Millisekunden speichern - beachten Sie, kein Zeitstempel, sondern eine Dauer in Millisekunden. Also habe ich meine Spalte wie so"Wert" erhalten 3000002000 "liegt außerhalb des Bereichs für den Typ"

time_in_ms | bigint 

Allerdings, wenn ich einen Wert in Rails speichern gehen, erhalte ich die folgenden Fehler

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' 

Es würde die Zahl erscheinen, „3000002000“ kleiner ist als der maximale Wert für die Spalte (die ich lese ist "9223372036854775807"), also frage ich mich, was sonst noch schief läuft und wie ich es beheben kann.

Edit: zusätzliche Informationen zu liefern, in meiner db/schema.rb Datei wird die Säule in Frage thusly beschrieben ...

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

Edit 2: Hier ist die Ausgabe von erstellen in Tabelle 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

Überprüfen Sie einmal den Spaltendatentyp in der schema.rb-Datei erneut? –

+2

Die Fehlermeldung weist darauf hin, dass die Spalte tatsächlich ein 'int' ist. Was sagt dein 'schema.rb'? Was sagt '\ d my_object_times' aus' psql'? –

+2

Als Randnotiz sollten Sie die Dauer mit dem Datentyp 'interval' speichern, keine' bigint'. Es ist intern eine 64-Bit-Ganzzahl, wie 'bigint', aber wenn Sie' interval' verwenden, ist es semantisch nützlicher und Sie erhalten Zugriff auf alle Arten von handlichen Operatoren. –

Antwort

5

Ich habe es mir passieren, bevor, wo, wenn ich versuche zunächst ein Bigint Feld in der db zu erstellen, aus irgendeinem Grunde das Modell denkt, dass es eine ganze Zahl ist stattdessen, selbst wenn das Schema und die Migrationsdatei es als Bigint angeben.

Zum Beispiel: Ich habe diese Migrationsdatei Hinweis

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 

hatte, hat es die enthielt Länge: 8 Anforderung eine ganze Bigint zu machen. Nachdem ich die Migration durchgeführt hatte, hatte ich das gleiche Problem wie Sie. Schließlich habe ich gerade eine weitere Migration erstellt, um das Problem zu beheben, und es hat funktioniert. Hier ist die Migration ich verwendet, um das Problem zu beheben:

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

Also, wenn wir das geändert an Ihre Bedürfnisse anzupassen, es wäre:

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

Hoffnung, das hilft! -Charlie

-4

bigint ist 64 Bit, während die Schienen 32-Bit ist.

3000002000 ist größer als 2^32. Aus diesem Grund schlägt die Konvertierung in eine 32-Bit-Ganzzahl mit NumericValueOutOfRange fehl.

+1

Huh? Die Fehlermeldung weist darauf hin, dass sich die Datenbank beschwert und das OP behauptet, dass sie die Spalte als 64-Bit-Bigint erstellt haben. –

+0

@muistooshort 'PG :: NumericValueOutOfRange' - suggeriert, dass es sich um das bereichsbezogene Konvertierungsproblem handelt, genau das Problem, das ich in meiner Antwort erkläre;) –

+1

Der Fehler kommt von der Datenbank, nicht von Rails. Ruby aktualisiert Integer nach Bedarf auf Bignums. Der Rubin im Einsatz ist fast sicher 64bit sowieso, da dies 2016 ist. –

1

edit: ich gerade dies und meine ursprüngliche Antwort wieder lese eigentlich keinen Sinn in Ihrem Fall machen. Ich glaube, dass Sie außerhalb dieser Spalte nach einer Antwort suchen müssen, und bestätigen Sie jedes Bit von dem, was Sie denken, dass Sie über den Zustand davon wissen, manuell. Jede Hinzufügung von Details würde uns helfen, eine richtige Antwort zu finden. Setzen Sie Haltepunkte durch die Anfrage auf Schritt und sehen, ob Sie die integer

create_table „my_object_times“ beschmutzen können, Kraft: Kaskade tun | t | ... t.integer "time_in_ms", Grenze: 8

t.integer - so wie Ihr Täter mir aussieht. ... Nun, ich habe versucht, mein letzter Gedanke ist, dass es zu einer Art Rails Anfrage Middleware bezogen werden muss, aber ich weiß nicht, was die Besonderheiten sein könnten. Etwas im Anforderungspfad denkt, dass die Spalte eine ganze Zahl ist. Ich habe nicht verstanden, wie Rails Migrations-Datentypen bisher funktioniert haben, also habe ich etwas gelernt. (Und ich ging den ganzen Tag angeln, also zähle ich diesen Tag zu einem Sieg.) Viel Glück!

+0

Ich verstehe nicht, was Sie von mir wollen. Welche zusätzlichen Informationen könnten helfen? – Dave

+1

Ich weiß es ehrlich gesagt nicht, ich versuche nur darüber nachzudenken, was ich tun würde. Ich würde bestätigen, dass das Datenschema eine Bigint in der tatsächlichen DB-Spalte für time_in_milliseconds zeigt. Die Fehlermeldung zeigt definitiv einen Teil des Systems an (ich bin kein Rails-Experte, aber Active Record sieht so aus), dass der Wert eine ganze Zahl sein sollte, nicht bigint ... posten Sie Ihr Modell, Samen, Migrationen und Tabellenstrukturausgabe von PostGre, vielleicht? –

+0

Ich habe die db/schema.rb in meine Frage aufgenommen und auch in meiner Frage wurde die "\ d my_object_times" Definition von der PostGresdb enthalten. – Dave

1

Ich denke, die Tabelle my_object_times wird möglicherweise nicht aus der Datei schema.rb erstellt oder in anderen Migrationsdateien überschrieben. Denn in der Migrationsdatei ist die Integer-Spalte mit Limit 8 selbst eine bigint. Sie sollten also die Tabellendefinition vom PG-Administrator überprüfen.Wenn die Spalte nicht BigInt führen Sie dann die folgenden Migrations

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 
Verwandte Themen