I’ve got a relatively simple Rails app that takes a form with nested params that includes a photograph. It looks like this:
class List < ActiveRecord::Base
has_many :list_items
has_many :people, through: list_items
end
class ListItem < ActiveRecord::Base
belongs_to :list
belongs_to :person, autosave: true
has_attached_file :picture,
:storage => :s3,
:bucket => 'myfreebielist',
:s3_credentials => {
:access_key_id => ENV['S3_KEY'],
:secret_access_key => ENV['S3_SECRET']
}
def autosave_associated_records_for_person
if new_person = Person.find_by_name(Person.name) then
self.person = new_person
else
self.person.save!
end
end
end
class Person < ActiveRecord::Base
has_many :list_items
end
I set up a test new form, just to make sure everything works, and it does, nice and pretty:
<%= form_for @list do |f| %>
List name: <%= f.text_field :name %><br/>
<%= f.fields_for :list_items do |lif| %>
<%= lif.fields_for :person do |pif| %>
Person name: <%= pif.text_field :name %>
<% end %>
Picture: <%= lif.file_field :picture %>
<br/>
<% end %>
<%= f.submit %>
<% end %>
OK, so I want to be able to post a new list, with list items (and their related picture images), as well as the person for that list item. I have this code that I’m testing with in Objective C:
NSMutableDictionary *listParams = [NSMutableDictionary dictionary];
[listParams setValue:@"Test One" forKey:@"name"];
NSMutableDictionary *listItems = [NSMutableDictionary dictionary];
// Generate each list item -- a person and a photo.
NSDictionary *person1 = [NSDictionary dictionaryWithKeysAndObjects:@"name", @"John Smith", nil];
NSDictionary *listItem1 = [NSDictionary dictionaryWithKeysAndObjects:@"person_attributes", person1, nil];
[listItems setValue:listItem1 forKey:@"0"];
[listParams setValue:listItems forKey:@"list_items_attributes"];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setValue:listParams forKey:@"list"];
[[RKClient sharedClient] post:@"/lists" params:params delegate:self];
This also works fine, with the notable absence of the picture.
Now, I understand that using an RKParams instead of an NSDictionary is how you’re supposed to handle this type of request, but when I post using an RKParams there is all manner of strange things arriving at the rails side — lots of \n newlines, spaces and things around the keys. I tried using an RKParams with an attachment as part of person1, but it seems to just send the string representation of the name of the object RKParams object.
I feel like I’m so, so close but I’ve been hitting my head against this for hours now. Any help would be appreciated.
Environment: Xcode 4.3, Rails 3.2.1.
The answer is: JSON. I had to adjust the server to support JSON, something I should have done at the outset. That’s what all the spaces and
\ns are about. Note to self: don’t program an all-nighter, no matter how motivated you are.