custom hash from group_by hash
It sounds like you're trying to group transactions by member_id and company_id, though in the code you posted you are only grouping by member_id and then overwriting the company with each new transactions' company.

If you pass a block to group_by, though, you can group by more than a simple method on the object, for instance you can group by an array of attributes that match, such as:

transactions.group_by { |transaction| [transaction.member_id, transaction.company_id] }


and then you still have to loop through and format the transactions how you want, but you can clean that up as well, by using map and each_with_object:

transactions.
  group_by { |transaction| [transaction.member_id, transaction.company_id] }.
  each_with_object({}) do |((member_id, _), transactions), data|
    data[member_id] = {
      # no need to keep rebuilding the company hash, all transactions belong to
      # the same company
      company: { id: transactions.first.company_id,
                 name: transactions.first.company_name },
      transactions: transactions.map do |transaction|
        { 
          particulars: transaction.particulars,
          contribution: { contribution1: transaction.contribution1,
                          contribution2: transaction.contribution2 }
        }
      end
    }
  end


This can be cleaned up even more, by moving the generation of these hashes to presenters but that's just moving the code around at this point, regardless you still need to go through all the transactions and present them as the hash, so the loop is unavoidable.