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

- - - - - - - - - - - 
ブログを更新しました。<a href="http://workabroad.jp/posts/2133">元の記事はコチラ</a>
- - - - - - - - - - - 
Amazon S3にファイルが入っていて、
Railsのrakeタスクかなんかで定期的に処理を走らせるみたいな。
そんな事あんまりないかもしれないけど、今回必要だったのでメモ。

<!-- extract -->
　　
![s3-rake](http://image.workabroad.jp/upload/2015/249/workabroad.jpg)

**例えばこんな状況**

- 営業が .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](https://github.com/aws/aws-sdk-ruby)


```rb: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_objects ``` と ```get_object``` を使うので、
実行できる権限がないと ```Access Denied``` と言われてしまう。
[IAMで設定](http://www.workabroad.jp/posts/2131)しておきましょう。

　　
**CORS**
コメント頂きました。CORS必要ないです。

~~my_bucket の CORS configurationも設定が必要。~~
![S3 Management Console](http://image.workabroad.jp/upload/2015/248/workabroad.jpg)

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

```xml
<?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](https://aws.amazon.com/tools/#SDKs)

[Class: Aws::S3::Client — AWS SDK for Ruby V2](http://docs.aws.amazon.com/sdkforruby/api/frames.html)

[Class: AWS.Config — AWS SDK for JavaScript](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#constructor-property)

[AWS SDK for Ruby(V2)を利用して、Amazon S3を操作する - Qiita](http://qiita.com/itayan/items/112f23cbff13e49cdb53)

[aws/aws-sdk-ruby](https://github.com/aws/aws-sdk-ruby)



 → <a href="http://workabroad.jp/posts/2133">http://workabroad.jp/posts/2133</a>