- Restful embodiment ---- Resource
Of course, it seems quite narrow to put restful and resource together. In rails, actioncontroller: Resources abstracts resources in rest. Here, I will not talk about the concept of rest, A huge amount of online information. Let's take a look at how resource is used in rails to easily and easily complete restful applications.
Resources. Rb
Source code path:/actionpack-2.0.2/lib/action_controller/resources. Rb
First of all, we do not need to look at the resource in depth, you can understand it as, when you define the following resource in routes. RB:
Map. Resources: Products
Rails will automatically generate a large number of named route for us. These route correspond to the action in the corresponding controller through HTTP verb. Of course, many helper methods are also generated. See the following table:
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 |
... |
... |
From this point of view, you can think of resource as a vest of many related named route.
The entire process is relatively intuitive. rails uses resource to generate various route step by step. Next, let's take a look at how the core code completes these functions. First, the following resource may be defined in routes. RB:
Ruby code
- Actioncontroller: routing: routes. DrawDo| Map |
- Map. Resources: Products
- ...
- End
ActionController::Routing::Routes.draw do |map| map.resources :products ...end
The resources method is defined in the module actioncontroller: resources, and then enters the Mapper class through Mixin. Let's first take a look at this method:
Ruby code
- DefResources (* 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
It is easy to separate entities and options from parameters, and then perform the map_resource operation for each entity. Let's continue and see the true face of the map_resource method:
Ruby code
- DefMap_resource (entities, options ={}, & Block)
- Resource = resource.New(Entities, options)
- With_options: controller => resource. ControllerDo| 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)
- IfBlock_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 endend
With entity and options, what are you waiting? Generate our resource object immediately. The resource object encapsulates the collection method, member method, new method, path prefix, name prefix, single/plural representation, and option related to the resource. The resource object is generated by parsing the corresponding attributes of the object from options and saving them. The code is simple and will not be pasted here.
Now, the resource object is available. We can see from the code above. Next, we will handle the named route related to this resource. The specific processing logic is similar. Here, map_member_actions (MAP, resource) is used as a signal. Interested students can view the source code on their own.
Ruby code
- DefMap_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
Here, we can intuitively see that rails generates many route for the member-related methods of resource. We can see the familiar show, update, and destroy actions in the controller. Yes. Here, rails generates the corresponding route for the URL-to-controller action.
This article from: http://woody-420420.javaeye.com/blog/174352