浏览 1606 次
|
锁定老贴子 主题:一个常见REST应用场景的困惑和探究
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2007-08-31
下面是一个最常碰到的应用场景:
一个论坛应用(如: javaeye)。文章资源是一个嵌套关系: 栏目(board)-->分类(category)-->文章(topic),其routes.rb里的配置可能如下:
map.resources :boards do |board|
board.resources :categories do |category|
category.resources :topics
end
end
列出某分类下的所有主题的URL则是这样的:http://***/boards/2/categories/4/topics 但是我们有时可能需要列出某栏目下的所有主题。于是可能需要这样的URL: http://***/boards/2/topics 要实现这样的URL的需要修改一下routes,如下。
map.resources :boards do |board|
board.resources :topics
board.resources :categories do |category|
category.resources :topics
end
end
但这样方式有点问题:在构造URL时 topics_path(@board,@category)有效,但topics_path(@board)无效。 但是......,我们可能还要搜索附合一些关键字条件的文章,也许需要这样的URL: http://***/boards/2/topics?keyword="rails ruby" 或者象javaeye现在的处理方式用URL:http://***/borads/ajax_search?keyword="rails ruby" ------------------------------------------------------------------ 又或许我们就抛弃嵌套方案,直接定义topics资源,如下
map.resources :topics
以后删除和查看都很容易构造URL,只需要文章id就行了: http://***/topics/1 如果要查某栏目、某分类下的文章就在topics_controller里创建几个自定义action。 ------------------------------------------------------------------ 也许是我面向URL设计的思想没转过弯来,说实在的我倒觉得用REST越来越复杂了。主要是因为它即可以这样做,又可以那样做。有很多常见问题,并没有太多现存的解决的模式可供参考。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2007-08-31
刚说没有可供参考的案例,突然想到了http://beast.caboo.se/,看看它是怎么实现的
它有这样的嵌套关系: forums--> topics -->posts (即 栏目-->帖子-->回复) 关于posts的routes如下。 map.resources :forums, :has_many => [:posts] do |forum|
forum.resources :topics, :name_prefix => nil do |topic|
topic.resources :posts, :name_prefix => nil
topic.resource :monitorship, :name_prefix => nil
end
end
map.resources :posts, :name_prefix => 'all_', :collection => { :search => :get }
map.with_options :controller => 'posts', :action => 'monitored' do |map|
map.formatted_monitored_posts 'users/:user_id/monitored.:format'
map.monitored_posts 'users/:user_id/monitored'
end
这里即有post嵌套关系,也有把 post直接定义成资源,也有传统的controller/action定义。 在其网页上有一个搜索帖子的form表单,其代码如下: <form action="/posts/search" method="get">
<input id="search_box" name="q" size="15" type="text">
</form>
这应该是用了routes里的post第二条的定义。 post_controller有一个search方法,如下: def search
conditions = params[:q].blank? ? nil : Post.send(:sanitize_sql, ["LOWER(#{Post.table_name}.body) LIKE ?", "%#{params[:q]}%"])
@posts = Post.paginate @@query_options.merge(:conditions => conditions, :page => params[:page], :count => {:select => "#{Post.table_name}.id"})
@users = User.find(:all, :select => 'distinct *', :conditions => ['id in (?)', @posts.collect(&:user_id).uniq]).index_by(&:id)
render_posts_or_xml :index
end
另外,post_controller里还有第三条routes定义的action----monitored,没细看它是做什么用的。 http://beast.caboo.se/posts http://beast.caboo.se/forums/1/posts http://beast.caboo.se/forums/1/topics/1208/posts 都能用,它们都是指定post_controller的index方法,这个方法里构造SQL条件挺巧妙的, def index
conditions = []
[:user_id, :forum_id, :topic_id].each { |attr| conditions << Post.send(:sanitize_sql, ["#{Post.table_name}.#{attr} = ?", params[attr]]) if params[attr] }
conditions = conditions.any? ? conditions.collect { |c| "(#{c})" }.join(' AND ') : nil
@posts = Post.paginate @@query_options.merge(:conditions => conditions, :page => params[:page], :count => {:select => "#{Post.table_name}.id"})
@users = User.find(:all, :select => 'distinct *', :conditions => ['id in (?)', @posts.collect(&:user_id).uniq]).index_by(&:id)
render_posts_or_xml
end
|
|
| 返回顶楼 | |
|
最后更新时间:2007-09-03
REST跟URL没有关系吧。
|
|
| 返回顶楼 | |
|
最后更新时间:2007-09-03
liubin 写道 REST跟URL没有关系吧。
1.1 什么是REST? REST这个术语,是Roy Fielding在Ph.D.论文中提出来的,它的全称是“Representational State Transfer.” REST描述了这么一个架构:利用标准的http 协议中的 get, post, put, delete 来请求和操作网络上的资源。 在REST中,资源的意思就是一个 基于URL实体,客户端可以通过 http协议来和它进行交互。这个资源可以用各种形式来展示给客户端,如 HTML,XML,RSS,主要依赖于客户端的调用方式。并不像以往的Rails开发那样,用REST方式,一个 url 不是指定一个 model 或者 action, 一个 url 仅仅是资源的本身而已。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-09-04
在路由定义里的has_many不起作用,原因是没有安装edge。
# map.resources :forums, :has_many => [:posts] do |forum| 可以用以下替代。 # forum.resources :forums do |forum| # topic.resources :posts, :name_prefix => 'forum_' 在beast网站中,name_prefix大都是设为nil,我建议还是加一个前缀,否则在构造URL只能构造默认的一种。 今天 已经把我开发的网站全部转成REST,工作量都集中在把controller+action的url构造方式,改成*_*_path方式。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-11-23
提个问题,这种类型的嵌套资源怎么表示:
class Post < ActiveRecord::Base
has_many :comments,:dependent=>:destroy,:as=>:commentable
has_one :last_comment,
:class_name=>"Comment",
:order=>"id desc",
:as=>:commentable
end
class Image < ActiveRecord::Base
has_many :comments,:as=>:commentable
end
class Comment < ActiveRecord::Base
belongs_to :commentable,:polymorphic=>true
end
即Comment是Post和Image的嵌套资源,要添加一个Post的Comment和Image的Comment的URL该怎么设计呢,Action又要怎么写?这种类型用传统风格很好实现,但REST? |
|
| 返回顶楼 | |






