Rails / 定期的に Amazon S3 のファイルを読み込んで処理するRakeタスク

Amazon S3にファイルが入っていて、
Railsのrakeタスクかなんかで定期的に処理を走らせるみたいな。
そんな事あんまりないかもしれないけど、今回必要だったのでメモ。

  
s3-rake

例えばこんな状況

  • 営業が .csv を Amazon S3 にアップロード
  • 定期的にRakeタスクを実行してDBに取り込む

S3はこんな構成になっているとする。
my_bucketの中身を読み込みたい。

  • other_bucket
  • my_bucket
    • data
      • record-2015-02-09
        • 01.csv
        • 02.csv
      • record-2015-02-10
        • 01.csv
        • 02.csv

他の誰かからS3に安全にアップロードしてもらう方法はこちら。
Developerではない人にはFTPクライアント使ってもらいます。
http://www.workabroad.jp/posts/2131

Gem

aws/aws-sdk-ruby

Gemfile

gem 'aws-sdk', '~> 2'

S3のデータを読み込む

S3KEY / S3SECRET / S3REGION は環境変数に入れておいてください。
「あるBucketの中のフォルダの中のファイルたち」みたいなのは prefix をつかって指定します。

my_bucket/data/record-2015-02-10 なら
prefix: "data/record-2015-02-10" のように。

/lib/tasks/content.rake


require 'aws-sdk'
def get_records(date)

    bucket = "my_bucket"

    records = []

    Aws.config.update(
      access_key_id: ENV['S3KEY'],
      secret_access_key: ENV['S3SECRET'],
      region: ENV['S3REGION']
    )
    s3 = Aws::S3::Client.new

    s3.list_objects(bucket: bucket, prefix: "data/record-#{date}").contents.each do |obj|
        puts obj.key
        # get_object.body returns StringIO object
        # http://docs.ruby-lang.org/ja/2.0.0/class/StringIO.html
        text = s3.get_object(bucket: bucket, key: obj.key).body.read
        records |= text
    end

    # remove nil
    records.compact!
end

AWSの設定

IAM
list_objectsget_object を使うので、
実行できる権限がないと Access Denied と言われてしまう。
IAMで設定しておきましょう。

  
CORS

Qiitaでコメントもらいました。CORS必要ないです。

my_bucket の CORS configurationも設定が必要。
S3 Management Console

AllowedOrigin が * になってますが適切なものに変えてください。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Rakeタスク

これは普通のrakeタスク。
実行時にオプション渡せるようにもしてる。
こんな感じ。

rake content:create["2015-02-09"]

  
何も渡さなければ今日の日付がついたフォルダをS3から探して何かする、と。
HerokuのSchedulerとかで定期的に実行する場合はオプションなしで指定しておけば便利。

/lib/tasks/content.rake


namespace :content do
  desc "Create contents from files in Amazon S3"

  task :create, "date"

  task create: :environment do |task, options|
    if options.date.present?
        date = options.date
    else
        date = Time.current.in_time_zone('Tokyo').strftime('%Y-%m-%d')
    end

    puts date
    records = get_records(date)

    records.each do |record|
      # do something
    end
  end
end

以上です。
自動化するといろいろ楽ですね。

参考

AWS | Tools

Class: Aws::S3::Client — AWS SDK for Ruby V2

Class: AWS.Config — AWS SDK for JavaScript

AWS SDK for Ruby(V2)を利用して、Amazon S3を操作する - Qiita

aws/aws-sdk-ruby

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた