【问题标题】:Ruby on Rails export to csv - maintain mysql select statement orderRuby on Rails 导出到 csv - 维护 mysql 选择语句顺序
【发布时间】:2010-03-25 04:38:28
【问题描述】:

使用 FasterCSV 将一些数据从 mysql 导出到 csv 文件。我希望输出的 CSV 中的列与查询中的 select 语句的顺序相同。

例子:

rows = Data.find(
  :all,
  :select=>'name, age, height, weight'
)

headers = rows[0].attributes.keys
FasterCSV.generate do |csv|
  csv << headers
  rows.each do |r|
    csv << r.attributes.values
  end
end

CSV 输出:

height,weight,name,age
74,212,bob,23
70,201,fred,24
.
.
.

我希望 CSV 列的顺序与我的选择语句相同。显然属性方法是行不通的。关于确保我的 csv 文件中的列与 select 语句的顺序相同的最佳方法的任何想法?有很多数据和性能是一个问题。选择语句不是静态的。我意识到我可以遍历 rows.each 循环中的列名,但它似乎有点脏。

【问题讨论】:

    标签: mysql ruby-on-rails csv fastercsv


    【解决方案1】:

    使用Comma gem:

    class Data < ActiveRecord:Base
    
      comma do
        name
        age
        height
        weight
      end
    
      comma :height_weight do
       name
       age
       height_in_feet
       weight
     end
    
    
    end
    

    现在您可以按如下方式生成 CSV:

    Data.all(:select => 'name, age, height, weight').to_comma
    
    Data.all(:select => 'name, age, height_in_feet, weight').to_comma(:height_weight)
    

    编辑:

    ActiveRecord 查找器不支持结果集中的计算列,即

    data = Data.first(:select => 'name, age, height/12 as height_in_feet, weight')
    data.height_in_feet # throws error
    

    如果要包含计算列,可以使用select_extra_columns gem。

    【讨论】:

    • 谢谢,我会调查的。我可能应该提到这一点,但我的 select 语句是动态生成的,所以我不确定这是否可行。例如,我的选择语句可能是“姓名、年龄、身高/12 作为身高_in_feet、体重”。
    • 您可以为各种选择组合添加多个逗号部分。我已经修改了我的答案,以包含有关此的其他信息。
    • 我似乎无法重现您在编辑中谈到的错误。您使用的是什么版本的导轨,具体错误是什么?
    • 响应您的编辑:该代码绝对适合我(使用 ruby​​ 1.8.7)。而且我的选择语句是非常动态的,并且是从数据库中的其他表创建的——我无法在模型中定义每个不同的逗号块。除非我能以某种方式即时使用逗号块,否则我认为它不会起作用。所以也许我只需要咬紧牙关,在 rows.each 循环中按照我想要的顺序循环遍历属性值。
    • 我添加了另一个答案来解决您需求的动态方面。看看吧。
    【解决方案2】:

    试试这个:

    def export_to_csv (rows, col_names)
      col_names = col_names.split(",") if  col_names.is_a?(String)
      FasterCSV.generate do |csv|
        # header row
        csv << col_names
    
        # data rows
        rows.each do |row|
          csv << col_names.collect{|name| row.send(name)}
        end
      end
    end
    
    cols = 'name, age, height, weight'
    rows = Data.find(:all, :select=> cols)
    csv = export_to_csv(rows, cols)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多