なべしす

独立系SI企業から完全異業種のベンチャー企業に転職、社内のITインフラを整えるべく颯爽と登場した自称天才プログラマー俺のハートフルブログ

heroku 初心者がRailsアプリケーションの公開で躓く原因はDBにあった

はじめに

「herokuは簡単にアプリケーションを公開できる!」
と聞いていたんですが少しハマったので共有します。
簡易的なものですが...

※最低限の設定しかしていません

基本的には2ステップで公開できる?

以下の2ステップです。

$ heroku create
$ git push heroku master

まあしかしそんな甘くはなかったです。
ローカルで普通に動くからってこの2ステップだけで動くわけない...
当たり前なんだよなあ...

ソースの変更点

# config/application.rb
config.assets.initialize_on_precompile = false
# Gemfile
gem 'pg'
# database.yml
adapter: postgresql
encoding: unicode
url: <%= ENV['DATABASE_URL'] %>

herokuではpostgresを使う必要があります

SQLを起動するのを忘れない

$ heroku addons:add heroku-postgresql

まとめ

つまり、ソースを3箇所変更して以下の4ステップで完了します。

$ heroku create
$ git push heroku master
$ heroku addons:add heroku-postgresql
$ heroku run rake db:migrate

Rails MWS 商品情報の取得

はじめに

MWSで商品情報を取得できるオペレーションには以下のようなものがあります。

この3つはレスポンスは同じですが、以下のような違いがあります。

オペレーション 役割 最大リクエストクォータ 回復レート 時間あたりのリクエストクォータ
ListMatchingProducts 検索クエリに応じた、商品およびその属性のリストを返します。 20リクエス 5秒あたり1回のリクエス 1時間あたり720リクエス
GetMatchingProduct ASINのリストに応じた、商品およびその属性のリストを返します。 20リクエス 1秒あたり20商品 1時間あたり7200リクエス
GetMatchingProductForId ASIN、GCID、SellerSKU、UPC、EAN、ISBN、およびJANのリストに応じた、商品およびその属性のリストを返します。 20リクエス 1秒あたり5商品 1時間あたり18000リクエス

汎用性が高いものほどリクエストの制限が厳しくなっているイメージですね。

今回はGetMatchingProductForIdを使用して商品情報を取得します。

実装

事前準備

oredeki.hatenablog.com

こちらよりpeddlerのclientインスタンスを作成できる状態にして置いてください。

リクエストの送信

peddlerのclientインスタンスを使用すればリクエストを送信することはとても簡単です。

リファレンスではこう書いてあります。リファレンス
get_matching_product_for_id(id_type, *ids, opts = { marketplace_id: primary_marketplace_id })

id_typeで選択できるのは、SellerSKU、UPC、EAN、ISBN、JANの何か、
そしてidsid_typeで選択したコードを最大で5つ設定できます。

なので、これだけでリクエストを送ることができますね。

client = MWS.products( 
  # 省略
)

id_type = 'EAN'
ids = ['4545784064849', '4571368442307']

client.get_matching_product_for_id(id_type, ids)

レスポンスは以下の通りです。

