天天看點

複制活動記錄記錄的最簡單方法是什麼?

我想制作一個activerecord記錄的副本,在流程中更改單個字段(除了id之外 )。 最簡單的方法是什麼?

我意識到我可以建立一個新記錄,然後周遊每個字段,逐字段複制資料-但我認為必須有一種更簡單的方法來執行此操作...

如:

@newrecord=Record.copy(:id)  *perhaps?*
           

#1樓

您還可以檢查act_as_inheritable gem。

“作為繼承的行為是專門為Rails / ActiveRecord模型編寫的Ruby Gem。它旨在與Self-Referential Association或具有共享可繼承屬性的父級的模型一起使用。這将使您繼承任何屬性或與父模型的關系。”

通過将

acts_as_inheritable

添加到模型中,您将可以通路以下方法:

Inherit_attributes

class Person < ActiveRecord::Base

  acts_as_inheritable attributes: %w(favorite_color last_name soccer_team)

  # Associations
  belongs_to  :parent, class_name: 'Person'
  has_many    :children, class_name: 'Person', foreign_key: :parent_id
end

parent = Person.create(last_name: 'Arango', soccer_team: 'Verdolaga', favorite_color:'Green')

son = Person.create(parent: parent)
son.inherit_attributes
son.last_name # => Arango
son.soccer_team # => Verdolaga
son.favorite_color # => Green
                

Inherit_relations

class Person < ActiveRecord::Base

  acts_as_inheritable associations: %w(pet)

  # Associations
  has_one     :pet
end

parent = Person.create(last_name: 'Arango')
parent_pet = Pet.create(person: parent, name: 'Mango', breed:'Golden Retriver')
parent_pet.inspect #=> #<Pet id: 1, person_id: 1, name: "Mango", breed: "Golden Retriver">

son = Person.create(parent: parent)
son.inherit_relations
son.pet.inspect # => #<Pet id: 2, person_id: 2, name: "Mango", breed: "Golden Retriver">
                

希望這可以幫到你。

#2樓

簡單的方法是:

#your rails >= 3.1 (i was done it with Rails 5.0.0.1)
  o = Model.find(id)
 # (Range).each do |item|
 (1..109).each do |item|
   new_record = o.dup
   new_record.save
 end
           

要麼

# if your rails < 3.1
 o = Model.find(id)
 (1..109).each do |item|
   new_record = o.clone
   new_record.save
 end     
           

#3樓

由于可能存在更多邏輯,是以在複制模型時,我建議建立一個新類,在其中處理所有需要的邏輯。 為了緩解這種情況,有一個寶石可以幫助您: clowne

根據他們的文檔示例,對于使用者模型:

class User < ActiveRecord::Base
  # create_table :users do |t|
  #  t.string :login
  #  t.string :email
  #  t.timestamps null: false
  # end

  has_one :profile
  has_many :posts
end
           

您建立克隆器類:

class UserCloner < Clowne::Cloner
  adapter :active_record

  include_association :profile, clone_with: SpecialProfileCloner
  include_association :posts

  nullify :login

  # params here is an arbitrary Hash passed into cloner
  finalize do |_source, record, params|
    record.email = params[:email]
  end
end

class SpecialProfileCloner < Clowne::Cloner
  adapter :active_record

  nullify :name
end
           

然後使用它:

user = User.last
#=> <#User(login: 'clown', email: '[email protected]')>

cloned = UserCloner.call(user, email: '[email protected]')
cloned.persisted?
# => false

cloned.save!
cloned.login
# => nil
cloned.email
# => "[email protected]"

# associations:
cloned.posts.count == user.posts.count
# => true
cloned.profile.name
# => nil
           

從項目中複制了示例,但是它将清晰地說明您可以實作的目标。

為了快速而簡單地記錄,我将選擇:

