Puneet Pandey
Puneet Pandey

Reputation: 555

Capture key inside rescue block in Rails

I am looking for a simple solution here for the problem statement below:

I have a array of hashes like this:

arr = [
  {group_id: 51, product_id: 34345},
  {group_id: 45, product_id: 22133},
  {group_id: 90, product_id: 10045},
  {group_id: 2,  product_id: 15495},
  {group_id: 23, product_id: 25085}
]

I am running BULK INSERT query based on the unique index of group_id and product_id like this:

GroupProduct.insert_all(arr, unique_by: %i[ group_id product_id ])

This insert statement throws error of ActiveRecord::InvalidForeignKey sometimes:

PG::ForeignKeyViolation: ERROR: insert or update on table "group_products" violates foreign key constraint "fk_rails_a3bed1e3ad" DETAIL: Key (product_id)=(15495) is not present in table "group_products".

So, I would like to perform insert_all operation inside begin-resuce block such that, if a key product_id is not found/present, it will rebuild the array and retry.

Basically, I would like to capture product_id inside rescue block

Here's what I would like to accomplish:

arr = [
  {group_id: 51, product_id: 34345},
  {group_id: 45, product_id: 22133},
  {group_id: 90, product_id: 10045},
  {group_id: 2,  product_id: 15495},
  {group_id: 23, product_id: 25085}
]

begin
  GroupProduct.insert_all(arr, unique_by: %i[ group_id product_id ])
rescue ActiveRecord::InvalidForeignKey => e
  arr = arr.reject {|r| r[:product_id] == PRODUCT_ID_I_WOULD_LIKE_TO_CAPTURE}
  retry
end

Is there a direct way of getting product_id say e.message.product_id?

Upvotes: 0

Views: 581

Answers (1)

Giuseppe Schembri
Giuseppe Schembri

Reputation: 857

begin
  GroupProduct.insert_all(arr, unique_by: %i[ group_id product_id ])
rescue ActiveRecord::InvalidForeignKey => e
  match_on_product_it = /\APG::ForeignKeyViolation:.+\(product_id\)=\((\d+)\)/.match e.message
  arr = arr.reject {|r| r[:product_id] == match_on_product_it[1].to_i}
  retry
end

Upvotes: 1

Related Questions