<?xml version="1.0"?>
<GetMatchingProductForIdResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductForIdResult Id="4545784064849" IdType="EAN" status="Success">
  <Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
    <Product>
      <Identifiers>
        <MarketplaceASIN>
          <MarketplaceId>A1VC38T7YXB528</MarketplaceId>
          <ASIN>B06XKNN3L2</ASIN>
        </MarketplaceASIN>
      </Identifiers>
      <AttributeSets>
        <ns2:ItemAttributes xml:lang="ja-JP">
          <ns2:Binding>おもちゃ&ホビー</ns2:Binding>
          <ns2:Brand>マックスファクトリー</ns2:Brand>
          <ns2:ItemDimensions>
            <ns2:Height Units="inches">10.24</ns2:Height>
            <ns2:Length Units="inches">5.51</ns2:Length>
            <ns2:Width Units="inches">3.94</ns2:Width>
          </ns2:ItemDimensions>
          <ns2:IsAdultProduct>false</ns2:IsAdultProduct>
          <ns2:Label>Max Factory</ns2:Label>
          <ns2:Languages>
            <ns2:Language>
              <ns2:Name>japanese</ns2:Name>
              <ns2:Type>Unknown</ns2:Type>
            </ns2:Language>
          </ns2:Languages>
          <ns2:ListPrice>
            <ns2:Amount>5800.00</ns2:Amount>
            <ns2:CurrencyCode>JPY</ns2:CurrencyCode>
          </ns2:ListPrice>
          <ns2:Manufacturer>Max Factory</ns2:Manufacturer>
          <ns2:Model>M06484</ns2:Model>
          <ns2:PackageDimensions>
            <ns2:Height Units="inches">3.07</ns2:Height>
            <ns2:Length Units="inches">8.90</ns2:Length>
            <ns2:Width Units="inches">6.06</ns2:Width>
            <ns2:Weight Units="pounds">0.55</ns2:Weight>
          </ns2:PackageDimensions>
          <ns2:PackageQuantity>1</ns2:PackageQuantity>
          <ns2:PartNumber>M06484</ns2:PartNumber>
          <ns2:ProductGroup>Hobby</ns2:ProductGroup>
          <ns2:ProductTypeName>TOYS_AND_GAMES</ns2:ProductTypeName>
          <ns2:Publisher>Max Factory</ns2:Publisher>
          <ns2:ReleaseDate>2017-10-31</ns2:ReleaseDate>
          <ns2:SmallImage>
            <ns2:URL>http://ecx.images-amazon.com/images/I/51geCQ766OL._SL75_.jpg</ns2:URL>
            <ns2:Height Units="pixels">75</ns2:Height>
            <ns2:Width Units="pixels">54</ns2:Width>
          </ns2:SmallImage>
          <ns2:Studio>Max Factory</ns2:Studio>
          <ns2:Title>figma キルラキル 纏流子 ノンスケール ABS&PVC製 塗装済み可動フィギュア 再販</ns2:Title>
        </ns2:ItemAttributes>
      </AttributeSets>
      <Relationships/>
      <SalesRankings>
        <SalesRank>
          <ProductCategoryId>hobby_display_on_website</ProductCategoryId>
          <Rank>18480</Rank>
        </SalesRank>
        <SalesRank>
          <ProductCategoryId>2189356051</ProductCategoryId>
          <Rank>2366</Rank>
        </SalesRank>
      </SalesRankings>
    </Product>
  </Products>
