CSVに変換したいActiveRecordモデルの配列を取得しました。 FasterCSVのようなgemを調べてみましたが、ActiveRecordモデルではなく、文字列と配列で動作するようです。
要するに、私は変換したい:
user1 = User.first
user2 = User.last
a = [user1, user2]
TO:
id,username,bio,email
1,user1,user 1 bio,user1 email
1,user2,user 2 bio,user2 email
簡単なRailsこれを行う方法はありますか?
以下は、すべてのユーザーの属性をファイルに書き込みます。
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
@ 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
これは元の質問から外れているかもしれませんが、問題を解決します。 Active Recordモデルのすべてまたは一部をcsvに変換できるようにする場合は、ActiveRecordに関する懸念事項を使用できます。以下に例を示します
_module Csvable
extend ActiveSupport::Concern
class_methods do
def to_csv(*attributes)
CSV.generate(headers: true) do |csv|
csv << attributes
all.each do |record|
csv << attributes.map { |attr| record.send(attr) }
end
end
end
end
end
_
指定された属性はCSVのヘッダーとして使用され、この属性は含まれるクラスのメソッド名に対応することが期待されます。次に、任意のActiveRecordクラス、この場合はUserクラスにそれを含めることができます
_class User
include Csvable
end
_
使用法
User.where(id: [1, 2, 4]).to_csv(:id, :name, :age)
注:これはActiveRecord関係でのみ機能し、配列では機能しません
本番ではなく、技術に詳しくないユーザーのためにデータを取得するだけでなく、迅速で汚れたものが必要な場合は、これをコンソールに貼り付けることができます。
_require 'csv'
class ActiveRecord::Relation
def to_csv
::CSV.generate do |csv|
csv << self.model.attribute_names
self.each do |record|
csv << record.attributes.values
end
end
end
end
_
それから:User.select(:id,:name).all.to_csv
本番環境に行く場合は、おそらくこれをActiveRecord :: Relationのデコレーターに変換し、より正確にフィールド/属性の順序を確認します。
さらに別の同様の答えですが、ここに私が通常行うことを示します。
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.find_each do |model|
csv << model.attributes.values_at(*column_names)
end
end
end
end
既存のモジュールをハッキングする代わりに、通常、このコードをすべてのモデルの基本クラスであるApplicationRecord
クラスに配置します(通常)。
さらに詳しく説明する必要がある場合は、to_csv
メソッドに名前付きパラメーターを追加し、このクラスでこれらの機能を可能な限り処理します。
このようにして、to_csv
メソッドはモデルとそのリレーションの両方で利用可能になります。例えば。
User.where(role: :customer).to_csv
# => gets the csv string of user whose role is :customer
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)
これには、SQLエンジンも利用できます。例えば。 sqlite3の場合:
cat << EOF > lib/tasks/export-submissions.sql
.mode csv
.separator ',' "\n"
.header on
.once "submissions.csv"
select
*
from submissions
;
EOF
sqlite3 -init lib/tasks/export-submissions.sql db/development.sqlite3 .exit
CentOS 7を使用している場合-2013年にリリースされたsqliteに同梱されています。そのバージョンはseparator
とonce
をまだ知りませんでした。そのため、Webサイトから最新のバイナリをダウンロードする必要がある場合があります。 https://sqlite.org/download.html それをローカルにインストールし、ローカルインストールへのフルパスを使用します。
~/.local/bin/sqlite3 -init lib/tasks/export-submissions.sql db/development.sqlite3 .exit