RoomClip 開発者ブログ

GoogleSpreadSheetで回る記事入稿システムを構築する

こんにちは、Tunnelで エンジニアをしている仲本です。

日頃はサーバー周り、インフラ周りのおじさんとして頑張って生きております。

今回はGoogleSpreadSheetを活用した記事入稿システムを紹介させて頂きます。

弊社ではRoomClip magというWEBマガジンがございまして、 今ではお陰様でLINEの公式メディアアカウントになるほどの市民権を得ています。

運営は少人数の編集部とライターさん達で回っており、 記事の入稿はGoogleSpreadSheet上で管理・校正された原稿が本システムによって入稿されます。

今回はその辺りの仕組み周りをご紹介させて頂きたいと思います。

入稿までの流れ

以下のようにGoogleSpreadSheetのデータをWordpressまで届けます。

構成

入稿用GAS

構成(GAS) ここでは、セルに構築された原稿やタイトルなどの情報を取得し、APIサーバーに送信しています。 コード自体はクロージャである程度キレイにまとめたかったのですが、これを書いた時は初めてだったのでベタ書きでごめんなさい。 セルの内容をそのままHTTPでPOSTしているだけなのですが、一応post_tokenを付けていたずらを防ぐようにしています。

入稿用API

構成(API) 次にGASからのリクエストを受取るためのAPI部分のコードになります。 そのままWordpressに投げず、仕様や設計の変更に対する柔軟性とか含めてここで1クッション置いています。 XMLRPCの中身を作る処理は本エントリーに貼り付けるには重たすぎるので割愛するとして、このように投げてあげます。 ちなみにCodeIgniterをxmlrpcライブラリを使った書き方になります。

Wordpress

構成(Wordpress) ここでは特に書くコードはありませんが、Wordpressのxmlrpcは攻撃を受ける事が稀にあるのでこのようにEC2からしか叩けないようにしておきましょう。

これでSpreadSheetから記事入稿が出来るようになりました。 ただ、記事は色々な時間にアップされるため、公開機能を分離してコントロールする必要があります。

公開機能のGAS

構成(GAS) その際、弊社では記事の一覧を別のスプレッドシートで管理していて、そこから公開ステータスや公開日を変更できるようになっています。 そこで使われているGASはこのようになっています。 セルの値変更イベントをトリガに動作させるようにしています。 例えば、「公開」「非公開」などをスプレッドシート上でプルダウンにしておけば、運用スタッフ目線でもわかりやすいと思います。

画像変換GAS

構成(GAS) 記事はアップ出来たとはいえ、取り扱っている画像コンテンツの管理はまだ楽になっていません。 弊社のコンテンツは画像で、画像一枚一枚をIDで管理しています。 なので、画像のURL生成などを考えるとIDを元にファイル名などを生成出来た方が便利なわけです。 そのまんまな内容なのですが、画像IDを入れるとファイル名が返ってくるように作っています。 これで、画像の管理はIDで行い、URLなどの出力は関数を通して自動化するという事ができるようになりました。

コンテンツのURL生成システム

構成(rclone) 次は、自分達で調達したり作成した画像ファイルについてです。 ID管理されているわけではなく、これらはGoogleDriveで管理されています。 これらがそのまんま画像URLになればいいなあという話で、弊社ではGoogleDriveとS3を同期しています。 同期にはrcloneというソフトウェアをサーバー上でくるくると回しています。 構築は適当にAmazonLinuxを立ち上げて以下の手順で構築しました。

さいごに

このようにWordpressの管理画面を使わずにほぼGoogleSpreadSheetだけで記事入稿の運用が可能になるため、生産性も向上しました。

今後も増え続ける入稿数に対応できるように、工夫を重ねられる漢を目指していきたいと思います。 それではごきげんよう!


この記事を書いた人:仲本

Tunnel株式会社のエンジニア サーバーサイド・インフラ周りを中心に担当。 味のあるオッサンを目指して頑張っている。 夜は酒場に居る事が多い。


Yii2でブログシステムを作ってみた

Tunnelでインターンをしている松永です。
今回はこの『RoomClip開発者ブログ』を開発した話をします。

Yii2フレームワーク

