활성 레코드 레코드를 복제하는 가장 쉬운 방법은 무엇입니까?
-
09-06-2019 - |
문제
프로세스에서 단일 필드를 변경하여 활성 레코드 레코드의 복사본을 만들고 싶습니다( 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에 저장되지 않은) 레코드를 제공합니다.
연결은 복사되지 않으므로 필요한 경우 수동으로 복사해야 합니다.
다른 팁
필요와 프로그래밍 스타일에 따라 클래스와 병합의 새로운 방법을 조합하여 사용할 수도 있습니다.더 나은 것이 부족해서 단순한 예를 들어, 특정 날짜에 예정된 작업이 있고 이를 다른 날짜에 복제하려고 한다고 가정합니다.작업의 실제 속성은 중요하지 않으므로 다음과 같습니다.
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로 변경하세요.
평화.
당신은 또한 아메바 보석 액티브레코드 3.2용.
귀하의 경우에는 아마도 nullify
, regex
또는 prefix
구성 DSL에서 사용할 수 있는 옵션입니다.
쉽고 자동적인 재귀적 복제를 지원합니다. 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에는 더 많은 옵션이 있으므로 설명서를 꼭 확인하세요.
즐기다!:)
사용 활성 레코드::베이스#dup 아이디를 복사하고 싶지 않다면
나는 일반적으로 속성을 복사하여 변경해야 할 사항을 변경합니다.
new_user = User.new(old_user.attributes.merge(:login => "newlogin"))
연관이 포함된 딥 카피가 필요한 경우 다음을 권장합니다. deep_cloneable 보석.
쉬운 방법은 다음과 같습니다.
#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
당신은 또한 확인할 수 있습니다 act_as_inheritable 보석.
"상속 가능으로 작동(Acts As Inheritable)은 Rails/ActiveRecord 모델용으로 특별히 작성된 Ruby Gem입니다.와 함께 사용하도록 되어 있습니다. 자기 참조 연관, 또는 상속 가능한 속성을 공유하는 상위 모델이 있는 모델입니다.이렇게 하면 상위 모델로부터 모든 속성이나 관계를 상속받을 수 있습니다."
추가하여 acts_as_inheritable
모델에 대해 다음 방법에 액세스할 수 있습니다.
상속_속성
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
상속_관계
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">
이것이 당신을 도울 수 있기를 바랍니다.
더 많은 논리가 있을 수 있으므로 모델을 복제할 때 필요한 모든 논리를 처리하는 새 클래스를 만드는 것이 좋습니다.이를 쉽게 하기 위해 도움이 될 수 있는 gem이 있습니다: 광대
문서 예제에 따라 사용자 모델의 경우:
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'}
다음은 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이 필요하지 않지만 최신 ActiveRecord 버전이 필요합니다. #dup
구현된 방법