Ruby On Rails-2.0.2源代码分析(3)-resource
2010-04-30 11:44
162 查看
RESTful的化身----resource
当然,光把RESTful和resource扯到一起似乎相当狭义,在Rails中,ActionController::Resources抽象了REST中的Resource,这里,我不谈REST的相关概念,网上资料一大坨。我们就来看看Rails中是如何通过Resource来轻松,简便的完成RESTful应用的吧。resources.rb
源代码路径:/actionpack-2.0.2/lib/action_controller/resources.rb首先,我们也不需要将resource看得多么的高深,你可以把他理解为,当你在routes.rb中定义如下的resource的时候:
map.resources :products
Rails会自动为我们生成众多的named route,这些route通过http verb和相应的controller中的action对应起来,当然了,众多的helper方法也随即产生。如下表所示:
Named Route | Helpers |
product | product_url, hash_for_product_url, product_path, hash_for_product_path |
new_product | new_product_url, hash_for_new_product_url, new_product_path, hash_for_new_product_path |
edit_product | edit_product_url, hash_for_edit_product_url, edit_product_path, hash_for_edit_product_path |
... | ... |
整个流程比较的直观,Rails通过resource按部就班的完成各种route的生成,接下来我们看一看核心代码是如何完成这些功能的。首先,还是在routes.rb中,可能会定义如下的resource:
Ruby代码
ActionController::Routing::Routes.draw do |map|
map.resources :products
...
end
ActionController::Routing::Routes.draw do |map| map.resources :products ... end
resources方法定义在ActionController::Resources这个module中,然后通过mixin进入到Mapper类的。那我们首先来看一看这个方法:
Ruby代码
def resources(*entities, &block)
options = entities.extract_options!
entities.each { |entity| map_resource(entity, options.dup, &block) }
end
def resources(*entities, &block) options = entities.extract_options! entities.each { |entity| map_resource(entity, options.dup, &block) } end
很简单,将entities和options从参数中分离开来,然后针对每一个entity执行map_resource操作。我们继续进行,看看map_resource方法的真面目:
Ruby代码
def map_resource(entities, options = {}, &block)
resource = Resource.new(entities, options)
with_options :controller => resource.controller do |map|
map_collection_actions(map, resource)
map_default_collection_actions(map, resource)
map_new_actions(map, resource)
map_member_actions(map, resource)
map_associations(resource, options)
if block_given?
with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], &block)
end
end
end
def map_resource(entities, options = {}, &block) resource = Resource.new(entities, options) with_options :controller => resource.controller do |map| map_collection_actions(map, resource) map_default_collection_actions(map, resource) map_new_actions(map, resource) map_member_actions(map, resource) map_associations(resource, options) if block_given? with_options(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix, :namespace => options[:namespace], &block) end end end
有了entity和options,还等什么呢?马上生成我们的Resource对象,Resource对象封装了和此resource相关的collection method,member method,new method,path prefix,name prefix,单/复数表示,还有option。生成这个Resource对象无非就是将此对象的相应属性从options中解析出来,保存起来,代码比较简单,这里就不再贴出。
现在,Resource对象有了,从上面代码我们就可以看出来,接下来,就该处理和此resource相关named route了。具体的处理逻辑都类似,这里将map_member_actions(map, resource)拿出来作为示意,感兴趣的同学们可以自己查看相关的源代码。
Ruby代码
def map_member_actions(map, resource)
resource.member_methods.each do |method, actions|
actions.each do |action|
action_options = action_options_for(action, resource, method)
map.named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}", action_options)
map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}.:format",action_options)
end
end
show_action_options = action_options_for("show", resource)
map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options)
map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options)
update_action_options = action_options_for("update", resource)
map.connect(resource.member_path, update_action_options)
map.connect("#{resource.member_path}.:format", update_action_options)
destroy_action_options = action_options_for("destroy", resource)
map.connect(resource.member_path, destroy_action_options)
map.connect("#{resource.member_path}.:format", destroy_action_options)
end
def map_member_actions(map, resource) resource.member_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) map.named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}", action_options) map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}.:format",action_options) end end show_action_options = action_options_for("show", resource) map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options) map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options) update_action_options = action_options_for("update", resource) map.connect(resource.member_path, update_action_options) map.connect("#{resource.member_path}.:format", update_action_options) destroy_action_options = action_options_for("destroy", resource) map.connect(resource.member_path, destroy_action_options) map.connect("#{resource.member_path}.:format", destroy_action_options) end
这里,我们可以很直观的看到,Rails为resource的member相关方法生成了众多的route,我们可以看到Controller中熟悉的show,update,destroy action。是的,在这里,Rails就为url到controller的action生成了相应的route。
本文转自:http://woody-420420.javaeye.com/blog/174352
相关文章推荐
- Ruby On Rails-2.0.2源代码分析(3)-named route
- Ruby On Rails-2.0.2源代码分析(1)-Rails的启动
- Ruby On Rails-2.0.2源代码分析(1)-Rails的启动
- 用百度开源webuploader 上传图片 rubyonrails 后端代码
- Ruby on Rails Resource
- Ruby on Rails 入门之:(21) ruby中代码块的使用以及动态执行代码
- 补充ruby on rails的相关介绍并对比J2EE分析其架构
- 利用RJB在Ruby on Rails中使用Java代码的教程
- ruby on rails 之 延时执行代码
- 技巧分析之Ruby on Rails本地安装
- ruby on rails 代码技巧
- 在 Ruby on Rails 应用程序中重用 Java 代码
- 浅析 ruby on rails 中的事务嵌套 源码分析
- 在 Ruby on Rails 应用程序中重用 Java 代码
- ruby on rails 代码技巧
- ruby on rails 代码检查列单
- cloud controller 源码分析(包括Ruby on Rails项目结构分析)
- 简单对比分析Ruby on Rails 和 Laravel
- 【Ruby】Ruby框架的使用(Ruby on Rails项目结构分析)
- 一次摸索中搭建Ruby on Rails开发环境.