我目前正在克隆这样的单级关联:
class Survey < ActiveRecord::Base
def duplicate
new_template = self.clone
new_template.questions << self.questions.collect { |question| question.clone }
new_template.save
end
end
因此克隆Survey
然后克隆与该调查相关联的Questions
。精细。这很有效。
但我遇到的问题是每个问题has_many
Answers
。所以Survey has_many Questions which has_many Answers
。
我无法弄清楚如何正确克隆答案。我试过这个:
def duplicate
new_template = self.clone
self.questions.each do |question|
new_question = question.clone
new_question.save
question.answers.each do |answer|
new_answer = answer.clone
new_answer.save
new_question.answers << answer
end
new_template.questions << question
end
new_template.save
end
但实际上替换原始答案然后创建新答案会产生一些奇怪的东西,因此ID会正确停止匹配。
答案 0 :(得分:45)
new_survey = original_survey.clone :include => [:questions => :answers]
答案 1 :(得分:3)
您可能也喜欢ActiveRecord 3.2的Amoeba gem。
在您的情况下,您可能希望使用配置DSL中提供的nullify
,regex
或prefix
选项。
它支持has_one
,has_many
和has_and_belongs_to_many
关联的简单和自动递归复制,字段预处理以及高度灵活且功能强大的配置DSL,可以应用于模型和苍蝇。
请务必查看Amoeba Documentation,但使用非常简单......
刚
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
递归复制关联很容易,只需在子模型上启用amoeba
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还有更多选项,因此请务必查看文档。
享受! :)
答案 2 :(得分:1)
不使用宝石,您可以执行以下操作:
class Survey < ApplicationRecord
has_and_belongs_to_many :questions
def copy_from(last_survey)
last_survery.questions.each do |question|
new_question = question.dup
new_question.save
questions << new_question
end
save
end
…
end
然后您可以致电:
new_survey = Survey.create
new_survey.copy_from(past_survey)
这将把上次调查中的所有问题复制到新调查中,并将它们联系起来。
答案 3 :(得分:0)
不应该......
new_question.answers << new_answer
end
new_template.questions << new_question
答案 4 :(得分:-1)
您也可以使用rails dup方法对其进行别名,如下所示:
class Survey
has_many :questions, :inverse_of=>:survey, :autosave=>true
alias orig_dup dup
def dup
copy=orig_dup
copy.questions=questions
copy
end
end
class Questions
belongs_to :survey, :inverse_of=>:questions
has_many :answers, :inverse_of=>:question, :autosave=>true
alias orig_dup dup
def dup
copy=orig_dup
copy.answers=answers
copy
end
end
class Answer
belongs_to :question
end
然后你可以这样做
aaa = Survey.find(123).dup
aaa.save