</GetMatchingProductForIdResult>
<GetMatchingProductForIdResult Id="4571368442307" IdType="EAN" status="Success">
  <Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
    <Product>
      <Identifiers>
        <MarketplaceASIN>
          <MarketplaceId>A1VC38T7YXB528</MarketplaceId>
          <ASIN>B00P0BQUYY</ASIN>
        </MarketplaceASIN>
      </Identifiers>
      <AttributeSets>
        <ns2:ItemAttributes xml:lang="ja-JP">
          <ns2:Binding>おもちゃ&ホビー</ns2:Binding>
          <ns2:Brand>グッドスマイルカンパニー</ns2:Brand>
          <ns2:ItemDimensions>
            <ns2:Height Units="inches">3.00</ns2:Height>
            <ns2:Length Units="inches">8.00</ns2:Length>
            <ns2:Width Units="inches">4.00</ns2:Width>
            <ns2:Weight Units="pounds">1.28</ns2:Weight>
          </ns2:ItemDimensions>
          <ns2:IsAdultProduct>false</ns2:IsAdultProduct>
          <ns2:Label>グッドスマイルカンパニー</ns2:Label>
          <ns2:ListPrice>
            <ns2:Amount>10800.00</ns2:Amount>
            <ns2:CurrencyCode>JPY</ns2:CurrencyCode>
          </ns2:ListPrice>
          <ns2:Manufacturer>グッドスマイルカンパニー</ns2:Manufacturer>
          <ns2:ManufacturerMaximumAge Units="months">180.00</ns2:ManufacturerMaximumAge>
          <ns2:ManufacturerMinimumAge Units="months">168.00</ns2:ManufacturerMinimumAge>
          <ns2:Model>SEP148310</ns2:Model>
          <ns2:PackageDimensions>
            <ns2:Height Units="inches">6.54</ns2:Height>
            <ns2:Length Units="inches">10.79</ns2:Length>
            <ns2:Width Units="inches">7.87</ns2:Width>
            <ns2:Weight Units="pounds">1.28</ns2:Weight>
          </ns2:PackageDimensions>
          <ns2:PackageQuantity>1</ns2:PackageQuantity>
          <ns2:PartNumber>SEP148310</ns2:PartNumber>
          <ns2:ProductGroup>Hobby</ns2:ProductGroup>
          <ns2:ProductTypeName>TOYS_AND_GAMES</ns2:ProductTypeName>
          <ns2:Publisher>グッドスマイルカンパニー</ns2:Publisher>
          <ns2:ReleaseDate>2015-08-08</ns2:ReleaseDate>
          <ns2:Size>全高:約210mm</ns2:Size>
          <ns2:SmallImage>
            <ns2:URL>http://ecx.images-amazon.com/images/I/51H1EV5qzYL._SL75_.jpg</ns2:URL>
            <ns2:Height Units="pixels">75</ns2:Height>
            <ns2:Width Units="pixels">56</ns2:Width>
          </ns2:SmallImage>
          <ns2:Studio>グッドスマイルカンパニー</ns2:Studio>
          <ns2:Title>キルラキル 鬼龍院皐月 鮮血Ver. 1/8スケール ABS&ATBC-PVC製 塗装済み完成品フィギュア</ns2:Title>
        </ns2:ItemAttributes>
      </AttributeSets>
      <Relationships/>
      <SalesRankings>
        <SalesRank>
          <ProductCategoryId>hobby_display_on_website</ProductCategoryId>
          <Rank>77338</Rank>
        </SalesRank>
        <SalesRank>
          <ProductCategoryId>2189356051</ProductCategoryId>
          <Rank>10433</Rank>
        </SalesRank>
      </SalesRankings>
    </Product>
    <Product>
      <Identifiers>
        <MarketplaceASIN>
          <MarketplaceId>A1VC38T7YXB528</MarketplaceId>
          <ASIN>B0188100YI</ASIN>
        </MarketplaceASIN>
      </Identifiers>
      <AttributeSets>
        <ns2:ItemAttributes xml:lang="ja-JP">
          <ns2:Brand>グッドスマイルカンパニー</ns2:Brand>
          <ns2:IsAdultProduct>false</ns2:IsAdultProduct>
          <ns2:Label>Good Smile</ns2:Label>
          <ns2:Manufacturer>Good Smile</ns2:Manufacturer>
          <ns2:ProductGroup>Hobby</ns2:ProductGroup>
          <ns2:ProductTypeName>HOBBIES</ns2:ProductTypeName>
          <ns2:Publisher>Good Smile</ns2:Publisher>
          <ns2:SmallImage>
            <ns2:URL>http://ecx.images-amazon.com/images/I/51NjcNgP%2B3L._SL75_.jpg</ns2:URL>
            <ns2:Height Units="pixels">75</ns2:Height>
            <ns2:Width Units="pixels">56</ns2:Width>
          </ns2:SmallImage>
          <ns2:Studio>Good Smile</ns2:Studio>
          <ns2:Title>Good Smile Kill La Kill: Satsuki Kiryuin (Senketsu Version) PVC Figure [並行輸入品]</ns2:Title>
        </ns2:ItemAttributes>
      </AttributeSets>
      <Relationships/>
      <SalesRankings/>
    </Product>
  </Products>
</GetMatchingProductForIdResult>
<ResponseMetadata>
  <RequestId>0932d9f9-f34d-4307-8a59-79d3c3804825</RequestId>
</ResponseMetadata>
</GetMatchingProductForIdResponse>

レスポンスの解析

レスポンスを掘って掘って解析していきます。
今回の例は単純に商品のタイトルを配列に格納するというロジックです。

# 先ほどの続き
responce = client.get_matching_product_for_id(id_type, ids).xml
titles = []
results = response.dig('GetMatchingProductForIdResponse', 'GetMatchingProductForIdResult')
# [注意] 1商品だけ取得した場合eachで回す必要はないです。
results.each do |result|
  titles << result.dig('Products', 'Product', 'AttributeSets', 'ItemAttributes', 'Title')
end

結構上層部のタイトルでさえこれくらいは掘らないと取得できません。
共通化できる部分はうまく共通化して商品情報を取得するようにしましょう。

あとは煮るなり焼くなり...

注意点

  • 商品のサイズ系の単位はインチ
  • 商品の重さ系の単位はポンド

Rails MWS APIを利用するまでの事前準備

MWSとは

AmazonマーケットプレイスWebサービスの略です。
自分が販売をしているAmazon各プラットフォーム対して以下のようなことができます。

  • レポートの取得
  • 出品や商品情報の更新削除などができるフィードのサブミット
  • 商品情報の取得
  • などなど

