我有一个嵌套表单,保存后,我想在show页面上点击一个链接来复制或克隆该表单,并打开一个新表单。然后我应该能够进行编辑(如一个新的ID)并将其保存为一个新记录。我看过一些类似于deep_cloneable gem的示例,但我不知道如何实现它。我认为这应该很简单,但我不理解在控制器和展示页面中放置东西的位置。
我有一个嵌套表单,保存后,我想在show页面上点击一个链接来复制或克隆该表单,并打开一个新表单。然后我应该能够进行编辑(如一个新的ID)并将其保存为一个新记录。我看过一些类似于deep_cloneable gem的示例,但我不知道如何实现它。我认为这应该很简单,但我不理解在控制器和展示页面中放置东西的位置。
如果你想复制一个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
中创建一个路由,用于“copy”操作。
# 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 更新:
强参数脚手架使其更简洁:
# ProductController.rb
# GET /products/1/copy
def copy
@product = @product.dup
render :new
end
并且在erb模板中:
# 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
@existing_post
具有任何不可批量赋值的属性,那么这将会失败。您必须拒绝受保护或唯一的属性,例如id
。 - JellicleCat