[Swift]AWSのSNSとRailsを使って決まった時間にiOSへpush通知



## 前提条件
push通知を行う際には以下の
内容を実行、完了済である必要があります。

### AWS側
 - AWSのアカウントを持っていること
 - AWSのSNSの設定が完了していること


### Swift側
 - AWSのSDKを導入していること
 - AWSのSDKを使ってメソッドが利用出来ていること

### Rails側
 - 既にRailsのアプリケーションをサーバーに配置済であること


まだこのあたりを実行されていない方は以下の記事を参考に。


### 参考サイト
#### [SwiftでAWS SDKを使ってPush通知](http://qiita.com/g08m11/items/7c7df410596cb9a72fd0)

#### [Swiftアプリでも確認済み！RubyスクリプトとAmazon SNSで複数デバイスへのpush通知](http://qiita.com/g08m11/items/463af2665f514b35b9f7)


### バージョン

 - Swiftのバージョン:1.2
 - Rubyのバージョン:2.1.5
 - Railsのバージョン:4.1.7
  
<br>

## 手順

### 1.GemファイルにAWSのgemを追加する

 - gemの管理をしたいため

Gemfile

````gem

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

````

### 参考サイト

#### [AWS SDK for Ruby](http://aws.amazon.com/jp/sdk-for-ruby/)

<br>


### 2.bundle installを実行する


### 3.Gemfile.lockが更新されていることを確認する

 - 開発環境と本番環境で同じgemをインストールし、gemに乖離がない状態にしたいため




### 4.AWSのアカウント情報などをconfigs/push配下にymlに追記する
 - 環境毎にいちいち設定情報を更新する手間を省くため
 - 修正忘れなどを防ぐため


<b>Settings.yml</b>

```yml
production:
  account:
    access_key_id:      'AWSのアカウントのaccess_key_id'
    secret_access_key:  'AWSのアカウントのsecret_access_key'
    region:             'AWSのアカウントのregion'
  sns:
    topic_arn:  '本番環境用のAWS SNSのtopic_arnの値'
    protocol:   'application'
    message:    '配信予定のメッセ−ジ'
    platform_application_arn: '本番環境用のAWS SNSのplatform_application_arnの値'

staging:
  account:
    access_key_id:      'AWSのアカウントのaccess_key_id'
    secret_access_key:  'AWSのアカウントのsecret_access_key'
    region:             'AWSのアカウントのregion'
  sns:
    topic_arn:  'ステージング環境用のAWS SNSのtopic_arnの値'
    protocol:   'application'
    message:    '配信予定のメッセ−ジ'
    platform_application_arn: 'ステージング環境用のAWS SNSのplatform_application_arnの値'

development:
  account:
    access_key_id:      'AWSのアカウントのaccess_key_id'
    secret_access_key:  'AWSのアカウントのsecret_access_key'
    region:             'AWSのアカウントのregion'
  sns:
    topic_arn:  '開発環境用のAWS SNSのtopic_arnの値'
    protocol:   'application'
    message:    '配信予定のメッセ−ジ'
    platform_application_arn: '開発環境用のAWS SNSのplatform_application_arnの値'

```


### 5.pushのモデルを実装する
 - rakeタスクでもこの記述で動くが、pushの振る舞いはpushで行いたいため
 - pushの属性はpushで纏めたいため

<b>push.rb</b>

```ruby
require 'aws-sdk'
class Push

  def notification
    sns = Aws::SNS::Client.new(
      access_key_id:      push_config['account']['access_key_id'],
      secret_access_key:  push_config['account']['secret_access_key'],
      region:             push_config['account']['region'])

    # 対象のSNSからエンドポイントを取得
    num = sns.list_endpoints_by_platform_application(platform_application_arn: push_config['sns']['platform_application_arn'])

    # 作成済みのTopicに取得したエンドポイントをSubscribeする
    num.endpoints.each{|value|
      sns.subscribe(
        topic_arn:  push_config['sns']['topic_arn'],
        protocol:   push_config['sns']['protocol'],
        endpoint:   value.endpoint_arn)
    }

    # 起動していないアプリに対してメッセージをpush通知
    # topic_arnとtarget_arnは同一
    response = sns.publish(
      target_arn:   push_config['sns']['topic_arn'],
      message:      push_config['sns']['message']
    )
  end

  private
  def push_config
    config = YAML.load_file(File.join(Rails.root, 'config/push', 'setting.yml'))
    return config[Rails.env]
  end
end


```




### 6.lib/tasks配下にPush通知用のrakeを実装する(バッチを実装する)

  - cron設定でrakeを実行する設定を行うため 


<b>push.rake</b>


````ruby

require 'aws-sdk'
namespace :push do
  desc 'push notification(message) to Application'
  task notification: :environment do
    begin
      push_logger.info('push start')
      push = Push.new
      push.notification
      push_logger.info('push success')
    rescue Exception => e
      push_logger.error(e.message)
      push_logger.error(e.backtrace.join("\n"))
    end
  end

  def push_logger
    push_logger = Logger.new(Rails.root.join('log', 'push.log'), 5, 10.megabytes)
  end
end

````


### 7.本番環境のサーバのcrontabにpush通知時刻を設定する

 - 定刻でrakeタスクを実行するため


<b>crontab</b>

```
PATH=/usr/local/rbenv/shims:/usr/local/rbenv/bin:/usr/bin:/usr/sbin:/usr/local/bin:/bin

## 毎週月曜日の12時にメッセージを送る
0 12 * * 1 cd /var/www/#{自分のRailsアプリケーション名}/current; RBENV_VERSION=2.1.5 bundle exec rake push:notification RAILS_ENV=production

```