title: Writing custom method for a hash on Ruby? on rails
body: <p>i'm trying (and actually succeded, but i don't understand how it works) to write a custom method for a hash in my model (I'm working on Ruby on Rails 6).</p>
  <p>My hash looks like this</p>
  <pre><code>my_hash = { 
   [['name_1', 'slug_1']=&gt;value_1],
   [['name_2', 'slug_2']=&gt;value_2],
   [['name_1', 'slug_1']=&gt;value_3],
   [['name_2', 'slug_2']=&gt;value_4] 
  }
  </code></pre>
  <p>So basically a hash of arrays. You notice that the 'keys' are arrays that repeat themselves many times, but with different values. What i want to achieve is to write a custom method that &quot;joins&quot; all the keys in only one key, which will have an array of values assigned, so basically i should be able to get:</p>
  <pre><code>my_hash = { 
   ['name_1', 'slug_1']=&gt;&quot;values&quot;: [value_1, value_3],
   ['name_2', 'slug_2']=&gt;&quot;values&quot;: [value_2, value_4]
  }
  </code></pre>
  <p>For that, I have this piece of code, which i use many times:</p>
  <pre><code>my_hash.inject({}) do |hash, record|
    # each record has the following format =&gt; [[&quot;unit_name&quot;, &quot;axis.slug&quot;]=&gt;average_value(float)]
    keys, value = record
    # now keys has [&quot;unit_name&quot;, &quot;axis.slug&quot;] and values equals average_value
    hash[keys.first] ||= {}
    hash[keys.first][keys.last] = value.to_f
    hash
  end
  </code></pre>
  <p>Since I use this many times, i wanted to write a custom method, so i did:</p>
  <pre><code>  def format_hash_data my_hash
      my_hash.inject({}) do |hash, record|
        # each record has the following format =&gt; [[&quot;unit_name&quot;, &quot;axis.slug&quot;]=&gt;average_value(float)]
        keys, value = record
        # now keys has [&quot;unit_name&quot;, &quot;axis.slug&quot;] and values equals average_value
        hash[keys.first] ||= {}
        hash[keys.first][keys.last] = value.to_f
        hash
      end
    end
  </code></pre>
  <p>And used it like: <code>my_hash = format_hash_data(my_hash)</code> with no success(it threw an error saying that 'format_hash_data' was not a valid method for the class).</p>
  <p>So I fiddled around and added 'self' to the name of the method, leaving:</p>
  <pre><code>  def self.format_hash_data my_hash
      my_hash.inject({}) do |hash, record|
        # each record has the following format =&gt; [[&quot;unit_name&quot;, &quot;axis.slug&quot;]=&gt;average_value(float)]
        keys, value = record
        # now keys has [&quot;unit_name&quot;, &quot;axis.slug&quot;] and values equals average_value
        hash[keys.first] ||= {}
        hash[keys.first][keys.last] = value.to_f
        hash
      end
    end
  </code></pre>
  <p>Which, to my surprise, worked flawlessly when using <code>my_hash = format_hash_data(my_hash)</code></p>
  <p>I don't really understand why adding 'self' makes my code works, maybe anyone can shed some light? I tried using things like <code>send()</code> or <code>instance_eval</code> first, to just send the piece of code to the actual hash as a method (something like <code>my_hash.instance_eval(my_method)</code>) but I couldn't get it working.</p>
  <p>I'm sorry about the long explanation, I hope i was clear enough so any of you who had this same dilemma can understand. Thanks in advance.</p>