【问题标题】:Rails clone copy or duplicateRails 克隆副本或复制
【发布时间】:2011-08-08 08:39:42
【问题描述】:

我有一个嵌套表单,保存后,我希望能够单击显示页面上的链接来复制或克隆该表单并打开一个新表单。从那里我应该能够进行编辑(如新 id)并保存为新记录。我见过一些像deep_cloneable gem 这样的例子,但我不知道如何实现它。我认为这应该很简单,但我只是不明白在控制器和显示视图中放置东西的位置。

【问题讨论】:

    标签: ruby-on-rails-3 duplicates copy clone


    【解决方案1】:

    如果你想复制一个 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
    

    【讨论】:

    • 谢谢,在进入我的控制器之后,link_to 标签在视图中的外观应该如何?
    • 您是 Rails 新手吗?在显示页面上,您还需要呈现一些链接,例如 link_to "Copy to new record",{:controller=>"your controller",:action=>'create_from_existing',:id=>params[:id]},定义路由用于 create_from_existing 操作的 inroute.rb 文件。如果您想在现有页面上显示此表单,则可以使用 ajax 使用 link_to_remote (link_to :remote=>true, rails 3)
    • 如何处理has_many?它是为子对象创建新记录还是使用相同的记录?
    • 如果@existing_post 有任何不可批量分配的属性,这将失败。您必须拒绝受保护或独特的属性,例如 id
    【解决方案2】:
    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
    

    【讨论】:

      【解决方案3】:

      我发现这些答案有点难以理解。一个答案表明:

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

      这不起作用,因为它还会传递 id 和时间戳值。我使用 .dup 解决了这个问题,并在我的回答中展示了这一点。

      以下是我如何从现有项目创建新项目。

      该模型用于产品,即控制器 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 更新:

      强大的参数脚手架使其更短:

      # 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) %>
      

      【讨论】:

        【解决方案4】:

        另外值得一提的是模型上的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
        

        【讨论】:

          猜你喜欢
          • 2011-11-11
          • 1970-01-01
          • 2012-05-23
          • 2015-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-19
          • 1970-01-01
          相关资源
          最近更新 更多