詳しくは公式リファレンスを読みましょう。
結構色々なことができます

MWSを利用するのに必要な情報

開発者ではない場合(複数セラーを扱わない場合)

MWSを利用するには以下の3つのキーが必要です。

  • Seller ID(出品者ID)
  • AWS Access Key ID(AWSアクセスキーID)
  • Secret Key(秘密キー)

取得方法は以下の記事を参照にしてください。
amazonのMWSアカウント情報はセラーセントラルから確認できるんですけど

開発者の場合(複数セラーを扱う場合)

弊社のWebアプリケーションlismoaの様に複数のセラーの情報を扱う場合には上記の3つの他に

が必要になります。

アプリ開発者のDeveloper ID(開発者ID)とセラーのアカウントを紐付けてAuthTokenを取得します。
公式リファレンスに紐付ける方法は記載されていますが、正直分かり辛いと思います。
百聞は一見にしかずです
黙って一回自分自身を紐付けて見ましょう。
https://sellercentral.amazon.co.jp/gp/mws/registration/register.html

Railsで簡単にMWSを使えるgem「peddler」を導入する

MWSを生で扱うのはPOSTリクエストを魔改造する必要があり、かなりハードルが高いです
peddlerというgemを使いましょう。便利ですので
https://github.com/hakanensari/peddler
導入方法はREADMEにある通りいつもの感じです。

APIリファレンスはこちら
http://www.rubydoc.info/gems/peddler/toplevel

client作成のサンプル

peddlerではAPI Sectionごとにclientというオブジェクトを作成してsection以下の機能を利用するという流れになります。
API Sectionというのはこのレイヤーですね。

f:id:oredeki:20171108115821p:plain:w300 f:id:oredeki:20171108115816p:plain

今回は「商品(Products)」のclientを作成するサンプルです。
先ほど取得した複数のキー使用します。

@client = MWS.products(
  primary_marketplace_id: 'marketplace_id',
  aws_access_key_id: 'aws_access_key_id',
  aws_secret_access_key: 'aws_secret_access_key',
  merchant_id: 'seller_id',
  auth_token: 'auth_token' # 開発者ではない場合は不要
)

準備完了

これでMWSの多彩な機能を使う準備は完了です!
今後はその多彩な機能の紹介や注意点などを記事にしていこうと考えていますのでお楽しみに!

Pairsで「初回デート費用は男性が全て払う」を選択している人に直接聞いてみた

どんなマインドでそんなの選択してるんだ?

先月ふと思ったんですよ。。。

もしかして何かの隠語なのか?
業界的に暗黙の了解みたいなものがあるのか?

おそらく何もないでしょう。
ただただそういう考えの女性なんでしょうね!
でもモヤモヤするのでいつか聞ける機会があれば聞いてみたいなーと思っていました。

時は満ちた

先日ついにマッチングしたんですよ!
Pairsで「初回デート費用は男性が全て払う」を選択している女性と。
(ぼくは足跡ついた人全てに「いいね」してるので好みな人じゃなくてもマッチングします。)
f:id:oredeki:20171028181108p:plain:w300
※プライバシーのため色々白塗りしています。

早く聞きたい早く聞きたい

適度に挨拶を済ませていざ!
f:id:oredeki:20171028181758p:plain:w300
丁寧かつフランクかつ失礼のないように!!

返ってきた!

期待はずれの答えが返ってきましたね...
f:id:oredeki:20171028182200p:plain:w300


...ん?

f:id:oredeki:20171028181839p:plain


うそやん...

突っ込め突っ込め

f:id:oredeki:20171028182740p:plain:w300

返ってこなくなったんごー(^q^)

絶対なんかあるやろ。
「初回デートで奢らない懐の狭い男はないです」
とか
「男はATMだと思ってます」
とか
「私にはおごって当然でしょ?」
とかあるでしょ黒いところが!!

まとめ

人間は都合が悪いことはごまかす

今後

進展があったらまた記事書きますねw

GoogleAppsScript JavaScriptを用いてCSVをローカルに書き出す実装

概要

おおよそソースを見たらわかるようにしているので説明はふわっとです。

GAS側のメソッドと機能

メソッド 機能
onOpen() メニューバーのその他に「CSVで出力」を追加
csvDownload() CSVで出力」をクリックされるとCSVをダウンロード
getData() GASからJSにシートのデータを渡す
getFileName() 出力名を取得(アクティブシート名+現在日時)

