PG::NotNullViolation: ERROR: null value in column "id" violates not-null constraint - ruby-on-rails

I am getting this error when I try to add a new case
PG::NotNullViolation: ERROR: null value in column "id" violates not-null constraint DETAIL: Failing row contains (null, nini, momo, 2023-01-21, 2023-01-31, rwe, rwe, Upper, 18, Report_Cards_-_K-9_Three_Term.pdf, application/pdf, 847591, 2023-01-27 01:46:36.772805, ewr, werr, 449, f, f, f, T4-1007-0001_2020.pdf, application/pdf, 60955, 2023-01-27 01:46:36.803862, null, null, null, null, null, null, null, null, null, null, null, null, 2023-01-27 01:46:36.867886, 2023-01-27 01:46:36.867886). : INSERT INTO "cases" ("pt_first_name", "pt_last_name", "date_received", "due_date", "ship", "shade", "finished", "outsourced", "mould", "upper_lower", "implant_brand", "implant_quantity", "invoice_file_name", "invoice_content_type", "invoice_file_size", "invoice_updated_at", "invoice2_file_name", "invoice2_content_type", "invoice2_file_size", "invoice2_updated_at", "number", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24) RETURNING "id"
Recently I clone my app from heroku and I pull all the database from there then when I added a new migration with new column I got the error
def self.up
change_table :cases do |t|
t.attachment :invoice2
t.attachment :invoice3
t.attachment :invoice4
t.attachment :invoice5
t.timestamps
end
end
def self.down
remove_attachment :cases, :invoice2
remove_attachment :cases, :invoice3
remove_attachment :cases, :invoice4
remove_attachment :cases, :invoice5
end
in my schema
create_table "cases", force: :cascade do |t|
t.string "pt_first_name"
t.string "pt_last_name"
t.date "date_received"
t.date "due_date"
t.string "shade"
t.string "mould"
t.string "upper_lower"
t.integer "user_id"
t.string "invoice_file_name"
t.string "invoice_content_type"
t.integer "invoice_file_size", limit: 8
t.datetime "invoice_updated_at"
t.string "implant_brand"
t.string "implant_quantity"
t.integer "number"
t.boolean "finished"
t.boolean "ship"
t.boolean "outsourced"
t.string "invoice2_file_name"
t.string "invoice2_content_type"
t.integer "invoice2_file_size", limit: 8
t.datetime "invoice2_updated_at"
t.string "invoice3_file_name"
t.string "invoice3_content_type"
t.integer "invoice3_file_size", limit: 8
t.datetime "invoice3_updated_at"
t.string "invoice4_file_name"
t.string "invoice4_content_type"
t.integer "invoice4_file_size", limit: 8
t.datetime "invoice4_updated_at"
t.string "invoice5_file_name"
t.string "invoice5_content_type"
t.integer "invoice5_file_size", limit: 8
t.datetime "invoice5_updated_at"
t.datetime "created_at"
t.datetime "updated_at"
end
Let me know if there more information do you need! Thanks in advance.