Model.new(Model.last.attributes.reject {|k,_v| k.to_s == 'id'}

#4樓

這是重寫ActiveRecord

#dup

方法的示例,以自定義執行個體複制并包括關系複制:

class Offer < ApplicationRecord
  has_many :offer_items

  def dup
    super.tap do |new_offer|

      # change title of the new instance
      new_offer.title = "Copy of #{@offer.title}"

      # duplicate offer_items as well
      self.offer_items.each { |offer_item| new_offer.offer_items << offer_item.dup }
    end
  end
end
           

注意:此方法不需要任何外部gem,但需要使用

#dup

實作

#dup

方法的較新ActiveRecord版本

#5樓

在Rails 5中,您可以像這樣簡單地建立重複的對象或記錄。

new_user = old_user.dup
           

#6樓

要獲得副本,請使用clone(對于rails則為dup)3.1:

# rails < 3.1
new_record = old_record.clone

#rails >= 3.1
new_record = old_record.dup
           

然後,您可以更改所需的任何字段。

ActiveRecord會覆寫内置的Object#clone,進而為您提供一個具有未配置設定ID的新記錄(未儲存到DB)。

請注意,它不會複制關聯,是以如果需要,您将必須手動執行此操作。

Rails 3.1 clone是一個淺表副本,請改用dup ...

#7樓

我通常隻是複制屬性,更改我需要更改的内容:

new_user = User.new(old_user.attributes.merge(:login => "newlogin"))
           

#8樓

根據您的需求和程式設計風格,您還可以結合使用類的新方法和合并。 由于缺少更好的簡單示例,假設您已将任務安排在某個日期,并且您想将其複制到另一個日期。 任務的實際屬性并不重要,是以:

old_task = Task.find(task_id)
new_task = Task.new(old_task.attributes.merge({:scheduled_on => some_new_date}))      

将使用

:id => nil

:scheduled_on => some_new_date

以及所有其他屬性與原始任務建立一個新任務。 使用Task.new,您将必須顯式調用save,是以,如果要自動儲存,請将Task.new更改為Task.create。

和平。

#9樓

如果您不想複制ID,請使用ActiveRecord :: Base#dup

#10樓

如果您需要具有關聯的深層副本,建議使用deep_cloneable gem。

#11樓

您可能還喜歡ActiveRecord 3.2的變形蟲 。

在您的情況下,您可能想利用配置DSL中可用的

nullify

regex

prefix

選項。

它支援

has_one

has_many

has_and_belongs_to_many

關聯的輕松,自動的遞歸複制,字段預處理和高度靈活且功能強大的配置DSL,可同時應用于模型和運作中。

一定要檢查變形蟲文檔,但用法非常簡單...

隻是

gem install amoeba
           

或添加

gem 'amoeba'
           

到您的Gemfile

然後将變形蟲塊添加到模型中,并照常運作

dup

方法

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    enable
  end
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :posts
end

class PostsController < ActionController
  def some_method
    my_post = Post.find(params[:id])
    new_post = my_post.dup
    new_post.save
  end
end
           

您還可以控制通過多種方式複制哪些字段,但是,例如,如果要防止重複注釋,但又想保留相同的标簽,則可以執行以下操作:

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    exclude_field :comments
  end
end
           

您還可以預處理字段,以幫助使用字首和字尾以及正規表達式來訓示唯一性。 此外,還有許多選項,是以您可以根據自己的目的以最易讀的方式編寫:

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    include_field :tags
    prepend :title => "Copy of "
    append :contents => " (copied version)"
    regex :contents => {:replace => /dog/, :with => "cat"}
  end
end
           

關聯的遞歸複制很容易,也隻需在子模型上啟用變形蟲

class Post < ActiveRecord::Base
  has_many :comments

  amoeba do
    enable
  end
end

class Comment < ActiveRecord::Base
  belongs_to :post
  has_many :ratings

  amoeba do
    enable
  end
end

class Rating < ActiveRecord::Base
  belongs_to :comment
end
           

配置DSL還有更多選項,是以請務必檢視文檔。

請享用! :)