0

I've tried to put results from my vote model in a hash for further usage, but I don't know how to create a hash key from a variable in Ruby. See example below:

    def create_hash_array(campaign_votes)
        target_hash = Hash.new
        campaign_votes.each_with_index do |cv,i|
          target_hash[cv.content_id] = {} if i == 0

          if target_hash[cv.content_id].member?(cv.vote_button_id)
            target_hash[cv.content_id][cv.vote_button_id] = (target_hash[cv.content_id][cv.vote_button_id]).to_i + 1
          else
            target_hash[cv.content_id] = {cv.vote_button_id => nil}
          end

        end
        target_hash
    end

Usually I got an error:

undefined method `member?' for nil:NilClass

but it comes from unrecognized target_hash[cv.content_id], how can I make does variable to be recognized target_hash[cv.content_id] ??

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
KIT
  • 155
  • 1
  • 6
  • The error is obvious as `target_hash[cv.content_id]` tries to fetch value from hash with key `cv.content_id` which is not set yet and is nil and you calling `member` on it. Basically, do u want to nest your hash with `cv.vote_button_id` key if it exists right? – Md. Farhan Memon Apr 24 '17 at 21:34

1 Answers1

3

I think your code can be boiled down to this:

def create_hash_array(campaign_votes)
  target_hash = Hash.new { |h,k| h[k] = Hash.new(0) }

  campaign_votes.each do |cv|
    target_hash[cv.content_id][cv.vote_button_id] += 1
  end

  target_hash
end

There's multiple problems here, many to do with getting all tangled up in the process. You initialize the element of the target_hash structure only on the 0 index position, yet each campaign_vote could have different content_id values, meaning you're missing out on those.

This approach creates a single auto-generating Hash that will populate keys with counter hashes, that is hashes defaulting to 0. That means you can always navigate them and += 1 will work because of the default.

This approach is pretty common in Ruby, especially Hash.new(0), which is super handy for doing simple counters of arbitrary objects.

tadman
  • 208,517
  • 23
  • 234
  • 262