Ruby On Rails-2.0.2源代码分析(3)-named route和resource
- 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类的。那我们首先来看一看这个方法:
- 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方法的真面目:
- 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)拿出来作为示意,感兴趣的同学们可以自己查看相关的源代码。
- 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。完成了这些基本的route生成外,Rails还会处理嵌套,关联关系(存在block的处理和map_associations)。当然,基本逻辑都和上面的逻辑类似。
如此云云。。。针对Resource的一张庞大的route表就生成完成了
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!



