I'm creating an API in rails to expose to an iPhone app that I'm working on. I understand that usually you only create a single resource when posting to the create action of a controller in Rails. However, I'm not sure the best way to go about creating many resources at once. Is it acceptable to post JSON/XML containing multiple resources to be created of the same type in a single POST?
For example, creating a message and then adding many recipients. There is a model for the message itself, and then a model for a recipients that belongs to the message. I create the message by posting to /messages, but then what if I have 50 recipients to add to that message? Making 50 separate POSTs to /messages/1/recipients seems excessive and wasteful. What is the best way to go about this?
I'm new to Rails and RESTful apps in general and very much appreciate any help.
You could use accepts_nested_attributes_for
for this. In your parent model – where you define your has_many
association – you'd add the accepts_nested_attributes_for
giving it the same association name. Much like this:
class Message < ActiveRecord::Base
has_many :recipients
accepts_nested_attributes_for :recipients
end
class Recipient < ActiveRecord::Base
belongs_to :message
end
Then, in your message's form, you'd have a bunch of fields for the recipients named something like message[recipients_attributes][][name]
and message[recipients_attributes][][email]
. Or you could use form_for
and fields_for
(you just have to remember to build at least one instance in your has_many collection when you go to the new
page).
For more (and better) examples, watch this Railscast.
If you are posting XML data, you also need to include type="array". Here's an example:
<message>
<recipients_attributes type="array">
<recipient>
<name>Some Name</name>
<email>example@example.com</email>
</recipient>
<recipient>
<name>Some Name 2</name>
<email>example2@example.com</email>
</recipient>
<recipients_attributes>
</message>
If you don't, you'll get errors like "undefined method `stringify_keys' for Array" and "can't convert String into Integer" depending on your version of Rails. These originate from active_record/nested_attributes.rb.