Ответ 1
Используйте deep_clonable gem
new_survey = original_survey.clone :include => [:questions => :answers]
В настоящее время я клонирую одноуровневую ассоциацию:
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
Но это делает некоторые странные вещи, фактически заменяя исходные ответы, а затем создавая новые, так что идентификатор останавливается правильно.
Используйте deep_clonable gem
new_survey = original_survey.clone :include => [:questions => :answers]
Вам также может понравиться Amoeba gem для ActiveRecord 3.2.
В вашем случае вы, вероятно, захотите использовать опции nullify
, regex
или prefix
, доступные в конфигурации DSL.
Он поддерживает простое и автоматическое рекурсивное дублирование ассоциаций 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
Рекурсивное копирование ассоциаций легко, просто включите амебу на дочерние модели, а
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 имеет еще множество опций, поэтому не забудьте ознакомиться с документацией.
Наслаждайтесь!:)
Не должно быть..
new_question.answers << new_answer
end
new_template.questions << new_question
Вы также можете использовать метод 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