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] ??

1
  • 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? Commented Apr 24, 2017 at 21:34

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.