試したこと、読んだ本について書いていくブログです。

退職エントリ


12月いっぱいで今の会社を退職します。
次の職場でもがんばるぞい!

Read more ⟶

コーヒー美味しい


コーヒーサーバを手に入れました。
ありがとうサンタさん、来月はクレカ支払い頑張るよ。

マグカップが汚い…黒色のマグカップを使えば汚れが目立たなくていいのでは🤔

ステンレスフィルタを使うのは初めてなのですが粉が残りますね。フィルタを洗うのも手間なので、普段はペーパーフィルタを重ねて使った方が手軽そうです。

電気ケトルから直接お湯を注いでいるのですが、注ぎ口が広いのでまともに「の」の字を書いてドリップすることができませんでした。 注ぎ口が細くなっている電気ケトルかヤカンが欲しくなります。

どうせなら、自宅でコーヒー豆を挽いたり、焙煎したり…沼が広がります。

Read more ⟶

Pocketからお祝いされました -2018-


Pocketから以下のメールが届きました。

2016年、2017年には上位5%になったことを祝福するメールが届きましたが、ついに2018年は上位1%のユーザになれたようです。

自分が登録した記事の中から人気がある記事をピックアップしてみるとQiitaの記事が多いみたいです。
やはりQiitaはSEOに力を入れているのか閲覧者が多いようですね。

ちなみに、2018年12月21日時点では全記事数が9,720ページ、未読記事が2,289ページ、既読率76.5%という状況です。 2017年2月4日時点では全記事数が4,887ページ、未読記事が800ページ、既読率83.6%でしたので積読が捗っているようです。

毎日、未読率を出したり、未読記事からランダムでSlackに投稿するようにしましたが、まだ手緩いようです。todoリストと連携して毎日記事を読むように仕向けましょうか…

しかし…プレミアム会員にもなっていない自分が上位1%のユーザになれてしまうとは…
若者のPocket離れが深刻ですね。 Pocketなら気になる記事を後から読み返すことも簡単に出来るし(実際は読み返さないけど)、PocketのArticle Viewなら邪魔くさい広告が表示されないから集中して記事が読めて便利ですよ!
みんな使いましょう!!

Read more ⟶

Golangのpanicのお話


はじめに

Golangというと、クロスコンパイルが特徴の1つとして挙げられます。
クロスコンパイルにより、Macで書いたコードからLinuxやWindows向けの実行ファイルを簡単に生成することができます。そのため、業務で使う便利ツールを作ってチーム内に配る、といったことも容易に行えます。
今回は僕がGolangを書き始めたばかりのころ、他の環境で動かすツールを作ったときに驚いた思い出ばなしです。

サンプルコード

実際のコードとは違いますが、当時は以下のようにエラーが発生したらpanic()で処理を中断させるコードを書いていました。

で、このコードを以下のようなディレクトリ構成の中に配置していました。log_analysisが1つのプロジェクトというイメージです。

tmp
└── tanaka
    └── azunyan_prpr
        └── tools
            └── log_analysis
                └── main.go

このコードをmitchellh/goxを使ってクロスコンパイルすると、以下のように各プラットフォームに対応した実行ファイルが生成されます。

$ gox
Number of parallel builds: 3

-->   freebsd/amd64: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->      netbsd/arm: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->       linux/386: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->      darwin/386: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->   windows/amd64: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->     openbsd/386: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->   openbsd/amd64: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->     windows/386: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->      netbsd/386: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->     freebsd/arm: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->    darwin/amd64: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->       linux/arm: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->     linux/amd64: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->     freebsd/386: _/tmp/tanaka/azunyan_prpr/tools/log_analysis
-->    netbsd/amd64: _/tmp/tanaka/azunyan_prpr/tools/log_analysis

$ ls -1
log_analysis_darwin_386
log_analysis_darwin_amd64
log_analysis_freebsd_386
log_analysis_freebsd_amd64
log_analysis_freebsd_arm
log_analysis_linux_386
log_analysis_linux_amd64
log_analysis_linux_arm
log_analysis_netbsd_386
log_analysis_netbsd_amd64
log_analysis_netbsd_arm
log_analysis_openbsd_386
log_analysis_openbsd_amd64
log_analysis_windows_386.exe
log_analysis_windows_amd64.exe
main.go

