CSVファイルをダウンロード可能にする。

CSVサーバーは、管理部門の担当者がCSVファイルをアップロードすることで、path列に設定した権限のユーザーがweb上で閲覧可能になる。そうすると、閲覧しているユーザーから、すぐにこんな連絡が入りそう。「CSVファイルはダウンロードできないの?」と。
自然な要望ですね。おそらく閲覧しているユーザーは単に見るだけでなく、独自に情報を加工して分析もしたくなる。そんな時、データをCSVファイルとしてダウンロード出来れば、きっと嬉しいはず。
webの画面を見て手入力していたり、コピー&ペーストしていたり、というのはちょっと気の毒だ。そんなことにならないように、以下のようにやってみた。

ダウンロードリンクの追加

  • ajax_scaffoldでCSVファイルの内容を表示するページの1行目に、「CSVファイルとしてダウンロード」というリンクを作成した。
  • ダウンロードリンクをクリックすると、exportアクションが呼び出される。
app/views/displays/component.rhtml
ビュー
<% if @show_wrapper %>
<div class="export">
  <%= link_to 'CSVファイルとしてダウンロード', :action => 'export', :table => params[:table] %>
</div>
...(以下省略)...

ダウンロード処理の実装

  • exportアクションでは、カンマ区切りの文字列を作成して、それをsend_dataで処理することでファイルとしてダウンロード可能になる。
app/controllers/displays_controller.rb
コントローラー
class DisplaysController < ApplicationController
...(途中省略)...
  def export
  Display.with_scope(login_user) do
    csv_text = FasterCSV.generate do |csv|
      csv << Display.column_names
      Display.find(:all).each do |item|
        #csv << item.attributes.values
        #上記では、ハッシュは順序を持たないので問題あり。
        csv << Display.column_names.map {|column| item.send(column)}
      end
    end
    send_data(csv_text, 
              :type => 'text/csv', 
              :filename => "download.csv")
  end
  end
...(途中省略)...
  • Display.with_scope(login_user) doにより、自分が閲覧できる情報だけがダウンロードされる。login_userメソッドは、以下のように定義済み。
  # 閲覧制限をかけるため、with_scopeのオプション設定を返す。
  # 例:ログインユーザーが、営業1部1課を担当している場合、以下のようなハッシュを作成して返す。
  # {:find => {:conditions => path LIKE '%/株式会社RAILS/営業1部/営業1課/%' OR path=''}
  def login_user
    sql = current_paths.inject("path=''") do |result, item|
            %{path LIKE '#{item}%' OR path LIKE "'#{item}%" OR path LIKE '"#{item}%' OR } + result
          end
    if session[:user].admin?
      {}
    else
      {:find => {:conditions => sql}}
    end
  end

解決しない問題

CSVライブラリが利用できない

いつの頃からか、ruby標準添付のCSVライブラリが利用できなくなってしまった。csv_text = CSV.generate do |csv|とやると、uninitialized constant CSVというエラーが...。require 'csv'を宣言しても結果は同じ。なぜだろう...。しかし、FasterCSVを利用しているので問題ないのだが、それにしても気になる。

      • 解決しました!だって、自分でcsv_serverプロジェクトで、Csvモデルを作ってしまっているのですから...。csv_serverプロジェクトではCSVライブラリが利用できないハズです。とんだ大ボケでした...。
ファイル名の文字化け

本当は、ダウンロードした時のファイル名にテーブル名を利用したいのだが、どうも日本語が交じると文字化けしてしまう...。具体的には以下のような文字化け。(config/environment.rbで、$KCODE = 'u' require 'jcode'の設定ありの環境)

_200704_利益管理表_csv → _200704_利益管理表_csv

KconvやIconvを使ってエンコードを変換してみたが、日本語としては表示できなかった。仕方なく、"download.csv"というファイル名に固定した。でもやっぱり日本語ファイル名を使いたい...。解決策はあるのだろうか?


とりあえずは、ダウンロード可能になった。