我的目标是通过一个 REST 请求创建嵌套资源。REST 请求通过 XML 文档表示。这对于单个资源来说很好,但我无法为嵌套资源管理它。好的,接下来我给你举个小例子。
首先新建一个rails项目
rails forrest
接下来我们生成两种资源的脚手架,树木和鸟巢。
./script/generate scaffold tree name:string
./script/generate scaffold bird_nest tree_id:integer bird_type:string eggs_count:integer
在文件 ./forrest/app/models/tree.rb 我们在下面插入“has_many”行,因为一棵树可以有很多鸟巢:-)
class Tree < ActiveRecord::Base
has_many :bird_nests
end
在文件 ./forrest/app/models/bird_nest.rb 中,我们在下面插入“belongs_to”行,因为每个鸟巢都应该属于一棵树。
class BirdNest < ActiveRecord::Base
belongs_to :tree
end
之后我们设置数据库并启动服务器:
rake db:create
rake db:migrate
./script/server
只需将此 XML 片段复制并粘贴到名为“tree.xml”的文件中...
<tree>
<name>Apple</name>
</tree>
...并通过 cURL 将其发布到服务以创建新树:
curl -H 'Content-type: application/xml' -H 'Accept: application/xml' -d @tree.xml http://localhost:3000/trees/ -X POST
这工作正常。也为燕窝 XML(文件名“bird-nest.xml”)分开。如果我们发送这个...
<bird-nest>
<tree-id>1</tree-id>
<bird-type>Sparrow</bird-type>
<eggs-count>2</eggs-count>
</bird-nest>
...也通过以下 cURL 语句。该资源已正确创建!
curl -H 'Content-type: application/xml' -H 'Accept: application/xml' -d @bird-nest.xml http://localhost:3000/bird_nests/ -X POST
好的,到目前为止一切都很好。现在到了橡胶与道路相遇的地方。我们在一个请求中创建这两种资源。所以这里是包含一个鸟巢的树的 XML:
<tree>
<name>Cherry</name>
<bird-nests>
<bird-nest>
<bird-type>Blackbird</bird-type>
<eggs-count>2</eggs-count>
</bird-nest>
</bird-nests>
</tree>
我们再次使用 cURL 触发适当的请求......
curl -H 'Content-type: application/xml' -H 'Accept: application/xml' -d @tree-and-bird_nest.xml http://localhost:3000/trees/ -X POST
...现在我们将在树的控制器的(生成的)“创建”方法中得到一个服务器错误:AssociationTypeMismatch (BirdNest expected, got Array)
在我看来,这是服务器日志中关于接收到的属性和错误消息的重要部分:
Processing TreesController#create (for 127.0.0.1 at 2009-02-17 11:29:20) [POST]
Session ID: 8373b8df7629332d4e251a18e844c7f9
Parameters: {"action"=>"create", "controller"=>"trees", "tree"=>{"name"=>"Cherry", "bird_nests"=>{"bird_nest"=>{"bird_type"=>"Blackbird", "eggs_count"=>"2"}}}}
SQL (0.000082) SET NAMES 'utf8'
SQL (0.000051) SET SQL_AUTO_IS_NULL=0
Tree Columns (0.000544) SHOW FIELDS FROM `trees`
ActiveRecord::AssociationTypeMismatch (BirdNest expected, got Array):
/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:150:in `raise_on_type_mismatch'
/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:146:in `replace'
/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:146:in `each'
/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:146:in `replace'
/vendor/rails/activerecord/lib/active_record/associations.rb:1048:in `bird_nests='
/vendor/rails/activerecord/lib/active_record/base.rb:2117:in `send'
/vendor/rails/activerecord/lib/active_record/base.rb:2117:in `attributes='
/vendor/rails/activerecord/lib/active_record/base.rb:2116:in `each'
/vendor/rails/activerecord/lib/active_record/base.rb:2116:in `attributes='
/vendor/rails/activerecord/lib/active_record/base.rb:1926:in `initialize'
/app/controllers/trees_controller.rb:43:in `new'
/app/controllers/trees_controller.rb:43:in `create'
所以我的问题是关于 XML 资源的嵌套我做错了什么。哪个是正确的 XML 语法?还是我必须手动修改树的控制器,因为生成的控制器没有涵盖这种情况?