Export CSV records with association data

时间:2019-04-17 00:48:06

标签: ruby csv

I am creating a CSV export for pdforms in my Rails application. At the moment, I have this method in my pdform model.

def self.as_csv 
  attributes = %w{user date_start date_finish location event_name description acct_num sub reason impact uuid topic}
  CSV.generate(headers: true) do |csv|
    csv << attributes

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

This works as intended, however, as shown in attributes, I have a user. I when exporting this CSV I am shown the User object. I would like to show the email of the user in the exported CSV.

I attempted to replace it with attributes = %w{user.email date_start date_finish location event_name description acct_num sub reason impact uuid topic} however I just get this error:

undefined method `user.email' for # Did you mean? user_id

I can do user_id however. But this is no help to the person who is glossing over this CSV as they do not know who the user associated with that ID is. How can I get the Users email to display in the CSV row rather than the id or the object itself?

1 个答案:

答案 0 :(得分:0)

我可能会避免在生产中使用此类代码,而希望使用更明确,更易于读取/调试的代码(例如在所讨论的模型上定义user_email方法,并在要导出的属性列表中引用该方法,或调用email并将其委托给关联机构或其他任何机构),但是如果您喜欢这种简洁的解决方案,则可能会起作用:

def self.as_csv 
  attrs = %w{user.email date_start date_finish location event_name description acct_num sub reason impact uuid topic}

  CSV.generate(write_headers: true, headers: attrs) do |csv|
    method_chains = attrs.map { |a| a.split('.') }

    find_each do |user|
      csv << method_chains.map do |chain| 
        chain.reduce(user) { |obj, method_name| obj = obj.try(method_name.to_sym) }
      end
    end
  end
end

它与您的几乎相同,另外还有reduce来“折叠”方法链和其他一些小的改进:

  • 我不是通过csv << attributes显式编写标题,而是通过选项将CSV.generate设置为标题
  • 我不是all.each而是通过find_each批量提取记录-如果表很大,它会产生很大的不同