JS側のポイント

  • window.onloadで読み込み時にファンクションを実行
  • GAS側からダウンロードデータを作りダウンロードリンクを作成
  • 擬似的にlinkオブジェクトを作成してクリックさせる
  • google.script.host.close();でダウアログを閉じる

実装

// メニューバーにカスタムメニューを追加
function onOpen() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "CSVで出力",
    functionName : "csvDownload"
  }];
  spreadsheet.addMenu("その他", entries);
};

// JSを用いてCSVファイルをダウンロードする
function csvDownload() {
  // dialog.html をもとにHTMLファイルを生成
  // evaluate() は dialog.html 内の GAS を実行するため( <?= => の箇所)
  var html = HtmlService.createTemplateFromFile("dialog").evaluate();
  // 上記HTMLファイルをダイアログ出力
  SpreadsheetApp.getUi().showModalDialog(html, "ダウンロードなう");
}

// JS側で使用
function getData() {
  // スプレッドシート上の値を二次元配列の形で取得
  var sheet = SpreadsheetApp.getActiveSheet();
  var values = sheet.getDataRange().getValues();

  // 二次元配列をCSV形式のテキストデータに変換
  var dataArray = [];
  for (var i = 0; i < values.length; i++) {
    dataArray.push(values[i].join(","));
  }
  return dataArray.join("\r\n");  // 改行コードは windows を想定
}

// JS側で使用
// ファイル名の設定はここで!!
function getFileName() {
  var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadSheet.getActiveSheet();
  var now = new Date();
  var datetime = Utilities.formatDate( now, 'Asia/Tokyo', 'yyyyMMddHHmm');
  // アクティブシート名+現在日時
  return sheet.getName() + '_' + datetime + '.csv';
}
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script type='text/javascript'>    
      window.onload = function(){
        handleDownload();
      }
      function handleDownload() {
        // 出力データを GAS から取得する
        var content = <?= getData(); ?>;
        var blob = new Blob([ content ], { "type" : "text/csv"});
        var link = document.createElement('a');
        // ファイル名を GAS から取得する
        link.download = <?= getFileName(); ?>;
        link.href = window.URL.createObjectURL(blob);
        link.click();
        // ダイアログを閉じる
        google.script.host.close();
      }
  </script>
  </head>
</html>

所感

  • ダイアログが一瞬開いてしまうのは仕方がない
  • VBAの80倍なじみやすい

参考

GASで文字コード指定してファイルを書き出す
https://qiita.com/jsoizo/items/948e23231417d203eefa
ローカルにファイルダウンロード
http://googleappsscript.hatenablog.com/entry/2017/09/06/120000

Rails rubyzipでディレクトリを圧縮してダウンロードする

やりたいこと

こんな感じのディレクトリを含むデータを
スクリーンショット 2017-10-06 18.12.50.png
圧縮したい!!
スクリーンショット 2017-10-06 18.13.11.png

使用するgem

rubyzip
導入はREADMEを読みましょう。

ziprubyってのもあるから間違えないように。

rubyzipの基本的な使い方

READMEに書いてある基本的なzip作成方法は以下の通り
Basic zip archive creation

require 'rubygems'
require 'zip'

folder = "Users/me/Desktop/stuff_to_zip"
input_filenames = ['image.jpg', 'description.txt', 'stats.csv']

zipfile_name = "/Users/me/Desktop/archive.zip"

Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
  input_filenames.each do |filename|
    # Two arguments:
    # - The name of the file as it will appear in the archive
    # - The original file, including the path to find it
    zipfile.add(filename, File.join(folder, filename))
  end
  zipfile.get_output_stream("myFile") { |os| os.write "myFile contains just this" }
end

手始めにサンプルを少しいじってローカルにある画像ファイル数個を圧縮してみました。
簡単にできました。
その時こう思ったのです。
「あ、これは勝ちましたね。」と...

そして英語だからってまともにREADMEを読まずに、zipfile.addディレクトリ渡せばできるんじゃ?
という軽い気持ちで多方面からaddを試してみたんですが、ことごとく敗北。
負けました。

実装

readmeの少し下を見てみましょう。
Zipping a directory recursively....ん?流れ変わったな?
再帰的にディレクトリを圧縮する」by Google翻訳
以下ソース

require 'zip'

