How to intercept accepts_nested_attributes_for?

I have a Rails application with two models: SalesTransactions and PurchaseOrders.

In the PurchaseOrders model, new records are registered using "purchase_order_number" as the key field. I use the model’s create method to search if this “purchase_order_number” was previously registered, and if so, reuse this entry and use your identifier in the SalesTransaction entry. If this name has not been registered yet, I proceed and create, and then use the new PurchaseOrder record identifier in SalesTransaction (foreign_id link to the associated PO).

Please note that I do not have an existing PurchaseOrder record identifier until I have searched in the create method (so this is not a question “how do I update a record using“ accepts_nested_attributes_for "?”, I can do this as soon as I have the ID )

In some situations, my application registers a new SalesTransaction and simultaneously creates a new PurchaseOrder. It uses accepts_nested_attributes_for to create a PurchaseOrder record.

The problem is that when using "accepts_nested_attributes_for" creation is not called, so my model is not able to intercept the creation and search if "purchase_order_number" is already registered and handles this case.

I would appreciate advice on how to intercept the "accepts_nested_attributes_for" creations to allow some preprocessing (that is, look if the PurchaseOrder entry with this number already exists, and if so, use it).

Not all Sales have a PurchaseOrder, so a PurchaseOrder entry is optional in SalesTransaction.

(I saw kludge involving: reject_if, but this does not allow me to add the existing record identifier as foreign_id in the parent record.)

Thanks.

+4
source share
4 answers

Well, I left this question for a while and offered generosity, but I don't have the answer I'm looking for (although I certainly appreciate that people are trying to help).

I will conclude that I did not miss some trick, and at the time of writing, there is no clear solution, only workarounds.

As such, I'm going to rewrite my application to avoid using accept_nested_attributes_for, and publish the SalesTransaction and PurchaseOrder entries separately, so in both cases, you can use the create code.

Shame like accept_nested ... in this case is pretty cool, but in this case it is not complete enough.

I still love Rails; -)

0
source

You can use validate and save callbacks to do what you need.

Assuming installation:

 class SalesTransaction < ActiveRecord::Base belongs_to :purchase_order, :foreign_key => "po_purchase_order_no", :primary_key => "purchase_order_no" accepts_nested_attributes_for :purchase_order end class PurchaseOrder < ActiveRecord::Base has_many :sales_transactions, :foreign_key => "po_purchase_order_no", :primary_key => "purchase_order_no" before_validation :check_for_exisitng_po # maybe only on create? accepts_nested_attributes_for :sales_transactions private def check_for_exisitng_po existing_po = PurchaseOrder.find_by_purchase_order_no(self.purchase_order_no) if existing_po self.id = existing_po.id self.reload # don't like this, also will overwrite incoming attrs @new_record = false # tell AR this is not a new record end true end end 

This should again enable the use of accepts_nested_attributes_for again.


gist w / tests

+1
source

Two ideas: did you look at association callbacks? Perhaps you can "hook" accepts_nested_attributes_for at this level using: before_add to check if it is already in the database before creating a new record.

Another idea is to run a post process instead. In after_save / update, you can search for all records with a name (which must be unique), and if there are more than one to combine them.

0
source

I was going to write a before_save function, but you say this:

It uses accepts_nested_attributes_for to create a PurchaseOrder record.

So, in the SalesTransaction process SalesTransaction , why bother looking? You should just get the next one available ... there should be no reason to look for something that did not exist before NOW.

0
source

All Articles