<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jeroen van Baarsen</title>
    <description>The latest articles on DEV Community by Jeroen van Baarsen (@jvanbaarsen).</description>
    <link>https://dev.to/jvanbaarsen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F121178%2F7f76b908-870e-4dd6-8dd5-e4fc6bead0a8.jpg</url>
      <title>DEV Community: Jeroen van Baarsen</title>
      <link>https://dev.to/jvanbaarsen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jvanbaarsen"/>
    <language>en</language>
    <item>
      <title>Diving into Ruby's #dup and #clone</title>
      <dc:creator>Jeroen van Baarsen</dc:creator>
      <pubDate>Wed, 27 Feb 2019 07:01:41 +0000</pubDate>
      <link>https://dev.to/appsignal/diving-into-rubys-dup-and-clone-8fa</link>
      <guid>https://dev.to/appsignal/diving-into-rubys-dup-and-clone-8fa</guid>
      <description>&lt;p&gt;In today's post, we will look into Ruby's &lt;code&gt;#dup&lt;/code&gt; and &lt;code&gt;#clone&lt;/code&gt;. We'll start with a real-life example that triggered this interest. After that, we'll dive deeper with the goal of learning how &lt;code&gt;#dup&lt;/code&gt; is implemented in Ruby and how it compares to &lt;code&gt;#clone&lt;/code&gt;.  We'll then close of by implementing our own &lt;code&gt;#dup&lt;/code&gt; method. Let's go!&lt;/p&gt;

&lt;h1&gt;
  
  
  How I Started Using Dup
&lt;/h1&gt;

&lt;p&gt;When I worked at a company that specialized in setting up campaigns for NGO's to collect donations, I regularly had to copy campaigns and create new ones. For example, after the 2018 campaign ended, a new one for 2019 was needed.&lt;/p&gt;

&lt;p&gt;A campaign usually had loads of configuration options, which I didn't really feel like setting up again. It would take quite some time and was error-prone. So I started by copying the DB record and went from there.&lt;/p&gt;

&lt;p&gt;For the first few campaigns, I actually copied that by hand. It looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;current_campaign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_campaign&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updated_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Campaign 2019"&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This works, but requires a lot of typing, not to mention it is error-prone. I have forgotten to set the &lt;code&gt;created_at&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt; a few times in the past.&lt;/p&gt;

&lt;p&gt;Since this felt like a bit of a pain, I couldn't imagine that it was the best way to go about it. And it turns out, there is a better way!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;new_campaign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;dup&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Campaign 2019"&lt;/span&gt;
&lt;span class="n"&gt;new_campaign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will set the ID and the timestamps to &lt;code&gt;nil&lt;/code&gt;, which is exactly what we want to accomplish.&lt;/p&gt;

&lt;p&gt;This was how I first got into using &lt;code&gt;#dup&lt;/code&gt;. Now, let's go and take a deeper look into how &lt;code&gt;#dup&lt;/code&gt; actually works.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Going on Under the Hood?
&lt;/h2&gt;

&lt;p&gt;The default Ruby implementation of the &lt;code&gt;#dup&lt;/code&gt; method allows you to add a special initializer to your object that is only called when an object is initialized via the &lt;code&gt;#dup&lt;/code&gt; method. These methods are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initialize_copy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;initialize_dup&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implementation of these methods is actually quite interesting, as they don't do anything by default. They are basically placeholders for you to override.&lt;/p&gt;

