Validation and rejection on accepts_nested_attributes

Viewed 33

I'm having trouble wrapping my head around accepts_nested_attributes_for and the best way to integrate it into my process.

I have a collection of Cartons which have a ProductCode and CartonNumber assigned through the ProductCarton join table. ProductCode and CartonNumber are unique, so whenever a new carton is created, the Carton is assigned to the respective ProductCarton id if it exists, otherwise it's created.

Example:
ProductCarton(1) = ProductCode1-CartonNumber1
ProductCarton(2) = ProductCode2-CartonNumber1
ProductCarton(3) = ProductCode1-CartonNumber2
etc

Now if a new Carton is created with ProductCode1-CartonNumber1, it's id is 1 as it already exists.

class ProductCarton < ApplicationRecord
  has_many :cartons
  # product_code and carton_number both contain a unique :name field
  belongs_to :product_code
  belongs_to :carton_number

The reason for this is for the SaleOrder and SaleOrderRule model, A user can specify a ProductCarton and a quantity with which can be picked from, any Carton with the associated ID is eligible to be picked.

My problem begins here, I'm struggling on where and how to implement the validation for insert rules as a few things need to happen:

  • Resolve the entered ProductCode and CartonNumber to ProductCarton id (if there is one, otherwise display an error)
  • Check quantity specified is not greater than the number of Cartons in stock with the id of ProductCarton

So I have my SaleOrder controller accepting a list of nested parameters

     sale_order_rules_attributes: [
       :quantity,
       product_carton_attributes: [
         product_code_attributes: [
           :product_code
         ],
         carton_number_attributes: [
           :carton_number
         ]
       ]

     ])

Obviously all this currently does is created a new set of everything if it doesn't exist, which isn't what i want to do, I'm just trying to find the "Rails" way to go about resolving the ProductCarton relationship and assigning it as well as properly handling the errors that can occur through the whole process, my initial attempt was resolving it in the SaleOrder model with a before_validation, but i couldn't figure out how to add/remove the rules if they didn't pass the requirements.

Sorry if this is a ramble, any help is much appreciated.

1 Answers

Smth like

# controller

def create
  product_cartons = ProductCarton.where(...)
  @sale_order = SaleOrder.new(
    product_cartons = product_cartons
    ...
  )

  if @sale_order.save
    # render success
  else
    # validation failed, render errors
  end
end

# sale_order.rb

class SaleOrder
  validate :in_stock
  ...

  def in_stock
    unless product_cartons.each(&:in_stock?)
        errors.add(:product_cartons, :out_of_stock)
    end
  end
end
Related