Ach*_*omm 5 ruby xml nested ruby-on-rails
我的目标是通过一个REST请求创建嵌套资源.REST请求通过XML文档表示.这适用于单个资源,但我无法管理嵌套的资源.好的我接下来会给你一个小例子.
首先创建一个新的rails项目
rails forrest
Run Code Online (Sandbox Code Playgroud)
接下来,我们生成两种资源的支架,树木和鸟巢.
./script/generate scaffold tree name:string
./script/generate scaffold bird_nest tree_id:integer bird_type:string eggs_count:integer
Run Code Online (Sandbox Code Playgroud)
在文件./forrest/app/models/tree.rb中,我们在下面插入"has_many"行,因为树可以有许多鸟巢:-)
class Tree < ActiveRecord::Base
has_many :bird_nests
end
Run Code Online (Sandbox Code Playgroud)
在File ./forrest/app/models/bird_nest.rb中,我们在下面插入"belongs_to"行,因为每个鸟巢应该属于一棵树.
class BirdNest < ActiveRecord::Base
belongs_to :tree
end
Run Code Online (Sandbox Code Playgroud)
然后我们设置数据库并启动服务器:
rake db:create
rake db:migrate
./script/server
Run Code Online (Sandbox Code Playgroud)
只需将此XML片段复制并粘贴到名为"tree.xml"的文件中即可...
<tree>
<name>Apple</name>
</tree>
Run Code Online (Sandbox Code Playgroud)
...并通过cURL将其发布到服务以创建新树:
curl -H 'Content-type: application/xml' -H 'Accept: application/xml' -d @tree.xml http://localhost:3000/trees/ -X POST
Run Code Online (Sandbox Code Playgroud)
这很好用.也用于鸟巢XML(文件名"bird-nest.xml").如果我们发送这个......
<bird-nest>
<tree-id>1</tree-id>
<bird-type>Sparrow</bird-type>
<eggs-count>2</eggs-count>
</bird-nest>
Run Code Online (Sandbox Code Playgroud)
...也可以通过以下cURL声明.该资源正确创建!
curl -H 'Content-type: application/xml' -H 'Accept: application/xml' -d @bird-nest.xml http://localhost:3000/bird_nests/ -X POST
Run Code Online (Sandbox Code Playgroud)
好的到目前为止一切都很好.现在,橡胶遇到了道路.我们在一个请求中创建两个资源.所以这里是我们树的XML,它包含一个鸟巢:
<tree>
<name>Cherry</name>
<bird-nests>
<bird-nest>
<bird-type>Blackbird</bird-type>
<eggs-count>2</eggs-count>
</bird-nest>
</bird-nests>
</tree>
Run Code Online (Sandbox Code Playgroud)
我们再次使用cURL触发相应的请求...
curl -H 'Content-type: application/xml' -H 'Accept: application/xml' -d @tree-and-bird_nest.xml http://localhost:3000/trees/ -X POST
Run Code Online (Sandbox Code Playgroud)
...现在我们将在树的控制器的(生成的)"create"方法中得到服务器错误: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'
Run Code Online (Sandbox Code Playgroud)
所以我的问题是我在XML资源的嵌套方面做错了什么.哪个是正确的XML语法?或者我是否必须手动修改树的控制器,因为生成的情况不包括这种情况?
实现此目的的一种方法是重写树模型上的bird_nests=方法。
def bird_nests=(attrs_array)
attrs_array.each do |attrs|
bird_nests.build(attrs)
end
end
Run Code Online (Sandbox Code Playgroud)
这里唯一的问题是您失去了设置器的默认行为,这可能是也可能不是您的应用程序中的问题。
如果您运行的是最新版本的 Rails,您可以按照此处所述打开批量分配:
http://github.com/rails/rails/commit/e0750d6a5c7f621e4ca12205137c0b135cab444a
和这里:
http://ryandaigle.com/articles/2008/7/19/what-s-new-in-edge-rails-nested-models
class Tree < ActiveRecord::Base
has_many :bird_nests, :accessible => true
end
Run Code Online (Sandbox Code Playgroud)
这是首选方案。
| 归档时间: |
|
| 查看次数: |
3334 次 |
| 最近记录: |