log_analysis_windows_amd64.exeがWindows(64bit)向けの実行ファイルになるので、Windows10のD:\tools配下に置いておきます。
log_analysis_windows_amd64.exeを実行すると、読み込むべきsample.logが存在しないのでpanic("ファイルないよ")が実行されます。

Read more ⟶

Tweetボタンでつぶやく内容を動的に変更する


はじめに

今回はWebページ設置するTwitterの共有ボタンからTweetを行う際、Tweetする内容を動的に変更する方法をご紹介します。

本文

Twitterの共有ボタンを設置するだけなら、Twitter公式サイトで生成できる以下のコードをHTMLに埋め込むことで簡単に実現できます。

<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-text="ハローワールド" data-show-count="false">Tweet</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

しかし、この方法だとTweetする文章を動的に変更することはできません。

そこで、JavaScriptでTweetする内容を生成して、window.openメソッドでTweet共有用のURL(https://twitter.com/share) を呼び出すことで対応します。
URLに以下のパラメータを追加することで、ハッシュタグやアカウントを含めたTweetを行うことができます。

パラメータ説明
textTweetする文章
urlTweetに含めるURL
viaTweetに含めるアカウント
hashtagsTweetに含めるハッシュタグ
relatedTweet後にフォローを勧めるアカウント

サンプルコード

以下がサンプルコードになります。
JavaScriptのコードが18行ありますが、ほとんどは現在時刻を求めているだけで、実際にTweetを行うのに必要なのは17行目のwindow.open(...);だけです。

See the Pen mQrWxz by foresukecom (@foresukecom) on CodePen.

Tweetボタンを押すと、以下のようなTweetを投稿できます。

※追記
Tweetが140文字を超えたらどうなるか確認したところ、以下のように403エラーとなりました。
実際に使うなら、文字数チェックの処理が必要ですね。

See the Pen dynamit_tweet_long by foresukecom (@foresukecom) on CodePen.

その他

最近Ultimate Chicken Horseをはじめました。
このゲームは4人対戦の2Dアクションゲームです。スタートからゴールまで早く到着したプレイヤーが勝ち、というシンプルなルールなのですが、試合ごとに足場やトラップを自由に設置できるので、後半になるほどカオスなコースになり、ワイワイと楽しむには最適なゲームです。

Read more ⟶

GAEでバッチ処理


はじめに

Google App Engine(GAE)を使って、バッチ処理が実行できたのでメモです。
GAEではcron.yamlに設定を記載することで時間を指定した処理を行うことができます。

サンプル

今回は、slackにメッセージを送信するアプリを定期的に実行させてみます。

slackにメッセージを送る部分は以下のサイトに詳しく記載されているので省略します。
CrossBridge Lab | GolangでSlackの特定のチャンネルにメッセージを送る

今回はGAE上でGolangを動かしてみましたよの構成を元に、GAEのプロジェクトを構築します。
ルートディレクトリ(app.yamlと同じ階層)にcrom.yamlを作成します。

cron.yaml

cron.yamlには、以下のように開始時刻や間隔で実行するタイミングを指定することが出来ます。

cron:
- description: "毎朝7時(日本時間)に実行"
  url: /morning
  timezone: Asia/Tokyo
  schedule: every day 7:00

- description: "毎週日曜8時(日本時間)に実行"
  url: /morning
  timezone: Asia/Tokyo
  schedule: every sunday 8:00

- description: "毎日0時を起点とし、1時間単位で実行"
  url: /morning
  timezone: Asia/Tokyo
  schedule: every 1 hours

その他のスケジュール指定方法や、HTTPリクエスト失敗時のリトライ回数は公式のドキュメントに詳しく記載されています。

注意点

GAEではdev_server.pyでローカルにサーバを立ち上げて、動作確認をすることができます。しかし、ローカル環境では、cron.yamlは動作しません。
localhost:8000 からGAEローカル環境の管理画面を開くことができます。
管理画面にcron.yamlで設定したスケジュールが一覧で表示されるので、Run nowをクリックすることで手動で実行することができます。

Cronの設定を本番環境にデプロイするときは、gcloud app deploy cron.yamlのようにcrom.yamlを指定します。
指定しないと、crom.yamlが読み込まれないため、いつまで待っても処理が実行されません。 Cronが設定されているかどうかは、コンソール画面のcronジョブから確認することが出来ます。

仮に他のユーザからHTTPでのリクエストがあった場合、想定していない時間に処理が実行される可能性があります。
そのため、GAEのcronサービスからのHTTPアクセス以外からのアクセスは除外する必要があります。
GAEのcronサービスからのHTTPアクセスにはHTTPヘッダにX-Appengine-Cron: trueが含まれているので、HTTPリクエストを受け取ったタイミングで、チェックする必要があります

例えば、GolangでGAEのcronサービス以外からのHTTPリクエストを弾くには、以下のように書きます。
(弾いた後の処理がお粗末ですが…)

// cron以外からのアクセスは弾く
if r.Header.Get("X-Appengine-Cron") != "true" {
	os.Exit(1)
}

感想

GAEはhttp(s)でのリクエストに対してレスポンスを返すだけのサービスだと思っていたので、時間指定で処理を実行してくれるのはとても意外でした。

Read more ⟶

GAEでfaviconを設定


はじめに

GoogleAppEngine(GAE)上で提供するWebページにfaviconを設定するさいに、少し迷ったのでメモに残しておきます。

faviconとは

faviconとは、ブラウザのタブやブックマークに表示されてるアレです。
最近は、スマートフォンでWebページのショートカットをホーム画面や、Windows10のスタートメニューで見かけることも増えてきました。

faviconについては、以下の資料に詳しくまとめられています。
WEBサイトが「できた」と安心する前に最終チェックすること

favicon準備

faviconの元にするイラストはこちらです。 このイラストをいい感じにfaviconとして使っていきます。

今回は、スライドで紹介されているFavicon Generatorを使ってfaviconを用意していきます。
faviconを生成すると、favicon_package_v0.16.zipがダウンロードできます。
favicon_package_v0.16.zipは以下のような中身になっています。

favicon_package_v0.16
├── android-chrome-192x192.png
├── android-chrome-384x384.png
├── apple-touch-icon.png
├── browserconfig.xml
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon.ico
├── mstile-150x150.png
├── safari-pinned-tab.svg
└── site.webmanifest

この中ので拡張子がpngicoは実際に表示されるイメージファイルです。
browserconfig.xmlはWindows10のスタート画面にWebページをピン留めしたときに表示される画像の設定情報です。このファイルは明示的に読み込まなくても、ルートディレクトリに置いておけば、勝手に読み込んでくれます。
safari-pinned-tab.svgはベクターというフォーマットの画像ファイルです。safariで表示するfaviconはこの画像を使っているようです。
site.webmanifestはAndroidでWebページをホーム画面に追加したときのアイコンや、タイトルを設定するファイルです。

今回はGAE上でGolangを動かしてみましたよの構成を元に、faviconを設定します。
browserconfig.xmlsite.webmanifestはルートディレクトリに配置し、その他の画像ファイルはルートディレクトリ直下のimagesに配置します。
プロジェクトのディレクトリ構成は以下の通りです。

.
├── app.yaml
├── gae_sample.iml
├── hello.go
├── index.yaml
└── static
    ├── browserconfig.xml
    ├── site.webmanifest
    ├── images
    │   ├── android-chrome-192x192.png
    │   ├── android-chrome-384x384.png
    │   ├── apple-touch-icon.png
    │   ├── favicon-16x16.png
    │   ├── favicon-32x32.png
    │   ├── favicon.ico
    │   ├── mstile-150x150.png
    │   └── safari-pinned-tab.svg
    ├── index.html
    └── js
        └── main.js

GAEで使う

GoogleAppEngineでfaviconを使用するには、HTMLファイルの<head>で読み込む以外に、Why do I get URI error for /favicon.ico?にも書かれているとおり、app.yamlにも記載する必要があります。

Read more ⟶

祝日のカウントダウンタイマー


はじめに

GoogleAppEngine(GAE)、Golangの勉強のために、祝日までのカウントダウンタイマーを表示するWebページを作ってみました。

https://shukujitsu.info

処理の内容

内閣府が祝日の情報をCSV形式で公開しているので、定期的に取得して、加工して、CloudStorageにアップロードしています。
GAEにアクセスがあると、CloudStorageから祝日情報を読み込んで、いい感じに加工して表示しています。

使ってる技術

GoogleAppEngine

インフラとしてGAEを使いました。
GAEに対応していない関数とかもあるので、ドキュメントを見ながら覚えていくしかなさそうです。
たとえば、GolangでHTTPのリクエストを行うときにhttp.Get()を使いますが、GAEでは対応していないのでurlfetch.Clientを使う必要があります。 他にも、Javaでは時刻を扱うjava.time.LocalDateというライブラリがあるのですが、同様にGAEでは使うことができません。
GAE使うなら言語に依らず注意する必要があります。

Golang

ネット上に公開されているCSVファイルを読み込んで、Cloud Storageにアップロードする部分をやってます。
もともと、Golangの勉強を兼ねたプロジェクトだったんですが、あまりGolangを使いませんでした。

Vue.js

JavaScriptで変数を書き換えると、いい感じにHTMLで表示される内容も変更されます。
まだVue.jsを使いこなせてはいませんが、低い学習コストでさっくり使うことができます。

Scrollify

マウススクロールでいい感じに画面を切り替える処理はScrollifyを使いました。
これを使うだけで今風な感じがでます。

今後の課題

データ保管場所

情報をCloudStorageに保存してるので、NoSQLを触ってみようかと考え中です。
日付と祝日名を格納するだけなのでRDBでも問題ないんですけど…

監視、ログ

なんらかのエラーが起きた場合はソーリー画面を出し、StackDriver上にログを出すようにしていますが、能動的にチェックしないとエラーに気が付きません。
エラーを検知したら通知する仕組みがほしいですね、LINEかSlackに飛ばすのが今風でしょうか…

パッケージ管理

使用しているライブラリのバージョン管理とかをしていないので、一般的に使われている(らしい)、depを使ってみようかと考え中。
次バージョンのGolangではmodulesという新たなパッケージ管理機能が正式リリース予定なので、最終的にはそっちに映る感じでしょうか。

リファクタリング

ディレクトリ階層がぐちゃぐちゃで、1つ1つのファイルも肥大化しているのでキレイにしたいです。
ある程度キレイになったらリポジトリを公開するのもアリですね。

CIツール導入

現在、dev_appserver.pyでローカル環境を立ち上げて、動作チェックが済んだらgcloud app deployで本番環境を更新する、という雑な運用をしています。
雑すぎるので、CircleCIとかを使って、PR投げたらステージング環境でテストが実行されてー、というのを導入したいです。

AltJS

「素のJavaScriptを書くのがツラい」という話を聞くことが増えてきました。
この規模なら素のJavaScriptでも問題ないですが、今後のことを考えるとTypeScriptかCoffeeScriptあたりを勉強して置き換えることを考え中です。

WPA化

WPAであれば、オンライン状態でアクセスしておけば、オフライン状態でもそのWebサイトにアクセスができるようです。
地下鉄などの電波状況が悪い場所でも祝日カウンターが使えれば素敵ですね。

見た目

レイアウト気にし始めるとキリがないので一旦リリースしてしまいました。
運用しながら徐々に変更を加える予定です。

感想

本当はcoinhive仕込みたかったけど神奈川県警に捕まったらいやなので我慢しました。
認証も、DBへのアクセスもないページですが、1人でインフラ、サーバサイド、フロントエンドの構築を行ったのでいろいろと勉強になりました。
細々としたTipsはブログに残していきたいです。 課題もたくさん出てきたので、徐々に直していきます。

欲しい機能とか、気になる箇所があれば、お気軽に@foresukecomまでご連絡下さい。

その他

ここ数年、ウィルキンソンの炭酸水をAmazonで定期購入してます。炭酸水のおかげで、ビールを飲む量がだいぶ減りました。
でも、炭酸水はウイスキーのチェイサーに最適なんですよね…割れば簡単にハイボールも作れるし…
悩ましい飲み物です。

Read more ⟶

ReactNativeを触ったお話


はじめに

お仕事でReactNativeを使うことになったので、触ってみました。

導入手順について本記事内では説明をしないので、ReactNativeの公式サイトのGetting Startedをご参照ください。
ちなみに、ReactNativeのバージョンは0.57.3です。

サンプル

今回はRESAS-APIから都道府県一覧を取得してリスト表示してみます。
react-native init projectNameを実行直後のディレクトリ構成は以下の通りになっています。

projectName
├── android
├── ios
├── node_modules
├── App.js
├── app.json
├── index.js
├── package-lock.json
└── package.json

今回はApp.jsのみを以下のように変更を加えていきます。

RESAS-APIを使うには事前に公式サイトから利用登録する必要があります。
X-API-KEYはRESAS-API登録時に発行されるキーを指定して下さい。

感想

ReactNativeは活発に開発が行われていますが、毎週のように最新バージョンが更新されているため、開発環境の構築が面倒ですね。
今回は使わかなかったから影響ないですが、ReactNativeの0.57.3ではButtonコンポーネントを使うとAndroidシミュレータで以下のエラーが発生します。
https://stackoverflow.com/questions/52784633/i-have-some-error-when-add-button-to-my-react-native-app

もう少し安定した(悪く言えば枯れた)技術を使った方が開発も運用も楽なんですが、最近はそんなことを言っていたら取り残されちゃうから、日々勉強するしかないですね。
でも…せめてLTSがあるといいな…

開発環境の構築が終われば、シミュレータ上でポンポンとテキストなりボタンなりを配置できるから面白いです。

その他

最近、フラジャイルを読み返しました。
医療漫画はいいですね。Dr.コトー診療所を読んだ時もそうですが、泣いてしまいます。特に3巻、4巻のアミノ製薬の話が好きです、火箱ちゃん可愛い。
フラジャイルはドラマ化しているみたいなので、そのうち観てみたいです。

Read more ⟶

JavaScriptでクロージャを触ったお話


はじめに

クロージャの存在は知っていましたが、ちゃんと使ったことがなかったんで使ってみました。

クロージャの詳しい説明はmozillaが公開している以下のドキュメントにわかりやすく載っているので省略します。 MDN web docs

サンプル

1から6までの整数を返す関数に追加機能として、連続して同じ値が出ないようにしてみます。 連続して同じ値が出なくなったので、ランダム感を演出できるようになりました。
実際には結果を操作してるのでランダムとは言えなくなりましたが ^^;

まずはクロージャを使わない例です。
前回の結果を保持する変数prevNumをグローバル関数として定義しているので、関数dice()以外からもアクセスが出来てしまいます。

See the Pen random_no_closure by foresukecom (@foresukecom) on CodePen.

次がクロージャを使った例です。
こちらではprevNumdice()内で定義しているので、dice()の外ではprevNumが使えなくなりました。

See the Pen random_closure by foresukecom (@foresukecom) on CodePen.

感想

クロージャを使わなくても同じ機能は実装できますが、グローバル変数の使用を抑えられるのは嬉しいところです。 今回のサンプルのような短いプログラムではありがたみも薄くなりますが、

前回と違う乱数を生成する箇所はforifを使わずに、剰余演算を使ってワンライナーできなかと一晩悩みましたが思いつきませんでした。
もっといい感じの計算式をご存知の方がいたら教えてください。

その他

最近、地元の静岡が舞台になっているローカル女子の遠吠えの4巻が発売されました。 作者の瀬戸口みづき先生も静岡出身ということで、思わず膝を連打するネタが多いです。

ただ…この漫画を読むと静岡に帰りたくなるので、転職や引越しなどの重大イベントを控えたタイミングでは読まないほうがいいでしょう。
あー、亀まんじゅう食べたい。げんこつハンバーグ食べたい。

Read more ⟶