0

Goal: I would like to export a ruby hash to CSV

Challenge: I keep getting the error: 'undefined method `to_csv' for # Did you mean? to_s'.

Approach: I'm making a call to Stripe, receive JSON back, sort the data and end up with a hash like this:

{"33"=>{:name=>"John Doe", :currency=>"eur", :total=>18748}, "31"=>{:name=>"Jane Doe", :currency=>"eur", :total=>7222}}

Ideally, I would like to export that hash to CSV so it can be imported to Excel or Google Sheets.

Recurring_revenue.html.slim:

= link_to 'Download CSV', recurring_revenue_path(format: 'csv'), class: 'btn btn-success'

Pages controller:

@invoices = Stripe::Invoice.list(
  paid: true,
  expand: ['data.subscription'],
  limit: 100,
  date: {
    gte: params[:start_date],
    lte: params[:end_date]
  }
)

@coaches = {}

@invoices.auto_paging_each do |invoice|

  @coaches[invoice.subscription.metadata.coach_id] ||= {
    name: invoice.subscription.metadata.coach,
    currency: invoice.subscription.plan.currency,
    total: 0
  }

  @coaches[invoice.subscription.metadata.coach_id][:total] ||= 0
  @coaches[invoice.subscription.metadata.coach_id][:total] += invoice.total
end

respond_to do |format|
  format.html
  format.csv { send_data(@coaches.to_csv) }  
end

Page.rb

class Page < ApplicationRecord
  def self.to_csv
    attributes = %w{id email name}

    CSV.generate(headers: true) do |csv|
      csv << attributes

      all.each do |user|
        csv << attributes.map{ |attr| user.send(attr) }
      end
    end
  end
end

I have added include "csv" in application.rb. Can anybody have a look and let me know what I'm doing wrong?

Andy
  • 531
  • 1
  • 4
  • 19
  • Your `@coaches` is a hash. It obviously can't use your `Page.to_csv`. – Sergio Tulentsev Mar 06 '18 at 12:21
  • I'm not even sure how `Page.to_csv` is relevant here. – Sergio Tulentsev Mar 06 '18 at 12:35
  • Please enlighten me @SergioTulentsev? What would I do to make it work? – Andy Mar 06 '18 at 12:41
  • 1
    Please see the linked answers. Plenty of examples there. In short, there appears to be no `Hash#to_csv`, so you'll have to write a helper to serialize your hash. Not as simple as `@coaches.to_csv`. More like `coaches_to_csv(@coaches)`, where `coaches_to_csv` you will have to write. – Sergio Tulentsev Mar 06 '18 at 12:42
  • Also: https://github.com/am-kantox/see_as_vee – Aleksei Matiushkin Mar 06 '18 at 12:45
  • @mudasobwa: you use a separate profile for work? – Sergio Tulentsev Mar 06 '18 at 12:46
  • 1
    @SergioTulentsev yes, to distinguish what was indeed sponsored by my employer and what was done during polar sleepless nights :) – Aleksei Matiushkin Mar 06 '18 at 12:48
  • @SergioTulentsev Not sure I'm following. I'll create a method in my pages controller that has the logic from your example links and then call that? – Andy Mar 06 '18 at 12:58
  • @Andy: yes, this is the simplest thing that could work. Of course, controller is not the place for this csv serialization logic and it has to be moved elsewhere. But this is unrelated to the problem. – Sergio Tulentsev Mar 06 '18 at 13:01
  • Okay, so I added the link to hit the method: = link_to 'Download CSV', coaches_to_csv_path(@coaches), and I added the controller action: def coaches_to_csv coaches = params CSV.open('data.csv', 'wb') { |csv| coaches.to_a.each { |coach| csv << coach } } end – Andy Mar 06 '18 at 13:09
  • @SergioTulentsev getting the following error: undefined method `to_a'. What I find hard to understand is when the hash is nested, which it is here. – Andy Mar 06 '18 at 13:10
  • @Andy: what I do in such cases is stare at the code for a minute, try to determine which variables hold what data at what step, and then use __lots__ of debug-printing to confirm or reject my hypotheses. – Sergio Tulentsev Mar 06 '18 at 13:17
  • Cheers mate, I'll try. – Andy Mar 06 '18 at 13:20
  • @Andy: yep, it isn't too complicated. With a bit of pen-and-paper you should be able to do this. But if you get stuck/overwhelmed, hit me up on codementor, I'll guide you through. :) – Sergio Tulentsev Mar 06 '18 at 13:43
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/166331/discussion-between-andy-and-sergio-tulentsev). – Andy Mar 06 '18 at 14:48

0 Answers0