답변:
사본을 얻으려면 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에 저장되지 않은) 레코드를 제공합니다.
연결을 복사하지 않으므로 필요한 경우 수동으로이 작업을 수행해야합니다.
필요와 프로그래밍 스타일에 따라 클래스의 새로운 메소드와 병합의 조합을 사용할 수도 있습니다. 더 간단한 예가 없으면 특정 날짜로 예약 된 작업이 있고 다른 날짜로 복제하려고한다고 가정하십시오. 작업의 실제 속성은 중요하지 않으므로 다음과 같이하십시오.
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로 변경하십시오.
평화.
WARNING: Can't mass-assign protected attributes: id, due_date, created_at, updated_at
반환
ActiveRecord 3.2 용 Amoeba gem 을 좋아할 수도 있습니다 .
귀하의 경우에는, 당신은 아마 사용하게 할 nullify
, regex
또는 prefix
구성 DSL에서 사용할 수있는 옵션을.
그것은 간단하고 자동 순환 중복 지원 has_one
, has_many
및 has_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에는 더 많은 옵션이 있으므로 설명서를 확인하십시오.
즐겨! :)
.amoeba_dup
아닙니다 .dup
. 이 코드를 실행하려고했지만 여기에서 작동하지 않았습니다.
ID를 복사하지 않으려면 ActiveRecord :: Base # dup을 사용하십시오.
.clone
나는 일반적으로 속성을 복사하여 변경해야 할 사항을 변경합니다.
new_user = User.new(old_user.attributes.merge(:login => "newlogin"))
unknown attribute
has_many 관계로 인해 열이 있기 때문에 하나의 열에 오류가 발생합니다. 이 주위에 어떤 방법이 있습니까?
User.create(old_user.attributes.merge({ login: "newlogin", id: nil }))
. 올바른 고유 ID를 가진 새 사용자를 저장합니다.
연관성이있는 깊은 사본이 필요한 경우 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
다음은 #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 버전이 필요합니다
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'}
q = p.clone
, 다음p == q
, 나는 얻을true
다시. 반면에, 내가 사용하는 경우q = p.dup
, 내가 수false
를 비교할 때 다시.