开发者

Rails - RESTful Routing - Add a POST for Member i.e(tips/6)

开发者 https://www.devze.com 2022-12-12 06:20 出处:网络
I\'m trying to create some nice RESTful structure for my app in rails but now I\'m stuck on a conception that unfortunately I\'m not sure if its correct, but if someone could help me on this it would

I'm trying to create some nice RESTful structure for my app in rails but now I'm stuck on a conception that unfortunately I'm not sure if its correct, but if someone could help me on this it would be very well appreciated.

If noticed that for RESTful routes we have (the uncommented ones)

collection
    :index   => 'GET'
    :create  => 'POST'
   #:?       => 'PUT'
   #:?       => 'DELETE'

member 
    :show    => 'GET'
   #:?       => 'POST'
    :update  => 'PUT'
    :destroy => 'DELETE'

in this case I'm only talking about base level action or the ones that occur directly inside i.e http://domain.com/screename/tips or http://domain.com/screename/tips/16

but at the same time I notice that there's no POST possibility for the members, anybody knows why?

What if I'm trying to create a self contained item that clones itself with another onwer?

I'm almost sure that this would be nicely generated by a POST method inside the member action, but unfortunately it looks like that there's no default methods on the map.resources on rails for this.

I tried something using :member, or :开发者_开发百科new but it doesn't work like this

 map.resources :tips, :path_prefix => ':user', :member  => {:add => :post}

so this would be accessed inside http://domain.com/screename/tips/16/add and not http://domain.com/screename/tips/16.

So how would it be possible to create a "default" POST method for the member in a RESTful route?

I was thinking that maybe this isn't in there because it's not part of REST declaration, but as a quick search over it I found:

POST

for collections : Create a new entry in the collection where the ID is assigned automatically by the collection. The ID created is usually included as part of the data returned by this operation.

for members : Treats the addressed member as a collection in its own right and creates a new subordinate of it.

So this concept still the same if you think about the DELETE method or PUT for the collection. What if I want to delete all the collection instead just one member? or even replace them(PUT)?

So how could I create this specific methods that seems to be missing on map.resources?

That's it, I hope its easy to understand.

Cheers


The reason they aren't included by is that they're dangerous unless until secured. Member POST not so much as collection PUT/DELETE. The missing member POST is more a case of being made redundant by the default collection POST action.

If you still really want to add these extra default actions, the only way you're going to be able to do it, is it to rewrite bits of ActionController::Resources.

However this is not hard to do. Really you only need to rewrite two methods. Even then you don't have to rewrite them fully. The methods bits that you'll need to add to those methods don't really on complex processing of the arguments to achieve your goal. So you can get by with a simple pair of alias_method_chain.

Assuming I haven't made any errors, including the following will create your extra default routes as described below. But do so at your own risk.

module ActionController
  module Resources
    def map_member_actions_with_extra_restfulness(map, resource)
      map_member_actions_without_extra_restfulness(map, resource)
      route_path = "#{resource.shallow_name_prefix}#{resource.singular}"
      map_resource_routes(map, resource, :clone, resource.member_path, route_path, :post, :force_id => true)
    end

    alias_method_chain :map_member_actions, :extra_restfulness


    def map_default_collection_actions_with_extra_restfullness(map, resource)
      map_default_collection_actions_without_extra_restfullness(map,resource
      index_route_name = "#{resource.name_prefix}#{resource.plural}"

      if resource.uncountable?
        index_route_name << "_index"
      end

      map_resource_routes(map, resource, :rip, resource.path, index_route_name, :put)
      map_resource_routes(map, resource, :genocide, resource.path, index_route_name, :delete)
    end

    alias_method_chain :map_default_collection_actions, :extra_restfulness
  end
end

You'll have to mess around with generators to ensure that script/generate resource x will create meaningful methods for these new actions.

Now that we've covered the practical part, lets talk about the theory. Part of the problem is coming up with words to describe the missing actions:

The member action described for POST in the question, although technically correct does not hold up when applied to ActionController and the underlying ActiveRecord. At best it is ambiguous, at, worst it's not possible. It makes sense for resources with a recursive nature (like trees,) or resources that have many of a different kind of resource. however this second case is ambiguous and already covered by Rails. Instead I chose clone for the collection POST. It made the most sense for default post on an existing record. Here are the rest of the default actions I decided on:

collection
    :index       => 'GET'
    :create      => 'POST'
    :rip         => 'PUT'
    :genocide    => 'DELETE'

member 
    :show    => 'GET'
    :clone   => 'POST'
    :update  => 'PUT'
    :destroy => 'DELETE'

I chose genocide for collection DELETE because it just sounded right. I chose rip for the collection PUT because that was the term a company I used to work for would describe the act of a customer replacing all of one vendor's gear with another's.


I'm not quite following, but to answer your last question there, you can add collection routes for update_multiple or destroy_multiple if you want to update or delete multiple records, rather than a single record one at a time.

I answered that question earlier today actually, you can find that here.

The reason that there's no POST to a particular member is because that member record already exists in the database, so the only thing you can do to it is GET (look at), PUT (update), or DELETE (destroy). POST is designed only for creating new records.

If you were trying to duplicate an existing member, you would want to GET the original member in a "duplicate" member action and POST to the resource root with its contents.

Please let me know if I'm missing what you're asking.

0

精彩评论

暂无评论...
验证码 换一张
取 消