Как передать JSON в приложение RAILS, чтобы оно создавало вложенные дочерние объекты в отношении has_many?
Вот что у меня есть:
Два модельных объекта.
class Commute < ActiveRecord::Base
has_many :locations
accepts_nested_attributes_for :locations, :allow_destroy => true
end
class Location < ActiveRecord::Base
belongs_to :commute
end
С Commute у меня настроен стандартный контроллер. Я хотел бы иметь возможность создавать объект Commute, а также несколько дочерних объектов Location за один вызов REST с использованием JSON. Я пробовал такие вещи:
curl -H "Content-Type:application/json" -H "Accept:application/json"
-d "{\"commute\":{\"minutes\":0,
\"startTime\":\"Wed May 06 22:14:12 EDT 2009\",
\"locations\":[{\"latitude\":\"40.4220061\",
\"longitude\":\"40.4220061\"}]}}" http://localhost:3000/commutes
Или, что более читабельно, JSON:
{
"commute": {
"minutes": 0,
"startTime": "Wed May 06 22:14:12 EDT 2009",
"locations": [
{
"latitude": "40.4220061",
"longitude": "40.4220061"
}
]
}
}
Когда я выполняю это, я получаю этот вывод:
Processing CommutesController#create (for 127.0.0.1 at 2009-05-10 09:48:04) [POST]
Parameters: {"commute"=>{"minutes"=>0, "locations"=>[{"latitude"=>"40.4220061", "longitude"=>"40.4220061"}], "startTime"=>"Wed May 06 22:14:12 EDT 2009"}}
ActiveRecord::AssociationTypeMismatch (Location(#19300550) expected, got HashWithIndifferentAccess(#2654720)):
app/controllers/commutes_controller.rb:46:in `new'
app/controllers/commutes_controller.rb:46:in `create'
Похоже, что массив JSON локаций читается, но не интерпретируется как объект Location.
Я могу легко изменить либо клиента, либо сервер, поэтому решение может прийти с любой стороны.
Итак, RAILS позволяет мне это делать? Или мне нужно добавить некоторую поддержку для моего объекта Commute? Возможно добавить метод from_json?
Спасибо за любую помощь.
Поскольку я работал над этим, одним из решений, которое работает, является модификация моего контроллера. Но это не похоже на "рельсовый" способ сделать это, поэтому, пожалуйста, все же дайте мне знать, если есть лучший способ.
def create
locations = params[:commute].delete("locations");
@commute = Commute.new(params[:commute])
result = @commute.save
if locations
locations.each do |location|
@commute.locations.create(location)
end
end
respond_to do |format|
if result
flash[:notice] = 'Commute was successfully created.'
format.html { redirect_to(@commute) }
format.xml { render :xml => @commute, :status => :created, :location => @commute }
else
format.html { render :action => "new" }
format.xml { render :xml => @commute.errors, :status => :unprocessable_entity }
end
end
end