# This is a simple example which uses rubyzip to
# recursively generate a zip file from the contents of
# a specified directory. The directory itself is not
# included in the archive, rather just its contents.
#
# Usage:
#   directory_to_zip = "/tmp/input"
#   output_file = "/tmp/out.zip"
#   zf = ZipFileGenerator.new(directory_to_zip, output_file)
#   zf.write()
class ZipFileGenerator
  # Initialize with the directory to zip and the location of the output archive.
  def initialize(input_dir, output_file)
    @input_dir = input_dir
    @output_file = output_file
  end

  # Zip the input directory.
  def write
    entries = Dir.entries(@input_dir) - %w(. ..)

    ::Zip::File.open(@output_file, ::Zip::File::CREATE) do |io|
      write_entries entries, '', io
    end
  end

  private

  # A helper method to make the recursion work.
  def write_entries(entries, path, io)
    entries.each do |e|
      zip_file_path = path == '' ? e : File.join(path, e)
      disk_file_path = File.join(@input_dir, zip_file_path)
      puts "Deflating #{disk_file_path}"

      if File.directory? disk_file_path
        recursively_deflate_directory(disk_file_path, io, zip_file_path)
      else
        put_into_archive(disk_file_path, io, zip_file_path)
      end
    end
  end

  def recursively_deflate_directory(disk_file_path, io, zip_file_path)
    io.mkdir zip_file_path
    subdir = Dir.entries(disk_file_path) - %w(. ..)
    write_entries subdir, zip_file_path, io
  end

  def put_into_archive(disk_file_path, io, zip_file_path)
    io.get_output_stream(zip_file_path) do |f|
      f.write(File.open(disk_file_path, 'rb').read)
    end
  end
end

「Copy from here」と書いていますし言われるがままにこのクラスをプロジェクトに配置します。
すると、素晴らしい。
インスタンスを作成してwriteメソッドを呼び出すだけで指定したフォルダがzipになるのです。

zip_file_generator = ZipFileGenerator.new(input_dir, output_file)
zip_file_generator.write
# ディレクトリのzipができる

後はコントローラーでsend_fileを使ってダウンロードさせるだけです。

send_file output_file

所感

  • READMEはヨンダホウガイイデスヨ
  • なんでgemのライブラリに含んでくれないんですかねえ
  • rubyzipの使い方は結構ググっても出てこない

Rails Stripe サブスクリプション決済実装 プランの登録

概要

Stripeでのサブスクリプション決済実装をRailsで行う場合、
公式で提供されているgemを使用することになると思います。

前回はAPIを使うまでの事前準備を記事にしました。

oredeki.hatenablog.com

今回はサブスクリプションプランをStripeに登録する方法を紹介します。

管理ページからプラン追加

Stripe管理ページでSubscriptions > Plansよりプランの一覧が閲覧できます。
管理ページからプランを追加する場合はこの画面のNewより追加できます。 スクリーンショット 2017-09-30 12.49.35.png こんな感じです。 スクリーンショット 2017-09-30 12.52.17.png

トライアル期間が365日あるが、その後は1日毎に100万円かかる悪魔的プランです。

Railsからプラン追加

アプリケーション側から先ほどのような悪魔的なプランを登録してみます。
プランを追加するにはモジュールはStripe::Planクラスのcreateメソッドを使用します。
前回Stripeモジュールを使用できる設定は完了させているので、単純にメソッドに適切な引数を設定するだけでプランは作成されます。
公式リファレンス:Create a plan

実装

  def create_plan
    Stripe::Plan.create(
      id:                   'test_plan',
      name:                 'Test Plan',
      amount:               1000000,
      currency:             'jpy',
      interval:             'day',
      interval_count:       1,
      trial_period_days:    365,
      statement_descriptor: 'sswatanabe'
      metadata: {
        are_you_from_chicago: "No i'm from NewYork"
      }
    )
  end

各パラメータの意味は名前の通りです。
英語に馴染みのない僕にはstatement_descriptorがなんのことか分からなかったのですが、
リファレンスを読んだところ、「クレジットの明細に表示される名前」らしいです。
metadataでは、好きな情報を持たせることができます。
アプリケーション側のPlan IDを登録する時などに活用できます。

確認

API側からも確認できますが、
手っ取り早くStripe管理ページでみてみましょう。
無事追加されています。 スクリーンショット 2017-09-30 13.38.56.png 詳細も正常ですね。 スクリーンショット 2017-09-30 13.39.07.png

所感

........アプリケーション側からプラン追加するってなかなか壮大なシステムでしか使わないよな。

参考