Akshay Goyal
Akshay Goyal

Reputation: 925

Rails - Add more nested attributes dynamically

This seems like a pretty trivial problem but i am not able to solve this. I have two tables invoices and invoice_items. In invoice model:

accepts_nested_attributes_for :invoice_items, allow_destroy: true, reject_if: :all_blank

Now in a method based on some conditions i want to add more invoice items dynamically. In before_save callback i am doing something like this:

def process_amounts
  if condition_holds
    self.invoice_items_attributes << {key_1: value_1, key_2: value_2} # Pseudo code.
  end
end

But this piece of code raises errors. Seems like only setter is available for nested_attributes.

NoMethodError Exception: undefined method `invoice_items_attributes' for # Invoice:0x007fd4de84a7a0

I also tried one another approach which results in weird behavior:

def process_amounts
  if condition_holds
    self.invoice_items_attributes = invoice_items.map(&:attributes) + [{key_1: value_1, key_2: value_2}] # Pseudo code.
  end
end

The above piece of code results in 3 items! It doesn't reassign the invoice_items_attributes.

So how to fix this problem?

Upvotes: 0

Views: 42

Answers (2)

Ashutosh Kushwaha
Ashutosh Kushwaha

Reputation: 121

Try this

 if condition_holds
    self.invoice_items << InvoiceItem.new(key_1: value_1, key_2: value_2)
 end

I'm assuming InvoiceItem is the model name for invoice_items.

Upvotes: 1

Sumra Yasmin
Sumra Yasmin

Reputation: 9

invoice_item_attributes is only available in params(Controller). You can do this in model invoice in before_save callback like this.

before_save :process_amounts

def process_amounts
 if condition_holds
   self.invoice_items.build([{key: value, key2: value2},{key: value, key2: value2}])
end

Upvotes: 0

Related Questions