I have Invoices with many Invoice Line Items. Invoice line items point to a specific item. When creating or updating an Invoice, I'd like to validate that there is not more than 1 invoice line item with the same Item (Item ID). I am using accepts nested attributes and nested forms.
I know about validates_uniqueness_of item_id: {scope: invoice_id}
However, I cannot for the life of me get it to work properly. Here is my code:
Invoice Line Item
belongs_to :item
validates_uniqueness_of :item_id, scope: :invoice_id
Invoice
has_many :invoice_line_items, dependent: :destroy
accepts_nested_attributes_for :invoice_line_items, allow_destroy: true
Invoice Controller
// strong params
params.require(:invoice).permit(
:id,
:description,
:company_id,
invoice_line_items_attributes: [
:id,
:invoice_id,
:item_id,
:quantity,
:_destroy
]
)
// ...
// create action
def create
@invoice = Invoice.new(invoice_params)
respond_to do |format|
if @invoice.save
format.html { redirect_to @invoice }
else
format.html { render action: 'new' }
end
end
end
The controller code is pretty standard (what rails scaffold creates).
UPDATE - NOTE that after more diagnosing, I find that on create it always lets me create multiple line items with the same item when first creating an invoice and when editing an invoice without modifying the line items, but NOT when editing an invoice and trying to add another line item with the same item or modifying an attribute of one of the line items. It seems to be something I'm not understanding with how rails handles nested validations.
UPDATE 2 If I add validates_associated :invoice_line_items
, it only resolves the problem when editing an already created invoice without modifying attributes. It seems to force validation check regardless of what was modified. It presents an issues when using _destroy, however.
UPDATE 3 Added controller code.
Question - how can I validate an attribute on a models has many records using nested form and accepts nested attributes?