&lt;p&gt;This is taken directly from the Ruby source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt;
&lt;span class="nf"&gt;rb_obj_dup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;dup&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;special_object_p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;dup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rb_obj_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rb_obj_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;init_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;rb_funcall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id_init_dup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dup&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For us, the interesting part is on line 11 where Ruby calls the initializer method &lt;code&gt;#intialize_dup&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;rb_funcall&lt;/code&gt; is a function that is used in the ruby C code a lot. It is used to call methods on an object. In this case it will call &lt;code&gt;id_init_dup&lt;/code&gt; on the &lt;code&gt;dup&lt;/code&gt; object. The &lt;code&gt;1&lt;/code&gt; tells how many arguments there are, in this case only one: &lt;code&gt;obj&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's dive a bit deeper and look at that implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt;
&lt;span class="nf"&gt;rb_obj_init_dup_clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rb_funcall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id_init_copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see in this example, nothing is actually happening other than it calling &lt;code&gt;id_init_copy&lt;/code&gt;. Now that we are down the rabbit hole, let's look at that method as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt;
&lt;span class="nf"&gt;rb_obj_init_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;rb_check_frozen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;rb_check_trusted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;TYPE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;rb_obj_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;rb_obj_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rb_raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rb_eTypeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"initialize_copy should take same class object"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even though there is more code, nothing special is happening except for some checks that are required internally (but that might be a good subject for another time).&lt;/p&gt;

&lt;p&gt;So what happens in the implementation is that Ruby gives you an endpoint and provides you with the tools needed to implement your own interesting behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rails' Dup Implementation
&lt;/h2&gt;

&lt;p&gt;This is exactly what Rails did in a bunch of places, but for now, we are only interested in how the &lt;code&gt;id&lt;/code&gt; and timestamp fields get cleared.&lt;/p&gt;

