development

활성 레코드 레코드를 복제하는 가장 쉬운 방법은 무엇입니까?

big-blog 2020. 2. 22. 11:40
반응형

활성 레코드 레코드를 복제하는 가장 쉬운 방법은 무엇입니까?


프로세스에서 단일 필드를 변경하고 ( id 외에도) 활성 레코드 레코드의 사본을 만들고 싶습니다 . 이것을 달성하는 가장 간단한 방법은 무엇입니까?

새 레코드를 만든 다음 필드별로 데이터를 복사하는 각 필드를 반복 할 수 있지만 더 쉬운 방법이 있어야한다고 생각했습니다 ...

같은 :

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

사본을 얻으려면 clone (또는 rails 3.1의 경우 dup) 방법을 사용하십시오.

# rails < 3.1
new_record = old_record.clone

#rails >= 3.1
new_record = old_record.dup

그런 다음 원하는 필드를 변경할 수 있습니다.

ActiveRecord는 기본 제공 Object # clone재정 의하여 할당되지 않은 ID를 가진 새로운 (DB에 저장되지 않은) 레코드를 제공합니다.
연결을 복사하지 않으므로 필요한 경우 수동으로이 작업을 수행해야합니다.

Rails 3.1 복제본은 얕은 사본이므로 대신 dup을 사용하십시오.


필요와 프로그래밍 스타일에 따라 클래스의 새로운 메소드와 병합의 조합을 사용할 수도 있습니다. 간단한 예가 없으면 특정 날짜로 예약 된 작업이 있고 다른 날짜로 복제하려고한다고 가정하십시오. 작업의 실제 속성은 중요하지 않으므로 다음과 같이하십시오.

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로 변경하십시오.

평화.


ActiveRecord 3.2 용 Amoeba gem좋아할 수도 있습니다 .

귀하의 경우에는, 당신은 아마 사용하게 할 nullify, regex또는 prefix구성 DSL에서 사용할 수있는 옵션을.

그것은 간단하고 자동 순환 중복 지원 has_one, has_manyhas_and_belongs_to_many협회, 필드 전처리 및 모델에와 비행에 모두 적용 할 수있는 매우 유연하고 강력한 구성 DSL을.

Amoeba Documentation 을 확인해야 하지만 사용법은 매우 쉽습니다.

다만

gem install amoeba

또는 추가

gem 'amoeba'

Gemfile에

그런 다음 모델에 amoeba 블록을 추가하고 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에는 더 많은 옵션이 있으므로 설명서를 확인하십시오.

즐겨! :)


ID를 복사하지 않으려면 ActiveRecord :: Base # dup을 사용하십시오.


나는 보통 속성을 복사하고 변경해야 할 것을 변경합니다.

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

연관성이있는 깊은 사본이 필요한 경우 deep_cloneable gem을 사용하는 것이 좋습니다 .


쉬운 방법은 다음과 같습니다

#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     

Rails 5에서는 이와 같이 중복 객체 또는 레코드를 생성 할 수 있습니다.

new_user = old_user.dup

acts_as_inheritable gem을 확인할 수도 있습니다 .

"상속 할 수없는 행위는 Rails / ActiveRecord 모델을 위해 특별히 작성된 루비 보석입니다. 자체 참조 연관 또는 상속 가능한 속성을 공유하는 부모가있는 모델과 함께 사용하기위한 것입니다.이를 통해 모든 속성 또는 부모 모델과의 관계 "

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">

이것이 당신을 도울 수 있기를 바랍니다.


더 많은 논리가있을 수 있으므로 모델을 복제 할 때 필요한 모든 논리를 처리하는 새 클래스를 만드는 것이 좋습니다. 그것을 돕기 위해, 도움이 될 수있는 보석이 있습니다 : 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: 'clown@circus.example.com')>

cloned = UserCloner.call(user, email: 'fake@example.com')
cloned.persisted?
# => false

cloned.save!
cloned.login
# => nil
cloned.email
# => "fake@example.com"

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

예제는 프로젝트에서 복사되었지만 달성 할 수있는 것에 대한 명확한 비전을 제공합니다.

빠르고 간단한 기록을 위해 다음과 같이하겠습니다.

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


다음은 #dup인스턴스 복제를 사용자 정의하고 관계 복제도 포함하기 위해 ActiveRecord 메소드를 대체하는 샘플입니다 .

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

참고 :이 방법은 외부 보석이 필요하지 않지만 #dup방법이 구현 된 최신 ActiveRecord 버전이 필요합니다

참고 URL : https://stackoverflow.com/questions/60033/what-is-the-easiest-way-to-duplicate-an-activerecord-record



반응형