2011-04-19 8 views
10

Tengo un formulario anidado y una vez que lo guardo, quiero poder hacer clic en un enlace en la página de la demostración para copiar o clonar ese formulario y abrir uno nuevo. A partir de ahí, podré hacer ediciones (como una nueva identificación) y guardar como un nuevo registro. He visto algunos ejemplos como este deep_cloneable gem, pero no tengo idea de cómo implementarlo. Creo que esto debería ser simple, pero simplemente no entiendo dónde poner las cosas en el controlador y en la vista del programa.Rails clone copy or duplicate

Respuesta

17

Si desea copiar un objeto ActiveRecord puede utilizar sus atributos para crear uno nuevo como

que puede tener una acción en el controlador que se puede llamar en el enlace,

def create_from_existing 
@existing_post = Post.find(params[:id]) 
#create new object with attributes of existing record 
@post = Post.new(@existing_post.attributes) 
render "your_post_form" 
end 
+0

Gracias, entonces después de eso va en mi controlador, ¿cómo debería verse la etiqueta link_to en la vista? – FattRyan

+0

¿Eres nuevo en los rieles? en la página de presentación, necesita renderizar algún enlace, diga link_to "Copiar a nuevo registro", {: controller => "su controlador",: acción => 'create_from_existing',: id => params [: id]} también, define route inroute.rb file para create_from_existing action. si desea mostrar este formulario en la página existente, entonces puede usar ajax usando link_to_remote (link_to: remote => true, rails 3) –

+1

¿Cómo funciona esto con has_many? ¿Crea nuevos registros para los objetos secundarios o usa los mismos registros? – Mike

3
class Foo < ActiveRecord::Base 
    def self.clone_from(parent) 
    parent = find(parent) unless parent.kind_of? Foo 
    foo = self.new 
    foo.attributes = parent.attributes 
    # if you want to also clone a habtm: 
    foo.some_association_ids = parent.some_association_ids 
    # etc. 
    foo 
    end 
end 

class FoosController < ApplicationController 
    def clone 
    foo = Foo.clone_from(params[:id]) 
    respond_with(foo) 
    end 
end 
17

Encontré estas respuestas un poco difíciles de seguir. Una respuesta muestra esto:

@post = Post.new(@existing_post.attributes) 

que no funcionará, ya que también pasará los valores de id y timestamp. Usé .dup para arreglar eso y lo muestro en mi respuesta.

Así es como he logrado crear un nuevo elemento a partir de un elemento existente.

El modelo es para un producto, el controlador Products_Controller.rb. Vamos a agregar una nueva acción al controlador llamada COPY y vamos a vincularla desde la vista SHOW de un Producto existente y renderizar una vista NUEVA completa, lista para ser editada y guardada.

En primer lugar, crear una ruta para la acción de copiar en routes.rb

resources :Products do 
    member do 
     get 'copy' 
    end 
    end 

A continuación, una acción de copia en Products_controller.rb

def copy 
     @source = Product.find(params[:id]) 
     @product = @source.dup 
     render 'new' 
     end 

Ahora tenemos que añadir un enlace a la vista de presentación para llamar a nuestra acción de copia.

<%= link_to "copy", copy_product_path(params[:id]) %> 

Esto funcionó para mí. Espero que funcione para usted y que la respuesta sea lo suficientemente simple como para seguirlo.

1

También vale la pena mencionar el método dup en un modelo. Hace una copia con todos los atributos y las relaciones salientes, pero establece id en nil. Así (código de préstamo de Naren Sisodiya):

def create_from_existing 
    @existing_post = Post.find(params[:id]) 
    #create new object with attributes of existing record 
    @post = @existing_post.dup 
    render "your_post_form" 
end