Can I use a jsonb field as a foreign_key in a belongs_to association? Something along the lines of:
belongs_to :product, class_name: "Product", foreign_key: "data ->'product_id'"
Can I use a jsonb field as a foreign_key in a belongs_to association? Something along the lines of:
belongs_to :product, class_name: "Product", foreign_key: "data ->'product_id'"
References can be defined only between columns (or groups of columns), as it is stated in the documentation:
FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
product_id
, without any form of FOREIGN KEY
, rails has no problem using that column to create associations and the correct queries. I guess my point being your link to the PostgreSQL docs have nothing to to with the ability of rails belongs_to
/has_many
to configure and create associations, otherwise polymorphic associations would be impossible –
Hipparch foreign_key: true
option has nothing to do with the association directly. that is only applicable to the migration, i.e. #references
method. They are two completely separate modules that do not require method interop in any way. Your link to the PostgreSQL docs still has nothing to do with the question. a more relevant link would be the link you placed in the comments; or this issue, that mentions raw sql is not supported, which is the real reason: github.com/rails/rails/issues/29607 –
Hipparch you can use activerecord-json-associations to use PostgreSQL JSONB fields to store association information of your models
As was discussed in comments to answer that @klin gave , it not possible to do in ActiveRecord out of the box.
However I came up with a maintable approach that works much better, in a similar situation in my project.
I'm utilizing a database feature (if you can control underlying DB) - Generated or Virtual columns are well suited for this task
ALTER TABLE orders ADD COLUMN product_id BIGINT GENERATED ALWAYS AS (CAST(data->>'product_id' AS BIGINT)) STORED;
CREATE INDEX IF NOT EXISTS "index_orders_on_product_id" ON "cq_shopify"."orders" ("product_id");
Now you are making DB do what it does best - store data and run essentially a stored procidure to maintain data integrity.
Since you now have a virtual or generate field called product_id
you can use normal belongs_to :products
in your Rails app
To keep this in you project - just add it as a migration to your code.
© 2022 - 2024 — McMap. All rights reserved.
SELECT * FROM products INNER JOIN instructions ON products.id = instructions.data->'product_id'
would still be valid SQL without theFOREIGN KEY
constraint, no? – Hipparch