そうだ、教祖になろう。出エジプト記 第3章4節 Lambdaでサーバサイドを実装する
山の神 海の神 今年も本当にありがとう
前回の第3章3節 Lambdaでサーバサイドを実装できないでUnicodeエンコーディングという後顧の憂いを断ちましたので、いよいよプログラミング祭の始まりです。
まずは、ざっくりクラス図を描きました。
読む人と返すために整える人。
あとでもうちょっと複雑化する気もしますが、今はこれでいいでしょう。
白い褌ひきしめた 裸若衆に雪が舞う
まずはGoogleスプレッドシートからランダムで1行取得するクラスです。
空でない行数をカウントして、ヘッダ行数を除いて2行目〜最大行目のうち、1レコードを辞書オブジェクトで返します。
取ったままの配列でもいいんですが、一応。
import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '.')) import random import gspread from oauth2client.service_account import ServiceAccountCredentials import settings class LifeReader(): def __init__(self, ): def random(self, ): credentials = ServiceAccountCredentials.from_json_keyfile_dict( settings.GSPREAD['account-key'], settings.GSPREAD['scope']) gclient = gspread.authorize(credentials) spreadsheet = gclient.open(settings.GSPREAD['spredsheet-title']) worksheet = spreadsheet.sheet1 count = len(worksheet.col_values(2)) - 1 row = random.randint(2, count + 1) values = worksheet.row_values(row) return { 'who': values[1], 'birth-min': values[2], 'birth-max': values[3], 'birth-step': values[4], 'birth-unit': values[5], 'way-of-life': values[6], 'cause-of-death': values[7], 'death-min': values[8], 'death-max': values[9], 'death-step': values[10], 'death-unit': values[11] }
ちなみにブログのソースコードのスタイルを変えてみましたが、見やすいでしょうか。
次に1レコードをもらってクライアントに渡すレスポンスを作るクラス。
import random class ResponseFormatter(): def __init__(self, ): def format( self, record, ): list = [] try: birth = '今から{}{}'.format( random.randrange(int(record['birth-max']), int(record['birth-min']), int(record['birth-step'])), record['birth-unit']) except: birth = record['birth-min'] try: death = '{}{}'.format( random.randrange(int(record['death-min']), int(record['death-max']), int(record['death-step'])), record['death-unit']) except: death = record['death-min'] list.append('あなたは{}に生まれ変わりました。'.format(record['who'])) list.append('{}は{}に生まれました。'.format(record['who'], birth)) list.append('{}生き'.format(record['way-of-life'])) list.append('{}{}死にました。'.format(record['cause-of-death'], death)) return list
正直こんな規模ならモジュール分割しなくてもいいんでしょうが、クラス化すると処理が擬人化されるみたいで可愛いですよね。
ね。
コードの匂いのしみこんだ 倅その手が宝物
settings.py
に諸々の定数を寄せました。
あとでProd用とStage用で設定分けるのもいいですね。
GSPREAD = { 'account-key': { # Googleスプレッドシートのサービスアカウントキー }, 'scope': ['https://www.googleapis.com/auth/drive'], 'spredsheet-title': 'シャッフル再生教' }
あとはメイン処理。
2クラスを呼ぶだけです。
import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '../site-packages')) import datetime import json import gspread from oauth2client.service_account import ServiceAccountCredentials sys.path.append(os.path.join(os.path.dirname(__file__), '.')) import settings from lifereader import LifeReader from responseformatter import ResponseFormatter def lambda_handler(event, context): reader = LifeReader() record = reader.random() formatter = ResponseFormatter() response = formatter.format(record) return { 'statusCode': 200, 'body': json.dumps(response, ensure_ascii=False) }
実行してみます。 きちんと要素4の配列でレスポンスが返ってます。
祭の後のうら寂しさ。
興奮冷めやらない感覚ですが、ひとまずこれで終わりです。
画像を返したり、Googleスプレッドシートを論理削除したりは別の機会に。