Create rest complex resource instance in a single rest call
I would like to create complex rest object instances with a single rest call using rails. In the example case below I get an error in the controller when I call new on Person with a parameter hash.
I 开发者_JAVA百科get an error for unexpected type when seeing a ActiveSupport::HashWithIndifferentAccess and not a PhoneNumber
The hash passed from the test contains an array of Hash objects, while the controller action parameters create ActiveSupport::HashWithIndifferentAccess objects.
- Any suggestions to fix the error?
- Is there an easier way to create complex activerecord objects with a single rest call.
ie models:
class Person < ActiveRecord::Base
has_many :phone_numbers , :autosave => true
class PhoneNumber < ActiveRecord::Base
belongs_to :person
person_controller_test.rb
test "should create person" do
newperson=Person.new(:name => "test")
newperson.phone_numbers << PhoneNumber.new(:number => "123-4567")
person_string= newperson.to_xml(:include => :phone_numbers)
person_hash=Hash.from_xml(course_string)
person_hash2=person_hash['person']
post :create, :person => person_hash2, :format => "xml"
assert_response :success
end
person_controller.rb
def create
@person = Person.new(params[:person])
class Person < ActiveRecord::Base
has_many :phone_numbers , :autosave => true
# this is important for create complex nested object in one call
accepts_nested_attributes_for :phone_numbers
end
class PhoneNumber < ActiveRecord::Base
belongs_to :person
end
person_controller_test.rb
test "should create person" do
newperson=Person.new(:name => "test")
newperson.phone_numbers.build(:number => "123-4567") #more cleaner
# and start from here I'm not sure but this maybe help you
# I think that you must pass a json object
post :create, :person => newperson.to_json(:include => :phone_numbers), :format => "xml"
assert_response :success
end
link: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Dinatih, Thanks for the helpful answer! It helped solve the issue.
I ran into a slight problem since with "accepts_nested_attributes_for :phone_numbers", the hash key 'phone_numbers_attributes' is needed instead of the to_xml/to_json serialization default of 'phone_numbers'. The test code (below) looks a little ugly, but it passes and creates the object correctly. Also passing json to the post method unfortunately doesn't create the object.
test "should create complex person" do
newperson=Person.new(:name => "test")
newperson.phone_numbers.build(:number => "123-4567")
person_string= newperson.to_xml(:include => :phone_numbers)
person_hash=Hash.from_xml(person_string)
person_hash2=person_hash['person']
person_hash2[:phone_numbers_attributes] = person_hash2['phone_numbers']
person_hash2.delete('phone_numbers')
p person_hash2
post :create, :person => person_hash2, :format => "xml"
p response.body
assert_select "person" do
assert_select "name", {:text=>"test"}
assert_select "phone-numbers" do
assert_select "phone-number" do
assert_select "number", {:text=>"123-4567"}
end
end
end
assert_response :success
end
you should also check out:
- Gem nested_form :
- https://github.com/ryanb/nested_form
- examples for nested_form: https://github.com/ryanb/complex-form-examples/tree/nested_form
and
- RailsCasts 196 / 197
- http://railscasts.com/episodes/196-nested-model-form-part-1
- http://railscasts.com/episodes/197-nested-model-form-part-2
精彩评论