わたろぐ

仕事、読書、ガジェット、グルメ、写真、旅行など雑多な備忘

Ruby on Railsを触ってみる ②CSVの取り込み

前回の続きで、ツイートCSVファイルの読み込み機能を実装してみる。 ActiveRecordを使って、DBにツイートを取り込む。

まずはRoutes.rbの修正。例に習いgit diffで編集箇所を見てみる。 初めて使ったけど、これは便利だな。

$ git diff config/routes.rb 
diff --git a/config/routes.rb b/config/routes.rb
index cf7d04d..379330e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,10 @@
 Twice::Application.routes.draw do
-  resources :tweets
+  resources :tweets do
+    collection do
+      get 'import_csv_new'
+      post 'import_csv'
+    end
+  end

import_csv_newとimport_csvというメッソドへのルーティングが追加される。

$ rake routes
               Prefix Verb   URI Pattern                      Controller#Action
import_csv_new_tweets GET    /tweets/import_csv_new(.:format) tweets#import_csv_new
    import_csv_tweets POST   /tweets/import_csv(.:format)     tweets#import_csv
               tweets GET    /tweets(.:format)                tweets#index
                      POST   /tweets(.:format)                tweets#create
            new_tweet GET    /tweets/new(.:format)            tweets#new
           edit_tweet GET    /tweets/:id/edit(.:format)       tweets#edit
                tweet GET    /tweets/:id(.:format)            tweets#show
                      PATCH  /tweets/:id(.:format)            tweets#update
                      PUT    /tweets/:id(.:format)            tweets#update
                      DELETE /tweets/:id(.:format)            tweets#destroy

tweets_controller.rbにアクションを追記する。

  # GET /tweets/import_csv_new
  def import_csv_new
  end  

  # POST /tweets/import_csv
  def import_csv
    respond_to do |format|
      if Tweet.import_csv(params[:csv_file])
        format.html { redirect_to tweets_path }
        format.json { head :no_content }
      else
        format.html { redirect_to tweets_path, :notice => "CSVファイルの読み込みに失敗しました。" }
        format.json { head :no_content }
      end
    end
  end  

import_csv_newは取り込み用のフォームを設置する。 import_csvで受け取ったCSVを取り込む処理を行い、処理が終わるとツイート一覧のページに遷移させる。 Views/tweets/配下に、import_csv_newに対応するViewファイルを作成する。

<h1>Import tweets CSV File</h1>
<%= form_tag('import_csv', :method => 'post', :multipart => true, :class => 'navbar-form pull-left') do %>
    <%= file_field_tag(:csv_file) %>
    <%= submit_tag("CSV Import",:class => 'btn') %>
<% end %>

import_csvをTweetモデルに作成する。

/* Models/tweet.rb */
# coding: utf-8
require 'csv'   # csv操作を可能にするライブラリ
require 'kconv' # 文字コード操作をおこなうライブラリ

class Tweet < ActiveRecord::Base
  
  def self.import_csv(csv_file)
    # csvファイルを受け取って文字列にする
    csv_text = csv_file.read

    # 読み込む前に古いツイートをすべて削除する。
    Tweet.delete_all

    #文字列をUTF-8に変換
    CSV.parse(Kconv.toutf8(csv_text)) do |row|

      # ヘッダー行を回避するためにtweet_idが数値でない場合は読み飛ばす
      if row[0] =~ /\d+/
        tweet = Tweet.new

        tweet.tweet_id              = row[0]
        tweet.in_reply_to_status_id = row[1]
        tweet.in_reply_to_user_id   = row[2]
        tweet.timestamp             = row[3]
        tweet.source                = row[4]
        tweet.text                  = row[5]
        tweet.retweeted_status_id   = row[6]
        tweet.retweeted_status_user_id    = row[7]
        tweet.retweeted_status_timestamp  = row[8]
        tweet.expanded_urls         = row[9]

        tweet.save

      end

    end
    return true
  end

end

こんな画面になる。イマイチBootstrapが活用できていないような...

ひとまずアップロードしてみる。 お、遅い。。。 とりあえずこんなかんじで一覧が表示される。

Bootstrapのclassを適用してみる。どうやらこの1万件の全ツイートを表示するのに時間がかかるみたい。

とりあえずここまででコミット。 Add CSV import twata701/twice GitHub

参考: Rails4 csvファイルをアップロードして読み込む ayaketanのプログラミング勉強日記