RailsでCSVファイルのセルを空白にする方法
はじめに
今回のブログでは、RailsでCSVファイルを生成する際に、連続したデータを空白にする方法について紹介します。
例として、Userモデルのageカラムを使い、前のユーザーと同じ年齢であればそのセルを空白にするコードを実装していきます。
CSVファイルでは、データが連続している場合、同じ情報を繰り返し表示するのは冗長です。
例えば、年齢が同じユーザーが続く場合は、2回目以降の同じ年齢を省略して表示することで、より見やすく、無駄のないファイルを生成できます。
実装の流れ
まずは、UsersControllerにCSV出力用のアクションを作成します。
UserモデルにCSVフォーマットを定義し、CSVファイルを生成して出力します。
# config/routes.rb
Rails.application.routes.draw do
get 'csv_output', to: 'users#csv_output'
end
# app/controllers/users_controller.rb
# Userモデルから全てのユーザーを年齢順に取得し、それをCSV形式で出力
class UsersController < ApplicationController
def csv_output
@users = User.all.order(:age)
send_data(User.csv_format(@users), filename: "ユーザー一覧.csv")
end
end
次に、UserモデルにCSVフォーマットを生成するメソッドを作成します。
作成したコードは下記になります。
# app/models/user.rb
# CSVフォーマットを生成
class User < ApplicationRecord
class << self
def csv_format(users)
CSV.generate do |csv|
csv << ["ID", "性", "名", "年齢", "性別", "給料"]
previous_age = nil
users.each do |user|
csv << format_user_row(user, previous_age)
previous_age = user.age
end
end
end
def format_user_row(user, previous_age)
age = user.age == previous_age ? nil : user.age
[user.id, user.first_name, user.last_name, age, user.sex, user.salary]
end
end
end
上記コードのポイントは下記になります。
まず、csv_formatメソッドは @users で年齢順に取得したUserモデルをusers という引数で受け取り、CSV.generateを使ってCSV形式のデータを作成しています。
また、csv <<を使って、まずヘッダー行(ID、性、名、年齢、性別、給料)を挿入しています。
次に format_user_rowメソッド ですが、こちらのメソッドで各ユーザーごとに行データを作成しています。
previous_ageと現在のuser.ageを比較し、同じ場合には空白(nil)を挿入します。
今回の Rails で CSV ファイルのセルを空白にする方法の一番のポイントは、条件に応じて値をnilにするロジックを組み込むことです。
今回の例では、previous_ageという変数を使って前回のユーザーの年齢を保持し、次のユーザーと同じ年齢であればnilを設定しています。
nilが CSV ファイル上では空白として扱われるため、特定の条件(同じ年齢が続く)でセルを空白にすることができるのです。
出力例
上記のコードを実行すると、例えば以下のようなCSVが出力されます。
(今回 usersテーブルにはハイキュー!のキャラデータを格納し、csvファイルで出力してみました)

上記のように、連続した年齢が空白になることで、無駄な情報の繰り返しが省略され、見やすいCSVファイルになります。
以上が、RailsでCSVファイルのセルを空白にする方法の説明になります。
まとめ
このテクニックを使うことで、CSVファイルの可読性を向上させることができます。
特定の条件でセルを空白にするのは、特に大量のデータを扱う場面で効果的です。
今回の例では年齢を対象にしましたが、他のデータでも同様の方法が応用可能です。
Discussion