54

CSV に変換したい ActiveRecord モデルの配列を取得しました。FasterCSV のような gem を調べてみましたが、ActiveRecord モデルではなく、文字列と配列で動作するようです。

要するに、変換したい:

user1 = User.first
user2 = User.last
a = [user1, user2]

に:

   id,username,bio,email
    1,user1,user 1 bio,user1 email
    1,user2,user 2 bio,user2 email

これを行う簡単なRailsの方法はありますか?

4

8 に答える 8

114

以下は、すべてのユーザーの属性をファイルに書き込みます。

CSV.open("path/to/file.csv", "wb") do |csv|
  csv << User.attribute_names
  User.find_each do |user|
    csv << user.attributes.values
  end
end

同様に、CSV 文字列を作成できます。

csv_string = CSV.generate do |csv|
  csv << User.attribute_names
  User.find_each do |user|
    csv << user.attributes.values
  end
end
于 2013-10-05T17:51:52.763 に答える
11

@ rudolph9の答えは本当に素晴らしいです。このタスクを定期的に行う必要がある人のためにメモを残しておきたいと思います。レーキ タスクとして作成することをお勧めします。

lib/tasks/users_to_csv.rake

# usage:
# rake csv:users:all => export all users to ./user.csv
# rake csv:users:range start=1757 offset=1957 => export users whose id are between 1757 and 1957
# rake csv:users:last number=3   => export last 3 users
require 'csv' # according to your settings, you may or may not need this line

namespace :csv do
  namespace :users do
    desc "export all users to a csv file"
    task :all => :environment do
      export_to_csv User.all
    end

    desc "export users whose id are within a range to a csv file"
    task :range => :environment do |task, args|
      export_to_csv User.where("id >= ? and id < ?", ENV['start'], ENV['offset'])
    end

    desc "export last #number users to a csv file"
    task :last => :environment do |task, arg|
      export_to_csv User.last(ENV['number'].to_i)
    end

    def export_to_csv(users)
      CSV.open("./user.csv", "wb") do |csv|
        csv << User.attribute_names
        users.each do |user|
          csv << user.attributes.values
        end
      end
    end
  end
end
于 2014-05-01T08:32:29.537 に答える
2

julia_builderを使用すると、csv エクスポートを非常に簡単に構成できます。

class UserCsv < Julia::Builder
  # specify column's header and value
  column 'Birthday', :dob
  # header equals 'Birthday' and the value will be on `user.dbo`

  # when header and value are the same, no need to duplicate it.
  column :name
  # header equals 'name', value will be `user.name`

  # when you need to do some extra work on the value you can pass a proc.
  column 'Full name', -> { "#{ name.capitalize } #{ last_name.capitalize }" }

  # or you can pass a block
  column 'Type' do |user|
    user.class.name
  end
end

その後

users = User.all
UserCsv.build(users)
于 2015-12-11T23:35:12.767 に答える