Daniel Bonnell
Daniel Bonnell

Reputation: 4997

ActiveRecord .dup on Association

I have two models, Survey and Question. A Survey has_many :questions and a Question belongs_to :survey. I know I can duplicate an instance of Survey by doing the following:

old_survey = Survey.last
new_survey = old_survey.dup

Now new_survey will be identical to old_survey except that its id attribute is nil. What I would like to know is how I can also duplicate associated objects, preferably without iterating through them or installing a 3rd party gem.

I'd like to do something like this:

old_survey = Survey.last
new_survey = old_survey.dup
new_survey.questions = old_survey.questions.dup
old_survey.save!

The above code doesn't work. If I call new_survey.questions.pluck(:id) I can see that the ids match old_survey.questions.pluck(:id), which is not desirable.

Obviously I could just iterate through old_survey.questions, but I'd like to find a more efficient way to accomplish this.

Upvotes: 3

Views: 5791

Answers (1)

NM Pennypacker
NM Pennypacker

Reputation: 6942

You could use the deep_clonable gem: https://github.com/moiristo/deep_cloneable

and then you could do something like this:

old_survey.dup include: :questions

But that adds another dependency to your app. The easiest way would be be to iterate through the old survey questions and assign ids as necessary. Your question states that you want to avoid doing so, but I really think it's the best (and most light-weight) option.

If you're willing to loop through the associated objects, this should do the trick:

def clone_with_questions
  new_survey = self.dup
  new_survey.save
  new_survey.questions = self.questions
  new_survey
end

@new_survey = Survey.last.clone_with_questions

Might have to tweak it a bit to work with your app, but that's the general idea.

Upvotes: 5

Related Questions