35
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails上で、CSVファイルを読み込んでみた

Posted at

やりたいこと

CSVなどのスプレッドシートから一気に読み込みたい。
(新規にシステムを作ったりするときにありがち)

前提

  • Rails 4.2.5(4.x系) SQLiteを使用
  • すでに登録対象のモデルが存在する。

登録対象のモデルに関しては、

objectという名前で

  • name:string
  • status:integer
  • content:text

を持つと仮定する。

実装

ここを参照にした。ほぼこれに近いけど少し違うって感じ

  • ビューに、ファイルを指定してアップロードする処理を呼び出す機能を実装
  • コントローラに、ファイルの受け取りとリダイレクト処理を実装
  • モデルに、内容に基づいた保存処理を実装
  • ルーティングの設定

ビューの実装

アップロード箇所を実装したい表示させたいビューに、こんな感じの実装を行います。

実装箇所
<%= form_tag({controller: "objects", action: "import", method: "post"}, {multipart: true}) do %>
  <%= file_field_tag :file %>
  <%= submit_tag "オブジェクトを一括インポート" %>
<% end %>

コントローラの実装

コントローラは元々ビューやモデルに対する処理を呼び出したりする部分なので、ここではモデルに実装するDBアクセス処理の呼び出しと、リダイレクト処理を実装する。

さっきのビューでは、objectsのコントローラ、にimportという操作をpostメソッドでアクセスする。という意味合いになる。

app/controllers/objects_controller.rb
  def import
    Object.import(params[:file])
    redirect_to "/object"
  end

ここでは、読み込みファイルを引数として、モデルに実装したimportメソッドを呼び出し処理を行った上で、 /object の一覧ページにリダイレクトするという意味合いになる。

モデルの実装

モデルでは、対象のファイルを読み込み1件1件バリデーションして登録する処理を実施している。

関係ある箇所だけ抜粋。

例によってパラメータの精査も忘れず実施。

app/models/object.rb
  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|

      obj = new
      obj.attributes = row.to_hash.slice(*updatable_attributes)

      obj.save!
    end
  end

  def self.updatable_attributes
    ["name","status","content"]
  end

ルーティングの修正

関係のあるところだけ抜粋

routes.rb
  #objects に限り、post で import 処理を許可する
  resources 'objects', only: :index do
    collection { post :import }
  end
35
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?