moiristo / deep_cloneable

This gem gives every ActiveRecord::Base object the possibility to do a deep clone that includes user specified associations.
MIT License
786 stars 88 forks source link

Recursive cloning #91

Closed rvfx closed 6 years ago

rvfx commented 6 years ago

My elements can contain themselves endlessly.

class MyElement
  has_many :children, foreign_key: 'parent_id', class_name: 'MyElement'
end

This works, but only for the amount of levels I type in:

my_element.deep_clone[
  { children: [
    { children: [
      { children: [
        :children
      ] }
  ] }
] }

Is there a way to automatically loop this so it works recursively? I tried the block functionality, but the cloned children aren't shown in there, so I cannot check if they exist.

my_element.deep_clone include: :children do |original, kopy|
  kopy.children if kopy.respond_to?(:children) # is always an empty array: []
end
moiristo commented 6 years ago

Interesting issue :) Maybe something like this could work? I based it on how I would implement it without deep_cloneable. I'm not sure if deep_cloneable adds a lot of value here, perhaps you could just make a duplicate method instead that uses dup directly. But it might be more concise if there are more things to include..

class MyElement
  has_many :children, foreign_key: 'parent_id', class_name: 'MyElement'

  def duplicate
    deep_clone(include: :children) do |original, kopy|
      kopy.children = original.children.map(&:duplicate) if original != self
    end
  end
end
new_element = my_element.duplicate
rvfx commented 6 years ago

Wow, it worked straightaway. There are several other associations to cover, that's why deep_clonable comes in very handy. Thanks a lot!