0

In my app I have model PurchaseOrder and PurchaseOrderList. When I create a purchase order it updates both tables purchase_orders and purchase_order_lists with a nested form.

Now I want to be able to add a button update stock on purchase_orders/show. When I click this button a new record will be created on table stockdiaries with same products, units and prices as on the purchase order.

The logic is that first I create a purchase order and then I click the button to update stock when goods are received.

The best I came up with is to create this method on PurchaseOrders controller:

 def update_stock
   @purchase_order_list = PurchaseOrderList.where(PURCHASE_ORDER: params[:ID])
   @stockdiary = Stockdiary.create(PRODUCT: @purchase_order_list.PRODUCT, UNITS: @purchase_order_list.UNITS, PRICEBUY: @purchase_order_list.PRICEBUY)
   flash[:notice] = "Stock updated successfully."
   redirect_to(:action => 'show', :ID => @purchase_order.ID)
 end

and in my purchase_orders/show:

<%= link_to "Update Stock", { controller: :purchase_orders, action: :update_stock, ID: @purchase_order.ID} %>

but it raises error

undefined method `PRODUCT' for
#<PurchaseOrderList::ActiveRecord_Relation:0x007f1efeff4898>

But there is a column PRODUCT on purchase_order_lists table.

Note that I included in the method only columns that are common to purchase_order_lists and stockdiaries as others (as id or status) are not concerned on this question. Columns names are capital as I'm building the app on existing db.

What is the correct way to create a stockdiary from a purchase order?

1 Answer 1

1

Updated

Rails is returning an an ActiveRecord Relation from this query:

@purchase_order_list = PurchaseOrderList.where(PURCHASE_ORDER: params[:ID])

This is because you used where, so ActiveRecord returns a relation that could potentially have multiple records in it. If you only want one record, or even if you know that there will only be one record then you should use find_by

So you can either do:

# change where to find_by
@purchase_order_list = PurchaseOrderList.find_by(PURCHASE_ORDER: params[:ID])
# and then this will work
@stockdiary = Stockdiary.create(PRODUCT: @purchase_order_list.PRODUCT, UNITS: @purchase_order_list.UNITS, PRICEBUY: @purchase_order_list.PRICEBUY)

OR... If you want where or there might be multiple records, then you can loop:

@purchase_order_list = PurchaseOrderList.where(PURCHASE_ORDER: params[:ID])
# and then loop through you potentially multiple records in @purchase_order_list
@purchase_order_list.each do |po|
  @stockdiary = Stockdiary.create(PRODUCT: po.PRODUCT, UNITS: po.UNITS, PRICEBUY: po.PRICEBUY)
end

or use first:

@stockdiary = Stockdiary.create(PRODUCT: @purchase_order_list.first.PRODUCT, UNITS: @purchase_order_list.first.UNITS, PRICEBUY: @purchase_order_list.first.PRICEBUY)

Usually this means you didn't place accepts_nested_attributes_for in the PurchaseOrder model.

PurchaseOrder

class PurchaseOrder
  accepts_nested_attributes_for :purchase_order_list
end

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for your answer. But I already placed that in my model. I can create purchase orders with a nested form and it creates records correctly on purchase_order_lists table. That wouldn't work if I hadn't.
And anyway as far as i know the correct syntax is` accepts_nested_attributes_for :purchase_order_lists` (plural)
ok, yea. I had a typo and I didn't read your question very carefully. Now I get it. Let me look and see. I know I've had that error in a similar case before
ok, @Catmal updated. Change where to find_by if you only want one record, or if you want multiple records then you should loop through @purchase_order_list and create one Stockdiary for each, depending on your requirements
Yes that was it thanks a lot. I need to loop tho (I want to create a stockdiary for each purchase_order_list). But I'm not sure about the syntax. Could you give me an example if it's not too bother?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.