alistairphillips.com

I’m : a web and mobile developer based in the Manning Valley, Australia.


PHP to Ruby - A journey of arrays

In most of my PHP applications I often return data as a nested array containing all the information I'd like to consume elsewhere. So in the case with TVScout my returned array in PHP would be something like:

<?php
    $result = array(
        'userid_01' => array(
            'chef' => array(
                'chef_result_01',
                'chef_result_02'
            ),
            'country' => array(
                'country_result_01',
                'country_result_02'
            )
        )
    )
?>

That way I've got all the watchlist terms, per user, with the results set out in a way that's easy to iterate over. But come the Ruby way, well I'm a bit stuck there and not at all happy with the code.

# Combine all watchlist item results per user/query and generate the emails
def self.sendit
  results = {}
  @notifications = Watchlist.email_details()
  @notifications.each do | item |
    # Do we have an entry for this user?
    if results[ item.user_id.to_s ].nil?
      results[ item.user_id.to_s ] = {}
    end

    if results[ item.user_id.to_s ][ item.query].nil?
      results[ item.user_id.to_s ].update( item.query => [] )
    end

    results[ item.user_id.to_s ][ item.query ].push( item )
  end
end

PHP is more than happy for me to check and generate array items any level deep without shouting at me about nil objects as Ruby does. The only way around it seemed to be to check if the item was empty, by using nil?, and creating it if it was. What is it that I'm missing or not doing in the "Ruby" way?

[UPDATE] Bryn found this post about how to accomplish this with minimum effort:

lazy = lambda { |h,k| h[k] = Hash.new(&lazy) }

h = Hash.new(&lazy)

h[1][2][3][4] = 5

p h     # {1=>{2=>{3=>{4=>5}}}}