开发者

REST path for "new from copy"

For certain models, I wish to provide functionality that allows a user to create a new record with 开发者_开发百科default attributes based on copy of an existing record.

I'm wondering what would be the correct restful route for this.

My initial thinking is that it could be a parameter to the new action. I.e. to borrow from the the Rails Guides examples, instead of just:

GET : /photos/new

Also allow:

GET : /photos/new/:id

...where :id is the id of the record to use as a template. The response would be a new/edit form, same as with a plain old new but the values would be pre-filled with data from the existing record. The parameter (or absense of it) could be easily handled by the new controller method.

The alternative seems to be to create a new controller method, for example copy which would also accept an id of an existing record and response with the new form as above. This seems a little 'incorrect' to me, as the record is not actually being copied until the user saves the new record (after probably editig it somewhat).

TIA...

UPDATE: my question is not "how do I do this in rails?", it's "is it RESTful?"


my question is not "how do I do this in rails?", it's "is it RESTful?"

No, it isn't. For that matter, neither is GET /photos/new. Rails seems to be hopelessly mired in the past, where it was considered haute programme for a GET on a URI to return an HTML form which would then POST x-www-form-urlencoded data back to that same URI. The opacity of that POST forces them to invent new verbs-as-URI's like /photos/new, when you could be using PUT instead, or at least POST with the same media type.

The simplest way to make a copy of an HTTP resource RESTfully is:

GET /photos/{id}/ -> [representation of a photo resource]
...make modifications to that representation as desired...
POST /photos/ <- [modified representation]

If you're implementing this for browsers, you should be able to perform those actions via Ajax quite easily, using an HTML page sitting perhaps at /photos/manager.html/ to drive the interaction with the user.


You can try to use nested resources. I'm not exactly sure about structure of you application, but in general using nested photos will look somehow like this:

routes.rb

resources :photos do
  resources :photos
end

photos_controller.rb

before_filter :find_parent_photo, :only => [:new, :create]

def create
  @photo = Photo.new params[:photo]
  if @parent_photo.present?
    # fill some @photo fields from @parent_photo
  end
  @photo.save

  respond_with @photo
end

def find_parent_photo
  @parent_photo = Photo.find(params[:photo_id]) if params[:photo_id].present?
end

new.html.haml

= form_for [@parent_photo, @photo] do |f|
  -# your form code

previously when you wanted to add a link to photo creation you wrote something like that

= link_to "new photo", [:new, :photo]

now if you want to add a link to photo creation based on foto @photo1

= link_to "new photo based on other one", [:new, @photo1, :photo]


You should be able to match a route like so:

match 'photos/new/:photo_id' => 'photos#new

or you could just pass a :photo_id parameter in the url and handle it in the controller:

'/photos/new?photo_id=17'

Example using helper method: new_photo_path(:photo_id => 17)

Edit: I don't know if this conforms to REST


It may be over the top, but you could do something like this:

class PhotoCopiesController < ApplicationController
  def new
    @photo = Photo.find(params[:photo_id]).dup
  end

  def create
  end
end

and

resources :photo_copies, :only => [:new, :create]

and

= link_to 'Copy', photo_copy_path(:photo_id => @photo.id)
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