views:

55

answers:

3

Hi,

Say I have a blog post with comments in rails, how do I clone it so I have another blog post with comments, both stored as new objects in the database with their own ids?

I know about the clone command, but it doesn't seem to copy over the comments - only links to them.

Is there a plugin or an easy way to do this in rails?

Thanks!

+1  A: 

Define a deep copy method

class BlogPost
...
    def deep_copy
    Marshal::load(Marshal.dump(self))
    end
...
end

This should do the trick! Edit : Just to clarify, what you are doing with this method is basically serializing your object to memory and then deserializing it in a new memory location, effectively creating a new object with the same field values as the original one.

Jas
If I have the following structure:Blog - id 1, Comment - id 1Will it be cloned as:Blog - id 2, Comment - id 2Or as:Blog - id 1, Comment - id 1?Thanks!
stringo0
It will contain the same values, so Blog#id = 1, Comment#id = 1. Anyway, why don't you fire your irb and test this immediately? All the best!
Jas
Thanks - this approach is definitely helpful in certain scenarios :)
stringo0
+2  A: 

Why do you want to use plugins? It's really very simple.

  1. clone the master object, the Post
  2. iterate over each comment in the master object, clone each comment and append it to the cloned post
  3. save the post, all comments will be saved and attached to that post
Simone Carletti
This is the default solution I'm planning on relying back on. However, something that did a deep clone with new id's would be awesome.
stringo0
+1  A: 

Since deep copying/cloning is going to look different for every Model class, it's usually left as an exercise to the developer. Here are two ways:

  1. Override clone (could be dangerous if you don't always want this behavior)

    class Post
    ...
      def clone
        new_post = super
        new_post.comments = comments.collect { |c| c.clone }
        new_post
      end
    ...
    end
    
  2. Create a deep_clone or deep_copy method and call it specifically

    class Post
    ...
      def deep_clone
        new_post = clone
        new_post.comments = comments.collect { |c| c.clone }
        new_post
      end
    ...
    end
    

Both of these guarantee the returned Post object and all its comments will be distinct entities in db (once you call save on the Post, of course).

bioneuralnet