我有一个嵌套的表单,一旦我保存,我希望能够单击显示页面上的链接来复制或克隆该表单并打开一个新的。从那里,我应该能够进行编辑(像一个新的id),并保存为一个新的记录。我看过一些类似deep_cloneable宝石的例子,但我不知道如何实现它。我认为这应该很简单,但我就是不明白在控制器和显示视图中应该把东西放在哪里。
如果你想复制一个activeRecord对象,你可以使用它的属性来创建一个新的,如
你可以在你的控制器中有一个动作可以在链接上调用,
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
我发现这些答案有点难以理解。一个答案是这样的:
@post = Post.new(@existing_post.attributes)
将不起作用,因为它还将传递id和时间戳值。我用。dup来解决这个问题,并在我的答案中显示出来。
下面是我如何从一个已存在的项目中创建一个新项目。
模型用于Product,即控制器Products_Controller.rb。我们将为控制器添加一个名为copy
的新动作,我们将从现有产品的show
视图链接到它,并呈现一个已填写的new
视图,准备进行编辑和保存。
首先,我们为routes.rb
# Routes.rb
resources :Products do
member do
get 'copy'
end
end
然后在Products_controller.rb
中复制操作 # ProductController.rb
def copy
@source = Product.find(params[:id])
@product = @source.dup
render 'new'
end
现在我们需要添加一个链接到show
视图来调用我们的复制操作。
# show.html.erb
<%= link_to "copy", copy_product_path(params[:id]) %>
Rails 4-6 Update:
强参数支架使它更短:
# ProductController.rb
# GET /products/1/copy
def copy
@product = @product.dup
render :new
end
在动词模板中:
# show.html.erb
<%= link_to "copy", copy_product_path(@product) %>
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
同样值得一提的是模型上的dup
方法。它创建一个具有所有属性和传出关系的副本,但将id
设置为nil
。像这样(借用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