くりにっき

フルスタックキュアエンジニアです

プリ☆チャンMAPを作ってみた

公式HPの あそべるお店 には住所しか載っていなくて不便なので自分用に作りました *1

drive.google.com

https://drive.google.com/open?id=1e16bKjf_dOTkHEmZLZCqVTTHlVIr3f5l

やってること

詳細は省きますが、店舗リストをスプレッドシートに投入してGoogleマイマップにインポートしているだけです

こんな感じでスプレッドシートを作っておけばいい感じに地図に表示できて便利

f:id:sue445:20180701192554p:plain

マイマップは1レイヤ辺り2000件までしか登録できないので、地区ごとにレイヤーを分けています。(都道府県単位でレイヤーを分けると今度はインポートが不便)

f:id:sue445:20180701192712p:plain

良かったこと

  • データだけ用意しておけば雑に地図を表示できる
    • jsや公開先のサーバいらず
  • 通常Googleマップに表示する時は緯度経度の情報が必要だが、住所だけで地図に表示できる
    • ジオコーディングいらず

苦労したこと

  • GoogleマイマップにはAPIがない
  • インポート元のスプレッドシートが更新されてもマイマップは 更新されない
    • てっきり同期されてるもんだと思っていたら、再反映時は都度レイヤー削除&インポートが必要っぽい
  • スプレッドシートは1枚目のシートしかインポートしてくれない
    • 最初は1枚のスプレッドシートに対して地区(レイヤ)ごとにシートを分けていたんですが、それだと一番左のシートしか登録できなかったので各地区ごとにスプレッドシートを作るようにしました
  • 公式HPに載ってる住所が一部おかしくてそのままインポートするとエラーになる
    • 2000件中20件くらいがエラーになったので手で直しています(´・ω・`)

*1:ソースは非公開です

Trelloで散財リストを管理する

タスク管理ツールとして有名な Trello を散財リストとして運用している知見の紹介です。

僕の散財リスト

百聞は一見にしかずということで僕の散財リストを晒し。

f:id:sue445:20180626234629p:plain

リスト

購入予定

Twitterで買いたいものの新作情報が流れてきたら購入予定リストにカードを追加します。

f:id:sue445:20180626235028p:plain

カードの期限のところに僕は商品の発売日を入力しています。

この時言語設定がEnglishだと日付が分かりづらいので日本語推奨。

Englishだと MM/DD/YYYY

f:id:sue445:20180626235310p:plain

日本語だと YYYY/MM/DD

f:id:sue445:20180626235144p:plain

発売日(期限)順にソートできて便利。

f:id:sue445:20180626235558p:plain

予約済

実際にAmazonとかで予約したらカードを移動します。

f:id:sue445:20180626235748p:plain

「購入予定」と「予約済」でリストがわかれているのは、Twitterとかで情報が出た時点では予約が始まってないことがあるので予約することを忘れないためです。

どのサイトで予約したかをラベルにしとくとAmazonで予約したことを忘れて楽天で再度予約したりすることがなくていいかもしれないですね。*1

f:id:sue445:20180626235810p:plain

購入済

実際に購入したらカードを移動します。

まとめ

一番古いカードを見たら2014年11月だったのでだいたい3年半くらいTrelloで散財リストを運用しているようです。

f:id:sue445:20180627000428p:plain

Trelloを使う前はEvernote辺りを使ってたと思うのですが、予約済なのか購入済なのかのステータス管理が面倒でした。

Trelloを使うことでステータス管理できるようになって効率よくプリキュアに散財できるようになりました

*1:僕はラベル付けることをよく忘れてますが

プリパラを全話見た

きっかけ

4月の新番組の キラッとプリ☆チャン を見始める

www.tv-tokyo.co.jp

  ↓

5月頃映画が上映されたのでなんとなく見に行く

pp-movie.com

  ↓

入場者特典が欲しいので3周鑑賞

  ↓

映画の元ネタを知るためにプリパラ全話視聴

キュアエンジニアがプリパラにハマっていく流れ

1st season

anime.dmkt-sp.jp

anime.dmkt-sp.jp

anime.dmkt-sp.jp

ちなみにこの辺はRubyKaigiの宿でPR書きながら見てたと思います。

2nd season

anime.dmkt-sp.jp

(上記ツイートはブラジルじゃなくてメキシコの勘違い)

anime.dmkt-sp.jp

3rd season

anime.dmkt-sp.jp

anime.dmkt-sp.jp

アイドルタイム

anime.dmkt-sp.jp

anime.dmkt-sp.jp

余談

初めて見たプリキュアの映画がオールスターズNewStageで当時まともに見てたのはスイートとスマイルだけでしたが、その後過去作品全話視聴しています

参考

sue445.hatenablog.com

この後の予定

プリリズとキンプリを見ていこうと思います。

追記

一番好きなユニットはガァルマゲドンです

本を売った

近々引っ越しをする予定があって、引越し前に荷物の整理をしたくて物理本をほぼ全部売ったのでその時のメモ。*1

漫画・ラノベ

まんだらけの宅配買取を利用

ekizo.mandarake.co.jp

詳しい冊数は数えてないけどダンボール2箱でたぶん100冊前後。買取金額は4720円也

ただし発払いで送料(3000円ちょい)をこっちが負担したので、実質的な利益は1000円ちょい。いやまぁ、荷物を減らすことが目的だったんで金額はそんなに気にしてないんですが。

技術書

電脳書房 の宅配買取を利用。

www.bookcyber.net

ここをチョイスしたのは以前知り合いのブログで読んで名前を覚えていたため。

yoonchulkoh.hatenablog.com

目録作るのが手間だったけど10冊ごとに買取金額500円アップはデカイ。

最終的に80冊で12000円(前述の事前見積りボーナス込みで16000円)で買い取ってもらえましたが特筆すべき点は着払いで先方が送料負担してくれたこと。こっちもダンボール2箱だったけどもし発払いだったら3000円くらい減ってたところだった。ありがたい

目録をメールで送って何回かやり取りしていく中でゆうパックの着払いで送ってくれって言われたのですが、発送元の場所やダンボールの数によっては発払いになるのかもしれない。

目録をメールで送った段階で「買取金額は最大このくらいだけど本の状態によっては金額が下がります」って言われてたのでちょっと心配してたんだけど、表紙の日焼けくらいは特に問題なく12000円で買い取りしてもらえた。(タバコの臭いがついていると買い取り金額が大きく下がるとのこと)

*1:「ほぼ」と書いているのはサイン本やプリキュア関係の書籍だけ手元に残しているため

padrinoにPRを送った

padrino アプリでactiverecordを5.1系から5.2.0に上げようとしたら rake ar:migrate でエラーになったので直した

エラー内容

activerecord 5.2系からは ActiveRecord::Migrator.migrate がなくなったとのこと。めちょっく!

$ bundle exec rake ar:migrate:reset --trace
** Invoke ar:migrate:reset (first_time)
** Invoke ar:drop (first_time)
** Invoke skeleton (first_time)
** Execute skeleton
** Execute ar:drop
** Invoke ar:create (first_time)
** Invoke skeleton
** Execute ar:create
** Invoke ar:migrate (first_time)
** Invoke skeleton
** Execute ar:migrate
rake aborted!
NoMethodError: undefined method `migrate' for ActiveRecord::Migrator:Class
/app/vendor/bundle/ruby/2.5.0/gems/padrino-gen-0.14.3/lib/padrino-gen/padrino-tasks/activerecord.rb:127:in `block (2 levels) in <top (required)>'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `block in execute'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `each'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:271:in `execute'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:237:in `block in invoke_prerequisites'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:235:in `each'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:235:in `invoke_prerequisites'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:212:in `block in invoke_with_call_chain'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/task.rb:182:in `invoke'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:160:in `invoke_task'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `each'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:116:in `block in top_level'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:125:in `run_with_threads'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:110:in `top_level'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:83:in `block in run'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:186:in `standard_exception_handling'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/lib/rake/application.rb:80:in `run'
/app/vendor/bundle/ruby/2.5.0/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
/app/vendor/bundle/ruby/2.5.0/bin/rake:23:in `load'
/app/vendor/bundle/ruby/2.5.0/bin/rake:23:in `<top (required)>'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:75:in `load'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:75:in `kernel_load'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:28:in `run'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli.rb:424:in `exec'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli.rb:27:in `dispatch'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/cli.rb:18:in `start'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/exe/bundle:30:in `block in <top (required)>'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/lib/bundler/friendly_errors.rb:122:in `with_friendly_errors'
/Users/sue445/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.1/exe/bundle:22:in `<top (required)>'
/Users/sue445/.rbenv/versions/2.5.1/bin/bundle:23:in `load'
/Users/sue445/.rbenv/versions/2.5.1/bin/bundle:23:in `<main>'
Tasks: TOP => ar:migrate:reset => ar:migrate

修正内容

github.com

現時点でまだgemはリリースされてないのでpadrinoでactiverecord 5.2系使いたい場合はmasterブランチを要参照。

activerecordのメソッドを直接読んでRailsdb:migrate 相当のことを実現してるgemはたまにあるので、そういう場合はこれを参考に直せばいいと思います。

itamaeプラグインのCIを作り直した

個人開発してるitamaeプラグインのCI環境を作り直したのでその知見

tl;dr;

itamaeプラグインのCIにDockerを活用してモダンになった

今までのCI

下記のブログに詳しく書いています

sue445.hatenablog.com

問題点

元々この構成は オライリーのServerspec本 を参考に構築してたのですが、長年使ってきて下記のような問題点がありました

DigitalOcean依存による問題

  • 同一OSでもローカル(VirtualBox)とCI(DigitalOcean)とでイメージが違うので、ローカルだとOKでもCIだとビルドがコケることがある
  • WerckerからDigitalOceanでVMを立ち上げる時に、VMの起動に失敗することが稀によくある
  • ssh越しにitamaeを実行するので遅い
  • DigitalOceanに利用にもお金がかかるのでビルドを回す度にお金が減る
    • itamaeプラグイン6個でweeklyビルドを実行して月1ドル前後

Vagrant依存による問題

  • 古いVagrantに依存しているため最新のbundlerと相性が悪い *1
  • CI実行時に毎回Vagrantをダウンロードしてインストールしてるのでその分ビルドが遅い

新しいCIの構成

  • TravisCI
  • Docker

やったこと

https://github.com/sue445/itamae-plugin-recipe-tig/pull/13 をかいつまんで説明

gemの依存にdocker-apiを追加

spec.add_development_dependency "docker-api"

spec/spec_helper.rbを修正

require 'serverspec'
require 'docker'

set :backend, :docker

set :docker_image, ENV['DOCKER_IMAGE']
set :docker_container, ENV['DOCKER_CONTAINER']

# Disable sudo
# set :disable_sudo, true


# Set environment variables
# set :env, :LANG => 'C', :LC_MESSAGES => 'C'

# Set PATH
# set :path, '/sbin:/usr/local/sbin:$PATH'

# via. http://qiita.com/sue445/items/b67b0e7209a7fae1a52a
require "yaml"
require "itamae/node"

def node
  return @node if @node

  hash = YAML.load_file("#{__dir__}/../recipes/node.yml")

  @node = Itamae::Node.new(hash, Specinfra.backend)
end

自分の場合spec内でnodeの値を使うことが多いので上記のような構成にしてるので不要な場合は node メソッドを削除してください。あとnode.ymlのパスは必要に応じて要微調整。

spec_helper.rbは下記が参考しています

joe-noh.hatenablog.com

.travis.ymlを修正

serviceを使わない場合

envIMAGEでDockerイメージの名前を渡してマトリクステストできるようにしています

language: ruby
sudo: required
services:
- docker
rvm:
- 2.3
env:
- IMAGE=centos:7
- IMAGE=debian:jessie
bundler_args: "--jobs=4"
cache: bundler
before_install:
- gem update --system --no-document
- gem install bundler --no-document
script:
- bundle exec itamae docker --node-yaml=recipes/node.yml recipes/install.rb --image=$IMAGE --tag itamae-plugin:latest
- DOCKER_IMAGE=itamae-plugin:latest bundle exec rspec

serviceを使う場合

CentOS 7だけかもしれないんですが普通に docker run した状態でserviceを起動しようと「Failed to get D-Bus connection: No connection to service manager.」というエラーになるので itamae-plugin-recipe-consul では下記のように書いていました。

before_script:
- docker run --privileged -d --name container-with-service $IMAGE /sbin/init
script:
- bundle exec itamae docker --node-yaml=recipes/node.yml recipes/install.rb --container=container-with-service --tag itamae-plugin:latest
- DOCKER_CONTAINER=container-with-service bundle exec rspec

このエラーの解決には下記が参考になりました

qiita.com

メリット

一番大きなところでは、ビルドの時間が速くなってます。

外部クラウドに対してVM起動することがなくなったり、ssh越しにコマンドを実行せずにローカルのDockerコンテナに対してコマンドを実行するようになったことから全体的にビルド時間が速くなりました

修正前後での1回辺りのビルド時間を集計しましたが、軒並み速くなっているのが確認できます。(修正前後ともに3~5回くらいビルドを実行した時の平均時間を記載)

修正前のビルド時間 (秒) 修正後のビルド時間 (秒)
itamae-plugin-recipe-consul 288.3 197.5
itamae-plugin-recipe-git_now 328.3 248
itamae-plugin-recipe-omori_gohan 300.6 205
itamae-plugin-recipe-tig 374.2 322
itamae-plugin-resource-encrypted_remote_file 441.4 315
itamae-plugin-resource-tmux 612.6 255.75

その他メリット

  • 不安定なビルドがだいぶなくなった
    • 修正前はDigitalOceanのVM起動が不安定だったのですが、TravisCIでDockerを起動することによりビルドがだいぶ安定するようになりました。*2
  • ローカルとCIで完全に同じ環境が使えるようになった
    • ローカルでも --provider=digital_ocean つければいいわけなのですが、自分以外の人がローカルで確認するためだけにDigitalOceanに登録してもらう必要があるので強制しづらい
  • DigitalOceanを使わなくなったのでその分のコストが浮いた

デメリット

  • Docker依存の問題によりレシピが実行できないことがある
    • 前述のsystemd問題など
  • 他にもDocker由来の問題でハマりどころはあるかもしれない

おまけ:同じ構成をCircleCIで書いた場合

最初全く同じ構成をCircleCIで書いていたのですがymlが膨大になりすぎて途中でTravisCIに移行しました。

最初に書いていたCircleCIの設定ファイル

https://github.com/sue445/itamae-plugin-recipe-tmux/blob/fb1ee0273d5445e48c572fa8ac1528907e38b05c/.circleci/config.yml

CircleCIも悪くはないんですが、マトリクステストしたい場合にはTravisCIの方が簡潔に書けていいですね。

*1: https://github.com/hashicorp/vagrant/blob/v1.8.4/vagrant.gemspec#L23

*2:TravisでのDocker起動時にもたまにエラーは出るんだけどDigitalOceanよりはだいぶ頻度は少ない

rubicure v1.1.2リリース

はぐプリでは公式HP*1のキャラ紹介に誕生日が載っていなくててっきり誕生日設定がないのかと思っていたのですが、プリティストアのTwitterアカウントからキュアエトワールの誕生日情報が流れてきたので対応しました。