2

I've built a small API that, when posted a JSON object, creates the representative model records. The data looks like this:

{
  "customer": {
    "email": "[email protected]",
    "first_name": "Michael T. Smith",
    "last_name": "",
    "shipping_address_1": "",
    "telephone": "5551211212",
    "source": "Purchase"
  },
  "order": {
    "system_order_id": "1070",
    "shipping_address_1": "",
    "billing_address_1": "123 Your Street",
    "shipping": "0",
    "tax": "0",
    "total": "299",
    "invoice_date": 1321157461,
    "status": "PROCESSING",
    "additional_specs": "This is my info!",
    "line_items": [
      {
        "quantity": "1",
        "price": "239",
        "product": "Thing A",
        "comments": "comments"
        "specification": {
          "width": "12",
          "length": "12",
        },
      },
      {
        "quantity": "1",
        "price": "239",
        "product": "Thing A",
        "comments": "comments"
        "specification": {
          "width": "12",
          "length": "12",
        },
      },
    ]
  }
}

The question is how to create the nested objects. My models are setup as such:

class Order < ActiveRecord::Base
  has_many :line_items
  belongs_to :customer

  accepts_nested_attributes_for :line_items
end

class LineItem < ActiveRecord::Base
  belongs_to :order
  has_many :specifications
end

class Specification < ActiveRecord::Base
  belongs_to :LineItem 
end

I'm trying to create the records using this code:

@order = @customer.orders.build(@data[:order])
@order.save

Is there a better way to do this? Currently I'm getting this error: ActiveRecord::AssociationTypeMismatch in ApiController#purchase_request LineItem(#70310607516240) expected, got Hash(#70310854628220)

Thanks!

2 Answers 2

3

accepts_nested_attributes_for defines a new setter method for the association: the original name with _attributes appended to it.

In your case, there is a line_items_attributes= method on your Order model, which is what you need to use to take advantage of the nested attributes feature. Something as simple as swapping the key before building the model would probably work, e.g.:

@data[:order][:line_items_attributes] = @data[:order].delete(:line_items)
@order = @customer.orders.build(@data[:order])
@order.save
Sign up to request clarification or add additional context in comments.

Comments

2

You can use accepts_nested_attributes_for like this: (in my example, Products has_many ProductionItineraries and ProductionItineraries belongs_to Products)

model/product.rb

has_many :production_itineraries, dependent: :delete_all
accepts_nested_attributes_for :production_itineraries, allow_destroy: true

model/production_itinerary.rb

belongs_to :product

To instantiate:

products = Product.new
products.production_itineraries.build(other_production_itineraries_fields)

Doing this, after save products, the production_itinerary object will be save automatically, with the respective product_id field

Comments

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.