That migration seems like it creates a null: false constraint. Presumably the existing rows in your DB do not have any values there. To fix this you would have to be able to pass an option to the migration to tell it that you want the column to be nullable.
Are you using Paperclip? Paperclip has been deprecated in favor of activestorage, but one of its open bugs was that the t.attachment migration didn’t pass on options correctly, so even if you did use a null: true option, it might not work. In this case the solution would be to move to active storage, or use a fork of paperclip that is up to date (there is one recommended in that paperclip issue.

Related

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "channels" does not exist

I'm trying to deploy to Heroku and I was getting the sqlite3 error so I followed the instructions on https://devcenter.heroku.com/articles/sqlite3
to switch to postgres but now I'm getting an error when I run rails db:migrate.
I've already tried dropping the database and creating it again with rails db:drop db:create, but haven't been able to get it to work.
My migration:
class CreateRooms < ActiveRecord::Migration[5.2]
def change
create_table :rooms do |t|
t.string :name
t.text :description
t.integer :session_id
t.references :channel, foreign_key: true
t.timestamps
end
end
end
In my room model:
class Room < ApplicationRecord
belongs_to :channel
has_many :users
end
In my Channel model:
class Channel < ApplicationRecord
has_many :rooms, dependent: :destroy
has_many :registrations, dependent: :destroy
has_many :users, through: :registrations
end
I get this error when running rails db:migrate
PG::UndefinedTable: ERROR: relation "channels" does not exist
: CREATE TABLE "rooms" ("id" bigserial primary key, "name" character varying, "description" text, "session_id" integer, "channel_id" bigint, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_1f9c11d4ad"
FOREIGN KEY ("channel_id")
REFERENCES "channels" ("id")
)
/CIS-196/final-project/db/migrate/20201128050333_create_rooms.rb:3:in `change'
bin/rails:4:in `<main>'
Caused by:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "channels" does not exist
: CREATE TABLE "rooms" ("id" bigserial primary key, "name" character varying, "description" text, "session_id" integer, "channel_id" bigint, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_1f9c11d4ad"
FOREIGN KEY ("channel_id")
REFERENCES "channels" ("id")
)
/CIS-196/final-project/db/migrate/20201128050333_create_rooms.rb:3:in `change'
bin/rails:4:in `<main>'
Caused by:
PG::UndefinedTable: ERROR: relation "channels" does not exist
/CIS-196/final-project/db/migrate/20201128050333_create_rooms.rb:3:in `change'
bin/rails:4:in `<main>'
Tasks: TOP => db:migrate
This is the schema:
ActiveRecord::Schema.define(version: 2020_12_12_224511) do
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.integer "record_id", null: false
t.integer "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum", null: false
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "channels", force: :cascade do |t|
t.string "name"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "registrations", force: :cascade do |t|
t.integer "channel_id"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["channel_id"], name: "index_registrations_on_channel_id"
t.index ["user_id"], name: "index_registrations_on_user_id"
end
create_table "rooms", force: :cascade do |t|
t.string "name"
t.text "description"
t.integer "channel_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "session_id"
t.index ["channel_id"], name: "index_rooms_on_channel_id"
end
create_table "users", force: :cascade do |t|
t.string "username"
t.string "name"
t.string "email", default: "", null: false
t.string "password_hash"
t.text "bio"
t.integer "room_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.index ["room_id"], name: "index_users_on_room_id"
end
end
These are the migration files:
screenshot of migration files
Your rooms table references the channel table. Therefore you need to create the channel table before you create the rooms table. You need to rename the migration which creates the channels table so that it appears before the migration that creates the rooms table.
Thus rename 20201128050352_create_channels.rb to 20201128050332_create_channels.rb so it will run before 20201128050333_create_rooms.rb. Then run rails db:drop db:create db:migrate.

PG::DuplicateColumn: ERROR: column "product_id" of relation "users" already exists

I have seen this question posted several times and the solution is always to drop the database and recreate it. I have data in my database and hence do not want to do that.
Schema:
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "product_id"
end
My second to last migration file:
class AddProductIdToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :product_id, :string
end
end
I have no other migration file that creates a product_id column on my current branch.
I have multiple branches with different database schema. I am wondering if that caused the issue. The branch that might have created the product_id is only there for reference now. It will not be merged to master.
How do I fix this issue? I have tried:
rake db:rollback step=3
rake db:migrate
but that did not work.
Your create_table is already creating product_id inside the database.
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "product_id" // <- note this line
end
And you are trying to add another column of same name in your table, which raises an error.

Rails 5.2 ActiveStorage with UUIDs on Postgresql

We have our app using uuids are primary keys, on a Postgresql Database. (Standard setup described here).
We integrated ActiveStorage following the process described here. A standard setup using rails active_storage:install and migrated using rails db:migrate.
We have a model & corresponding controller as follows:
# Model
class Message < ApplicationRecord
has_one_attached :image
def filename
image&.attachment&.blob&.filename
end
end
# Controller
class MessagesController < ApplicationController
def create
message = Message.create!(message_params)
redirect_to message
end
private
def message_params
params.require(:message).permit(:title, :content, :image)
end
end
We observed that the first few sets of image were correctly associated with the model instances, but then we used to get random images for model instance, or got no image at all. Every time, we restart the server, we get first few images right, but then it was unpredictable.
Unsure, of what's going wrong, we debugged in rails console:
params[:image]
=> #<ActionDispatch::Http::UploadedFile:0x007fcf2fa97b70 #tempfile=#<Tempfile:/var/folders/dt/05ncjr6s52ggc4bk6fs521qw0000gn/T/RackMultipart20180726-8503-vg36kz.pdf>, #original_filename="sample.pdf", #content_type="application/pdf", #headers="Content-Disposition: form-data; name=\"file\"; filename=\"sample.pdf\"\r\nContent-Type: application/pdf\r\n">
On saving the instance and retrieving file name we got a random file, we uploaded previously.
#message = Message.new(message_params)
#message.filename
=> #<ActiveStorage::Filename:0x007fcf32cfd9e8 #filename="sample.pdf">
#message.save
#message.filename
=> #<ActiveStorage::Filename:0x007f82f2ad4ef0 #filename="OtherSamplePdf.pdf">
Looking for an explanation for this weird behaviour, and a possible solution too.
After hours of going line by line in the activestorage source code, and running the same commands
#message = Message.new(message_params)
#message.save
again and again. We got same random results again and again. Then we went through the logs rails printed while attaching the image to message and observed the following:
S3 Storage (363.4ms) Uploaded file to key: KBKeHJARTjnsVjkgSbbii4Bz (checksum: S0GjR1EyvYYbMKh44wqlag==)
ActiveStorage::Blob Create (0.4ms) INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "metadata", "byte_size", "checksum", "created_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["key", "KBKeHJARTjnsVjkgSbbii4Bz"], ["filename", "sample.pdf"], ["content_type", "application/pdf"], ["metadata", "{\"identified\":true}"], ["byte_size", 3028], ["checksum", "S0GjR1EyvYYbMKh44wqlag=="], ["created_at", "2018-07-26 04:54:33.029769"]]
ActiveStorage::Attachment Create (2.7ms) INSERT INTO "active_storage_attachments" ("name", "record_type", "record_id", "blob_id", "created_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["name", "file"], ["record_type", "Message"], ["record_id", "534736"], ["blob_id", "0"], ["created_at", "2018-07-26 05:04:35.958831"]]
record_id was being set as 534736, instead of an uuid. Here's where we went wrong.
Active storage was expecting integer foreign key to our Message model, and we wanted it to use uuids instead. So we had to fix our migration, to use uuids instead of integer foreign keys.
Solution:
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
def change
create_table :active_storage_blobs, id: :uuid do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.bigint :byte_size, null: false
t.string :checksum, null: false
t.datetime :created_at, null: false
t.index [ :key ], unique: true
end
create_table :active_storage_attachments, id: :uuid do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false, type: :uuid
t.references :blob, null: false, type: :uuid
t.datetime :created_at, null: false
t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
end
end
end
Hope this helps, someone facing similar issues. cheers!
I'm late to the party hitting this in 2020 but as anurag mentioned this is due to the active_storage_attachments DB table using a bigint for the record_id. I wasn't able to migrate all the models with ActiveStorage attachments to use UUIDs so I needed a way to support both UUIDs and bigints at the same time.
Warning: If you can avoid this (by migrating everything to UUID most likely) then I'd strongly recommend doing that, and I plan on doing that as soon as we have time.
Warnings aside, migrating the active_storage_attachments table to change the record_id column to be text does work. I had to adjust the few places in our app where we were joining against the active_storage_attachments table using record_id to cast the value to text in the join. For example I used the following code when joining to a model that had a UUID ID.
.joins("
LEFT OUTER JOIN active_storage_attachments
ON active_storage_attachments.record_id = documents.id::text
")
Hopefully this helps someone else who is stuck in the halfway state where not all ActiveStorage using models are using UUIDs or bigint IDs.
I also had this issue. My models all use UUIDs. As I had no records in ActiveStorage needing to be retained, I dropped and recreated the :active_storage_attachments and :active_storage_blobs tables. Here is my migration, in case it's of use to anyone. Using Rails 6.0.4.
def change
reversible do |dir|
dir.up do
drop_table :active_storage_attachments
drop_table :active_storage_blobs
create_table "active_storage_blobs", id: :uuid,
default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.bigint :byte_size, null: false
t.string :checksum, null: false
t.datetime :created_at, null: false
t.index [ :key ], unique: true
end
create_table "active_storage_attachments", id: :uuid,
default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false, type: :uuid
t.references :blob, null: false, type: :uuid
t.datetime :created_at, null: false
t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
dir.down do
drop_table :active_storage_attachments
drop_table :active_storage_blobs
# original tables generated by rails
create_table :active_storage_blobs do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.bigint :byte_size, null: false
t.string :checksum, null: false
t.datetime :created_at, null: false
t.index [ :key ], unique: true
end
create_table :active_storage_attachments do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false
t.references :blob, null: false
t.datetime :created_at, null: false
t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
end
end

PG::Error: ERROR: null value in column "uid" violates not-null constraint

So, I setup a staging, and develop branch and now I'm getting this error when registering a new user locally:
PG::Error: ERROR: null value in column "uid" violates
not-null constraint DETAIL: Failing row contains
(7, test#gmail.com, $2a$10$WfiHKzYq4ovZtZoVAB.fRertuOSWezZYBw.RxkSqfBK89WbzcYxDK,
null, null, null, 0, null, null, null, null,
2013-08-13 07:20:13.484617, 2013-08-13 07:20:13.484617,
null, null, null, null). : INSERT INTO "users"
("created_at", "email", "encrypted_password", "updated_at")
VALUES ($1, $2, $3, $4) RETURNING "uid"
schema.rb snippit
create_table "users", id: false, force: true do |t|
t.integer "id", null: false
t.string "email", default: ""
t.string "encrypted_password", default: ""
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "admin"
t.string "provider"
t.string "uid", null: false
t.string "username"
end
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
I can't push any new code to production until this is worked out, which is annoying :/
Your uid is not-nullable but you aren't giving any values to it. Have your application generate one while you are registering users.
Ruby has a module named Secure Random which can be used to generate uids. It's usage is also pretty easy. Like,
require 'securerandom'
uid = SecureRandom.hex(10)
However, you can use factory girl to initialize your objects. For testing purpose though.
The problem is that your code to create a new user in the database is not defining a uid value for the row. Your database has constrained that field to disable rows from ever having uid as null. Therefore, you should either remove this constraint from the database or change your code to pass through a uid.

Error while saving floats to PostgreSQL from Rails

I just recently made the switch over to PostgreSQL.. and just wondering about this issue:
PG::Error: ERROR: column "bathrooms" is of type double precision but expression is of type character varying at character 161
HINT: You will need to rewrite or cast the expression.
: INSERT INTO "properties" ("address", "bathrooms", "bedrooms", "city", "country", "created_at", "description", "name", "state", "updated_at", "zip") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id"
Migration looks like this:
class CreateProperties < ActiveRecord::Migration
def change
create_table :properties do |t|
t.string :name
t.string :address
t.string :city
t.string :state
t.string :zip
t.string :country
t.float :bedrooms
t.float :bathrooms
t.string :country
t.text :description
t.timestamps
end
end
end
I switched the float to decimal, it seems PostgreSQL is fine with that implicit cast now?
Either way the error is gone, thanks

Resources