연관 및 속성 하의 여러 작업과 연관을 포함한 active_record 객체를 쉽게 복제합니다.
여기를 참조하세요.
목표는 관련 태그나 카테고리를 유지하면서 블로그 게시물을 복사하는 등 하위 항목을 포함한 ActiveRecord 개체를 쉽고 빠르게 재현할 수 있는 것이었습니다.
이 보석은 아메바(작은 생명체)가 번식에 능숙하기 때문에 "아메바"라는 이름이 붙여졌습니다. 그들의 자녀와 손주들도 빠르고 쉽게 번식합니다.
활성 레코드 모델을 복제할 때 연결된 하위 레코드 개체의 복제를 허용하는 ActiveRecord 확장 gem입니다.
레일스 5.2, 6.0, 6.1과 호환됩니다. Rails 4.2~5.1의 경우 버전 3.x를 사용하세요.
다음 연결 유형을 지원합니다.
has_many
has_one :through
has_many :through
has_and_belongs_to_many
복사할 필드를 구성하기 위한 간단한 DSL입니다. DSL은 레일 모델에 적용하거나 즉시 사용할 수 있습니다.
상위 아메바 설정을 상속하는 STI(Single Table Inheritance) 하위 항목을 지원합니다.
포괄적, 배타적, 무차별(모든 것을 복사라고도 함)과 같은 다양한 구성 스타일.
다대다 레코드의 하위 항목 복제 또는 단순히 원래 연결 유지를 지원합니다.
자동 드릴다운, 즉 하위 및 손자 레코드의 반복 복사를 지원합니다.
고유성을 표시하고 비즈니스 논리 요구 사항에 따라 데이터의 무결성을 보장하는 데 도움이 되는 필드 전처리를 지원합니다(예: "사본" 또는 유사한 텍스트 앞에 추가).
사용자 정의 람다 블록을 사용하여 필드 전처리를 지원하므로 예를 들어 복사본을 만드는 동안 사용자 정의 논리가 필요한 경우 기본적으로 원하는 모든 작업을 수행할 수 있습니다.
Amoeba는 복사된 레코드 필드에 대해 다음과 같은 전처리 작업을 수행할 수 있습니다.
세트
앞에 추가
추가
무효화하다
사용자 정의
정규식
당신이 기대했던 것과 같기를 바랍니다:
보석 설치 아메바
아니면 그냥 Gemfile에 추가하세요:
보석 '아메바'
아래 스타일 중 하나로 모델을 구성한 다음 dup
메소드를 정상적으로 실행하는 모델에서 amoeba_dup
메소드를 실행하십시오.
p = Post.create(:title => "Hello World!", :content => "Lorum ipsum dolor")p.comments.create(:content => "정말 좋아요!")p.comments.create(: content => "이건 짜증나!")puts Comment.all.count #은 2여야 합니다.my_copy = p.amoeba_dupmy_copy.saveputs Comment.all.count #는 4여야 합니다.
기본적으로 활성화되면 amoeba는 연결된 모든 하위 레코드를 자동으로 복사하여 새 상위 레코드와 연결합니다.
나열하는 필드만 포함하거나 제외하지 않는 필드만 포함하도록 동작을 구성할 수 있습니다. 세 가지 중에서 성능이 가장 뛰어난 것은 무차별 스타일이고, 그 다음은 포괄적 스타일이며, 배타적 스타일은 각 필드에 대한 추가 명시적 확인이 필요하기 때문에 가장 느립니다. 이 성능 차이는 읽고 쓰기 가장 쉬운 스타일을 기준으로 사용할 스타일을 선택할 수 있을 정도로 무시할 수 있습니다. 그러나 데이터 트리가 충분히 크고 복사할 필드를 제어해야 하는 경우 포함 스타일이 더 나을 수 있습니다. 독점 스타일보다 선택.
이러한 예는 실제 시나리오에 대한 대략적인 근사치일 뿐이며 특히 현실적이지 않을 수 있으며 기능 사용법을 보여주기 위한 목적으로만 사용됩니다.
이는 가장 기본적인 사용 사례이며 알려진 연결을 복사할 수 있습니다.
다음과 같은 블로그 모델이 있는 경우:
클래스 포스트 < ActiveRecord::Base has_many :commentsendclass 코멘트 < ActiveRecord::Base 소속_대상:후말
간단히 아메바 구성 블록을 모델에 추가하고 다음과 같이 하위 레코드 복사를 활성화하는 활성화 메서드를 호출합니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 아메바 가능 endendclass 코멘트 < ActiveRecord::Base 소속_대상:후말
amoeba_dup
메소드를 실행하면 하위 레코드가 자동으로 복사됩니다.
연관 중 일부만 복사하고 나머지는 복사하지 않으려면 포괄적 스타일을 사용할 수 있습니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 has_many :태그 has_many :저자 아메바 doenableinclude_association :tagsinclude_association :저자 endendclass 코멘트 < ActiveRecord::Base 소속_대상:후말
아메바 블록 내에서 포괄적 스타일을 사용하는 것은 실제로 아메바를 활성화하려는 것을 의미하므로 활성화 메서드를 실행할 필요는 없지만 해를 끼치지는 않습니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 has_many :태그 has_many :작성자 아메바 doinclude_association :tagsinclude_association :저자 endendclass 코멘트 < ActiveRecord::Base 소속_대상:후속
배열을 전달하여 복사할 필드를 지정할 수도 있습니다. 단일 값으로 include_association
을 호출하면 이미 포함된 필드 목록에 추가됩니다. 배열을 전달하면 배열이 원래 값을 덮어씁니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 has_many :태그 has_many :저자 아메바 doinclude_association [:tags, :authors] endendclass 코멘트 < ActiveRecord::Base 소속_대상:후속
이 예에서는 게시물의 태그와 작성자를 복사하지만 댓글은 복사하지 않습니다.
포괄적 스타일을 사용하면 이전에 선택한 다른 스타일이 자동으로 비활성화됩니다.
제외할 필드보다 포함할 필드가 더 많은 경우 전용 스타일을 사용하여 수행해야 하는 입력 및 읽기 양을 줄일 수 있습니다. 명시적으로 제외되지 않은 모든 필드는 복사됩니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 has_many :태그 has_many :작성자 아메바 doexclude_association :댓글 endendclass 코멘트 < ActiveRecord::Base 소속_대상:후속
이 예는 포괄적 스타일 예와 동일한 작업을 수행합니다. 게시물의 태그와 작성자는 복사하지만 댓글은 복사하지 않습니다. 포함 스타일과 마찬가지로 제외할 필드를 지정할 때 아메바를 명시적으로 활성화할 필요가 없습니다.
독점 스타일을 사용하면 이전에 선택한 다른 모든 스타일이 자동으로 비활성화됩니다. 따라서 포함 필드를 선택한 다음 일부 제외 필드를 선택하면 exclude_association
메서드는 이전에 선택한 포함 스타일을 비활성화하고 해당 포함 필드를 지웁니다. .
또한 포함 또는 제외 관계에 대한 추가 조건을 경로 지정해야 하는 경우 메서드 이름을 :if
옵션으로 경로 지정할 수 있습니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 has_many :태그 amoeba doinclude_association :comments, if: :popular? 끝 def 인기?좋아요 > 15 끝
Post.first.amoeba_dup
호출한 후 likes
모든 댓글보다 15보다 크면 복제되지만 다른 상황에서는 관계가 복제되지 않습니다. exclude_association
에도 동일한 동작이 적용됩니다.
주의하세요 ! 당신이 썼다면 :
클래스 포스트 < ActiveRecord::Base has_many :댓글 has_many :태그 amoeba doexclude_association :tagsinclude_association :comments, if: :popular? 끝 def 인기?좋아요 > 15 끝
포함 전략은 popular?
메소드 호출(반대 상황에서도 동일)
다대다 관계를 사용하는 경우 단순히 원본 레코드와의 연결을 유지하는 대신 원본 관련 레코드를 실제로 복제하도록 amoeba에 지시할 수 있습니다. 복제는 쉽습니다. 포함하거나 제외할 필드를 알려주는 것과 같은 방식으로 복제할 필드를 아메바에게 알려주기만 하면 됩니다.
클래스 포스트 < ActiveRecord::Base has_and_belongs_to_many :경고 has_many :post_widgets has_many :widgets, :through => :post_widgets 아메바 doenableclone [:widgets, :warnings] endendclass 경고 < ActiveRecord::Base has_and_belongs_to_many :postsendclass PostWidget < ActiveRecord::Base 소속_대상:위젯 own_to :postendclass 위젯 < ActiveRecord::Base has_many :post_widgets has_many :게시물, :through => :post_widgetsend
이 예는 실제로 데이터베이스의 경고와 위젯을 복제합니다. 원래 데이터베이스에 3개의 경고가 있었다면 게시물을 복제하면 데이터베이스에 6개의 경고가 표시됩니다. 이는 새 게시물이 기존 경고와 다시 연결되고 해당 경고 자체는 복제되지 않는 기본 동작과 대조됩니다.
기본적으로 ameba는 다음 연관 유형의 하위 항목을 인식하고 복사를 시도합니다.
하나 있어요
많다
많은 사람을 갖고 있고 속해 있다
아메바 구성 블록 내의 recognize
메소드를 사용하여 아메바가 적용되는 연관 유형을 제어할 수 있습니다.
클래스 포스트 < ActiveRecord::Base has_one : 구성 has_many :댓글 has_and_belongs_to_many :태그 아메바 dorecognize [:has_one, :has_and_belongs_to_many] endendclass 코멘트 < ActiveRecord::Base own_to :postendclass 태그 < ActiveRecord::Base has_and_belongs_to_many :postsend
이 예에서는 게시물의 구성 데이터를 복사하고 새 게시물과 연결된 태그를 유지하지만 게시물의 댓글은 복사하지 않습니다. 왜냐하면 amoeba는 has_one
및 has_and_belongs_to_many
연결의 하위 항목만 인식하고 복사하며 이 예에서 댓글은 has_and_belongs_to_many
연결이 아니기 때문입니다.
복사 시 일반( has_*
연관 기반이 아닌) 필드의 값이 유지되지 않도록 하려면 다음과 같이 필드를 "0으로 설정"하거나 "무효화"할 수 있습니다.
클래스 주제 < ActiveRecord::Base has_many :postsendclass 포스트 < ActiveRecord::Base 소속_대상:주제 has_many :댓글 amoeba doenablenullify :date_publishednullify :topic_id endendclass 코멘트 < ActiveRecord::Base 소속_대상:후속
이 예에서는 게시물의 모든 댓글을 복사합니다. 또한 게시 날짜가 무효화되고 게시물이 원래 주제와 분리됩니다.
포함 및 제외 스타일과 달리 null 필드를 지정해도 amoeba가 모든 하위 레코드를 자동으로 복사할 수는 없습니다. 활성 레코드 개체와 마찬가지로 마이그레이션에 기본값이 있는 경우 nil
대신 기본 필드 값이 사용됩니다.
모든 복제된 객체에 대해 임의의 값으로 필드를 설정하려면 set
지시문을 사용할 수 있습니다. 예를 들어, 일종의 승인 프로세스가 연결된 개체를 복사하려는 경우 새 개체의 상태를 다시 열림 또는 "진행 중"으로 설정하려고 할 수 있습니다.
클래스 포스트 < ActiveRecord::Base 아메바 doset :state_tracker => "open_for_editing" 끝
이 예에서 게시물이 복제되면 해당 게시물의 state_tracker
필드에 항상 open_for_editing
값이 부여되어 시작됩니다.
복사 단계 중에 복사된 객체의 필드 시작 부분에 문자열을 추가할 수 있습니다.
클래스 포스트 < ActiveRecord::Base amoeba doenableprepend :title => "복사본" 끝
복사 단계 중에 복사된 객체의 필드 끝에 문자열을 추가할 수 있습니다.
클래스 포스트 < ActiveRecord::Base amoeba doenableappend :title => "복사본" 끝
복사 단계 중에 복사된 개체의 필드에 대해 검색 및 바꾸기 쿼리를 실행할 수 있습니다.
클래스 포스트 < ActiveRecord::Base amoeba doenableregex :contents => {:replace => /dog/, :with => 'cat'} 끝
사용자 정의 메서드를 실행하여 기본적으로 원하는 작업을 수행할 수 있습니다. 단순히 람다 블록이나 람다 블록 배열을 customize
지시문에 전달하면 됩니다. 각 블록은 동일한 형식을 가져야 합니다. 즉, 각 블록은 원래 개체와 새로 복사된 개체라는 두 개의 매개 변수를 허용해야 합니다. 그러면 다음과 같이 원하는 대로 무엇이든 할 수 있습니다.
클래스 포스트 < ActiveRecord::Base amoeba doprepend :title => "안녕하세요! "customize(lambda { |original_post,new_post| if original_post.foo == "bar"new_post.baz = "qux" end})append :comments => "... 뭔지 알아요 내 말은?" 끝
또는 배열을 사용하여 다음을 수행합니다.
클래스 포스트 < ActiveRecord::Base has_and_belongs_to_many :태그 amoeba doinclude_association :tagscustomize([ Lambda do |orig_obj,copy_of_obj|# 좋은 내용은 여기에 갑니다. end,lambda do |orig_obj,copy_of_obj|# 더 좋은 내용은 여기에 갑니다. end]) 끝
기본적으로 모든 복사 및 필드 사전 처리 후에 실행 사용자 정의를 위해 전달된 Lambda 블록입니다. 사용자 정의 또는 필드 사전 처리 전에 메서드를 실행하려면 customize
의 사촌 override
사용할 수 있습니다. 사용법은 위와 동일합니다.
클래스 포스트 < ActiveRecord::Base amoeba doprepend :title => "안녕하세요! "override(lambda { |original_post,new_post| if original_post.foo == "bar"new_post.baz = "qux" end})append :comments => "... 뭔지 알아요 내 말은?" 끝
단일 전처리기를 여러 필드에 동시에 적용할 수 있습니다.
클래스 포스트 < ActiveRecord::Base amoeba doenableprepend :title => "복사본", :contents => "복사된 내용: " 끝
단일 모델에 여러 전처리 지시문을 한 번에 적용할 수 있습니다.
클래스 포스트 < ActiveRecord::Base amoeba doprepend :title => "복사본", :contents => "원본 내용: "append :contents => "(복사된 버전)"regex :contents => {:replace => /dog/, :with => ' 고양이'} 끝
이 예의 결과는 다음과 같습니다.
포스트 = 포스트.생성( :title => "안녕하세요.", :contents => "나는 개를 좋아한다, 개는 굉장하다.")new_post = post.amoeba_dupnew_post.title # "Hello world 사본"new_post.contents # "원본 내용: 나는 고양이를 좋아한다, 고양이는 굉장하다. (복제본)"
nullify
와 마찬가지로 전처리 지시문은 연결된 하위 레코드 복사를 자동으로 활성화하지 않습니다. 전처리 지시어만 사용하고 하위 레코드를 복사하고 싶지만 include_association
또는 exclude_association
목록이 제공되지 않는 경우에도 모델의 amoeba 블록 내에서 활성화 메서드를 호출하여 하위 레코드 복사를 명시적으로 활성화해야 합니다.
각 모델의 아메바 블록 내에서 구성 방법을 조합하여 사용할 수 있습니다. 인식된 연결 유형은 포함 또는 제외 목록보다 우선합니다. 포괄적 스타일은 배타적 스타일보다 우선하며, 이 두 가지 명시적 스타일은 무분별한 스타일보다 우선합니다. 즉, 복사할 필드를 나열하는 경우 amoeba는 나열된 필드만 복사하거나 경우에 따라 제외하지 않는 필드만 복사합니다. 또한 필드 유형이 인식되지 않으면 포함 목록에 표시되는지 여부에 관계없이 복사되지 않습니다. amoeba가 모든 하위 레코드를 자동으로 복사하도록 하려면 include_association
또는 exclude_association
사용하여 필드를 나열하지 마십시오.
다음 예제 구문은 완벽하게 유효하며 포괄적 스타일을 사용하게 됩니다. amoeba 블록 내에서 구성 메서드를 호출하는 순서는 중요하지 않습니다.
클래스 주제 < ActiveRecord::Base has_many :postsendclass 포스트 < ActiveRecord::Base 소속_대상:주제 has_many :댓글 has_many :태그 has_many :작성자 amoeba doexclude_association :authorsinclude_association :tagsnullify :date_publishedprepend :title => ""append :contents => "(복사된 버전)"regex :contents => {:replace => /dog/, :with => 'cat'}include_association :authorsenablenullify :topic_id endendclass 코멘트 < ActiveRecord::Base 소속_대상:후속
이 예에서는 게시물의 모든 태그와 작성자를 복사하지만 댓글은 복사하지 않습니다. 또한 게시 날짜가 무효화되고 게시물이 원래 주제와 분리됩니다. 또한 이전 전처리 예시에서와 같이 게시물의 필드를 전처리합니다.
우선순위 때문에 포함 스타일이 사용되며 제외 필드 목록은 참조되지 않습니다. 또한 include_association
사용할 때 아메바가 자동으로 활성화되므로 enable
방법은 중복됩니다.
전처리 지시문은 하위 레코드가 복사된 후 이 순서대로 실행됩니다.
널 필드
앞에 추가
추가
검색 및 바꾸기
전처리 지시문은 포함 및 제외 목록에 영향을 주지 않습니다.
아메바가 원하는 만큼 체인을 계속 복사하도록 할 수 있습니다. 하위 모델을 복사하려는 각 모델에 아메바 블록을 추가하기만 하면 됩니다. Amoeba는 활성화된 모든 손주로 자동으로 재귀하여 복사합니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 아메바 가능 endendclass 코멘트 < ActiveRecord::Base 소속_대상:게시물 has_many :등급 아메바 가능 endendclass 등급 < ActiveRecord::Base 소속_대상 :댓글끝
이 예에서 게시물이 복사되면 amoeba는 게시물의 모든 댓글을 각각 복사하고 각 댓글의 평점도 복사합니다.
has_one :through
연결을 사용하는 것은 간단합니다. has_one
연결을 사용하여 각 모델에서 amoeba를 활성화하면 amoeba는 다음과 같이 자동으로 재귀적으로 드릴다운합니다.
클래스 공급자 < ActiveRecord::Base has_one :계정 has_one :역사, :through => :계정 아메바 가능 endendclass 계정 < ActiveRecord::Base 소속:공급업체 has_one :역사 아메바 가능 endendclass 기록 < ActiveRecord::Base 소속_대상:계정
has_many :through
연관 복사는 자동으로 작동합니다. has_and_belongs_to_many
연결과 동일한 방식으로 복사를 수행합니다. 즉, 실제 하위 레코드는 복사되지 않고 연결만 유지됩니다. 원하는 경우 일부 필드 전처리기를 중간 모델에 추가할 수 있지만 반드시 필요한 것은 아닙니다.
클래스 어셈블리 < ActiveRecord::Base has_many : 매니페스트 has_many :parts, :through => :manifests 아메바 가능 endendclass 매니페스트 < ActiveRecord::Base 속한다:조립품 소속:부분 amoeba doprepend :notes => "복사본" endendclass 파트 < ActiveRecord::Base has_many : 매니페스트 has_many :어셈블리, :through => :manifests 아메바 가능 끝
구성 블록을 모델의 amoeba 메소드에 전달하여 amoeba가 객체를 복사하는 방법을 즉시 제어할 수 있습니다. 구성 방법은 정적이지만 구성은 인스턴스별로 적용됩니다.
클래스 포스트 < ActiveRecord::Base has_many :댓글 amoeba doenableprepend :title => "복사본" endendclass 코멘트 < ActiveRecord::Base own_to :postendclass PostsController < ActionController def Duplicate_a_postold_post = Post.create( :title => "Hello world", :contents => "Lorum ipsum")old_post.class.amoeba do prepend :contents => "여기 복사본이 있습니다: "endnew_post = old_post.amoeba_dupnew_post.title # "Hello world의 복사본"이어야 합니다.new_post.contents #은 "여기 복사본이 있습니다: Lorum ipsum"new_post.save 끝
ActiveRecord에서 제공하는 단일 테이블 상속을 사용하는 경우 아메바가 자동으로 상위 클래스와 동일한 방식으로 하위 클래스를 처리하도록 할 수 있습니다. 당신이 해야 할 일은 상위 클래스의 amoeba 블록 내에서 propagate
메소드를 호출하는 것뿐입니다. 그러면 모든 하위 클래스도 비슷한 방식으로 복사해야 합니다.
create_table :products, :force => true do |t| t.string :type # 이것은 STI 열입니다. # 이것은 모든 제품에 속합니다 t.string :제목 t.decimal :가격 # 이것은 셔츠 전용입니다. t.decimal :소매_길이 t.decimal :collar_size # 이것은 컴퓨터에만 해당됩니다. t.integer :ram_size t.integer :hard_drive_sizeendclass 제품 < ActiveRecord::Base has_many :이미지 has_and_belongs_to_many :카테고리 아메바 전파 활성화 가능 endendclass 셔츠 < Productendclass 컴퓨터 < Productendclass ProductsController def some_methodmy_shirt = Shirt.find(1)my_shirt.amoeba_dupmy_shirt.save# 이 셔츠는 이제 다음과 같아야 합니다.# - 모든 상위 이미지의 자체 복사본을 가지고 있습니다.# - 상위 이미지와 동일한 카테고리에 있어야 합니다. 끝
이 예에서는 Product의 하위 항목인 이 셔츠와 관련된 모든 이미지와 섹션을 복제해야 합니다.
기본적으로 전파에서는 복종적 양육 방식을 사용합니다. 즉, 상위 항목의 구성 설정이 적용되지만 하위 설정이 있는 경우 DSL 메서드 호출 방법에 따라 상위 설정에 추가되거나 상위 설정을 덮어씁니다.
소위 "육아 스타일"이라고 하는 이 동작을 변경하여 부모 설정에 우선권을 부여하거나 모든 자식 설정을 무시할 수 있습니다.
:relaxed
육아 스타일은 부모 설정을 선호합니다.
클래스 제품 < ActiveRecord::Base has_many :이미지 has_and_belongs_to_many :섹션 아메바 doexclude_association :imagespropagate :편안한 endendclass 셔츠 < 상품보기 include_association :이미지 include_association :섹션 prepend :title => "복사본"end
이 예에서는 하위 항목의 충돌하는 include_association
설정이 무시되고 상위 exclude_association
설정이 사용됩니다.