タイトルにもある通り、このブログはYii2というフレームワークを用いて一から実装されています。ちなみにRoomClipの開発に使用されているのはCodeIgniterです。

Yii2はPHPのMVCフレームワークのひとつで、高速であることやセキュアであることを売りにしているようです(他のフレームワークがそうでないかというと、そんなこともないと思いますが)。 実際に使ってみると、キャッシュを簡単に使用できたりCodeceptionでのテストをサポートしていたりと非常に開発をしやすい印象を受けました。サービスの規模に応じての拡張が容易であることも魅力的でした。

このYii2にはGiiというコード生成を行うためのExtensionがあり、これを用いるとDBテーブルに紐付いたモデルクラスやCRUDコードなどをGUIを通して生成することができます。また、テーブル構造の変更を考慮してクエリなどは生成したモデルクラスを継承したクラスに記述をしています。

gii

Yii2についてのより詳細な説明はこちらを参照してください。

開発

既存のコードに変更を加えたり機能を追加することはありましたが、ほぼ何もない状態からWebアプリケーションの開発を行うのは僕にとって初めての経験でした。 知識が足りないことも多く、細かなソフトウェア設計には頭を悩まされましたが、他のエンジニアに助けてもらいつつ実装を進めていきました。

コーディング規約は基本的にYii2のコードに合わせるように定めました。Giiでコードを生成するとDBのカラム名と生成される変数名が同じになるため、カラム名もキャメルケースで統一しています。

モデルクラス内のクエリ文はできるだけcreateCommandを使用して書きたいという思いがあったのですが、そのままだと目的のクラスのオブジェクトではなく連想配列として値が返ってきてしまいます。また、数値を期待していてもクエリを通すと文字列として返ってくるため型のチェックと変換を行いたいです。

そこで、以下のようなtraitを作成し、モデルクラスに与えることでこの2つの問題を解決しました。

このコードではreadObjectで連想配列をクラスで包み、モデルクラスのValidatorを利用して型の変換を行っています。このValidatorはGiiでのコード生成時にテーブル構造から読み込まれるものなので、別途型情報を付与する必要はほぼありません。

実際に使用する際は以下のようにしています。

高速化

ある程度の形が出来上がったら、高速化をする段階に入りました。

ここではレスポンスタイムの確認にNew Relicを使用し、PHPの関数ごとにどれくらいの時間がかかっているかを見ます。どのようなクエリを何回叩いているかなども表示してくれるので、キャッシュの仕方を決めるのに非常に役に立ちました。

Yii2には、FileCache / Redis / Memcachedなどを扱うためのクラスがあらかじめ用意されており、Configで切り替えることが可能です。このConfigはすべてのアクセスの受け皿となるEntry Script内でyii\web\Applicationオブジェクトの作成時に渡されるので、このオブジェクトを通していつでもキャッシュにアクセスすることができます。この技術ブログではRedisを使用しました。

テスト

RoomClipの開発でテストを走らせることはしていなかったので、この機会にテストのコードを書くことにも挑戦をしました。テストにはCodeceptionというテストフレームワークを使用しており、これはYii2がサポートしているため簡単に導入することができました。また、Fakerというツールを使用してFixtureのためのテストケースを生成しています。
現在はcronで定時にユニットテストを走らせてSlackにログファイルをアップロードするようになっています。コミット時にフックさせられると良いかもしれません。

もちろんテストをすることでバグを発見する手助けになるわけですが、テストコードを書くこと自体も思ったより負担になりそうです。実際に運用をする際には、どれだけ手軽にテストができるかが重要になりそうですね。

完成

ざっくりではありますが、このようにして技術ブログが完成しました。
ブログシステムを一から作れることは自分にとって良い経験でしたし、メインのサービスとは切り離されているので新しいことをやるのにはとても都合の良い場でした。
これからエンジニア・デザイナー・セールス含め、多くの記事が追加されていくと思いますので、興味を持っていただけたらと思います。

今後も『RoomClip開発者ブログ』をよろしくお願いします。


この記事を書いた人:松永

Tunnel社でインターンを始めてもうすぐ1年半のB4。趣味は競技プログラミング。