&lt;p&gt;The ID gets cleared in the core module for ActiveRecord. It takes into account what your primary key is, so even if you changed that, it will still reset it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# activerecord/lib/active_record/core.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize_dup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# :nodoc:&lt;/span&gt;
  &lt;span class="vi"&gt;@attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deep_dup&lt;/span&gt;
  &lt;span class="vi"&gt;@attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;primary_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;_run_initialize_callbacks&lt;/span&gt;

  &lt;span class="vi"&gt;@new_record&lt;/span&gt;               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="vi"&gt;@destroyed&lt;/span&gt;                &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="vi"&gt;@_start_transaction_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="vi"&gt;@transaction_state&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;

  &lt;span class="k"&gt;super&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The timestamps are cleared in the Timestamps module. It tells Rails to clear out all the timestamps that Rails can use for creating and updating (&lt;code&gt;created_at&lt;/code&gt;, &lt;code&gt;created_on&lt;/code&gt;, &lt;code&gt;updated_at&lt;/code&gt; and &lt;code&gt;updated_on&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# activerecord/lib/active_record/timestamp.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize_dup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# :nodoc:&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="n"&gt;clear_timestamp_attributes&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;An interesting fact here is that Rails deliberately chose to override the &lt;code&gt;#initialize_dup&lt;/code&gt; method instead of the &lt;code&gt;#initialize_copy&lt;/code&gt; method. Why would it do that? Let's investigate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Object#initialize_copy Explained
&lt;/h2&gt;

&lt;p&gt;In the above code snippets, we saw how Ruby calls &lt;code&gt;#initialize_dup&lt;/code&gt; when you use &lt;code&gt;.dup&lt;/code&gt; on a method. But there is also an &lt;code&gt;#initialize_copy&lt;/code&gt; method. To better explain where this is used, let's look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"#initialize_copy is called"&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize_dup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"#initialize_dup is called"&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dup&lt;/span&gt;

&lt;span class="c1"&gt;# =&amp;gt; #initialize_dup is called&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #initialize_copy is called&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can now see what the calling order is. Ruby first calls out to &lt;code&gt;#initialize_dup&lt;/code&gt; and then calls to &lt;code&gt;#initialize_copy&lt;/code&gt;. If we would have kept the call to &lt;code&gt;super&lt;/code&gt; out of the &lt;code&gt;#initialize_dup&lt;/code&gt; method, we would never have called &lt;code&gt;initialize_copy&lt;/code&gt;, so it is important to keep that in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Are There Other Methods to Copy Something?
&lt;/h2&gt;

&lt;p&gt;Now that we have seen this implementation, you might be wondering what is the use case for having two &lt;code&gt;#initialize_*&lt;/code&gt; methods. The answer is: there is another way to copy objects, called &lt;code&gt;#clone&lt;/code&gt;. You generally use &lt;code&gt;#clone&lt;/code&gt; if you want to copy an object including its internal state.&lt;/p&gt;

&lt;p&gt;This is what Rails is using with its &lt;code&gt;#dup&lt;/code&gt; method on ActiveRecord. It uses &lt;code&gt;#dup&lt;/code&gt; to allow you to duplicate a record without its "internal" state (id and timestamps), and leaves &lt;code&gt;#clone&lt;/code&gt; up to Ruby to implement.&lt;/p&gt;

&lt;p&gt;Having this extra method also asks for a specific initializer when using the &lt;code&gt;#clone&lt;/code&gt; method. For this, you can override &lt;code&gt;#initialize_clone&lt;/code&gt;. This method uses the same lifecycle as &lt;code&gt;#initialize_dup&lt;/code&gt; and will call up towards &lt;code&gt;#initialize_copy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Knowing this, the naming of the initializer methods makes a bit more sense. We can use &lt;code&gt;#initialize_(dup|clone)&lt;/code&gt; for specific implementations depending on whether you use &lt;code&gt;#dup&lt;/code&gt; or &lt;code&gt;#clone&lt;/code&gt;. If we have overarching behavior that is used for both, you can place it inside &lt;code&gt;#initialize_copy&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloning an Animal
&lt;/h2&gt;

&lt;p&gt;(just an example, no animals were hurt for this blog post)&lt;/p&gt;

&lt;p&gt;Now let's look at an example of how it works in practice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:dna&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dna&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_dna&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize_copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;original_animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize_dup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;original_animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dna&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_dna&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A new name"&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize_clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;original_animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;original_animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 2"&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_dna&lt;/span&gt;
    &lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;bello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;bello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Bello"&lt;/span&gt;
&lt;span class="n"&gt;bello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="n"&gt;bello_clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;
&lt;span class="n"&gt;bello_dup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dup&lt;/span&gt;

&lt;span class="n"&gt;bello_clone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Bello 2"&lt;/span&gt;
&lt;span class="n"&gt;bello_clone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 0&lt;/span&gt;

&lt;span class="n"&gt;bello_dup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "A new name"&lt;/span&gt;
&lt;span class="n"&gt;bello_dup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;age&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's break down what is actually happening here. We have a class called &lt;code&gt;Animal&lt;/code&gt;, and depending on how we copy the animal, it should have different behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When we clone the animal, the DNA remains the same, and its name will be the original name with 2 appended to it.&lt;/li&gt;
&lt;li&gt;When we duplicate the animal, we make a new animal based on the original one. It gets its own DNA and a new name.&lt;/li&gt;
&lt;li&gt;In all cases the animal starts as a baby.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We implemented three different initializers to make this happen. The &lt;code&gt;#initialize_(dup|clone)&lt;/code&gt; method will always call up to &lt;code&gt;#initialize_copy&lt;/code&gt;, thus ensuring that the age is set to 0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rounding up the CLONES and Other Animals
&lt;/h2&gt;

&lt;p&gt;Starting by explaining the itch we needed to scratch ourselves, we looked into copying a database record. We went from copying by hand in the Campaign example, to &lt;code&gt;#dup&lt;/code&gt; and &lt;code&gt;#clone&lt;/code&gt;. We then took it from the practical to the fascinating and looked into how this is implemented in Ruby. We also played around with &lt;code&gt;#clone&lt;/code&gt;ing and &lt;code&gt;#dup&lt;/code&gt;ing animals. We hope you enjoyed our deep dive as much as we did writing it.&lt;/p&gt;

</description>
      <category>academy</category>
      <category>engineering</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
