Reputation: 578
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!
Upvotes: 2
Views: 4425
Reputation: 41
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
Upvotes: 2
Reputation: 34072
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
Upvotes: 3