読者です 読者をやめる 読者になる 読者になる

読書メーター→ブクログ移行用スクリプトを書いた

ツール Ruby

読書メーターからブクログへ宗旨替えすることにしたので、データを移行したい気持ちになりました。

幸い、ブクログには CSV データによる読書データのインポート機能が備わっていたことと、私が以前読書メーターのスクレイピング gem である bookmeter_scraper を作っていたことから、ブクログへの移行用にスクリプト booklognize を書きました。

github.com

このスクリプトで移行できるのは次のデータです。

  • 自分が登録した本
  • 読書ステータス
    • 読んだ
    • いま読んでる
    • 積読
    • 読みたい
  • 読了日(既読本のみ)

読書メーターで複数回読了日を記録している書籍(再読本)については、最後に読んだ日を読了日とします。

移行方法

次の流れで進めます。

  1. bookloganize でブクログへのインポート用 CSV を作成
  2. ブクログへインポート

bookloganize でブクログへのインポート用 CSV を作成

bookloganize で読書メーターからデータを取得し、ブクログへのインポート用 CSV を作成します。bookloganize はただの Ruby スクリプトなので、ダウンロードすれば使えます。thorbookmeter_scraper が必要なので、適宜インストールします。また、bookloganize は結果を標準出力に出力します。詳細は README を参照してください。

また、ブクログへインポートする CSV の文字コードは Shift_JIS とする必要があります。だいたい次のようなコマンドで所望の CSV が作成できると思います。

$ git clone https://github.com/kymmt90/bookloganize.git
$ gem install thor bookmeter_scraper
$ ruby bookloganize.rb csv <読書メーターのメールアドレス> <読書メーターのパスワード> | iconv -f utf-8 -t sjis >books.csv

CSV は次ページの「ブクログ形式」にしたがったものとなっています。

  • まとめて登録 (CSV)

      CSVファイルは、以下の項目順で1アイテムにつき1行として作成してください。
      サービスID, アイテムID, 13桁ISBN, カテゴリ, 評価, 読書状況, レビュー, タグ, 読書メモ(非公開), 登録日時, 読了日
    

ブクログへインポート

次のページから、CSV を使ってブクログへ読書データをインポートできます。

なお、読書メーターのオリジナル本機能による本を登録している場合、そのデータはブクログへ移行できません。

hatenablog-writer 0.1.1 と hatenablog 0.3.0

Ruby

今月は自分の gem にいくつか PR をいただいて新バージョンをリリースしました。PR をくださった方々、ありがとうございました。

hatenablog-writer 0.1.1

hatenablog-writer は CLI からはてなブログに投稿できるツールです。作ったきりほったらかしていたのですがブログ投稿に使ってもらっており、バグ修正の PR をいただきました。

github.com

hatenablog 0.3.0

上記の hatenablog-writer でも使っている、はてなブログ AtomPub API に Ruby からアクセスするための gem です。設定ファイルで ERB の記法が使えるようになる PR をいただきました。

github.com

この機能によって、例えば設定ファイルで次のように環境変数を使えます。アプリケーションにこの gem を組み込むときなどに使いやすくなるかと思います。

consumer_key: <%= ENV['CONSUMER_KEY'] %>
consumer_secret: <%= ENV['CONSUMER_SECRET'] %>
access_token: <%= ENV['ACCESS_TOKEN'] %>
access_token_secret: <%= ENV['ACCESS_TOKEN_SECRET'] %>
user_id: <%= ENV['USER_ID'] %>
blog_id: <%= ENV['BLOG_ID'] %>

所感

メンテや必要な機能に対する想像力が不足しがちなので、ちゃんとやっていきたい…

Ruby で順列の列挙を実装する

Ruby

最近いろいろな人が次の本をやっているのを見かけるので、気になって読み進めてみています。

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

プログラマ脳を鍛える数学パズル シンプルで高速なコードが書けるようになる70問

ほとんどの問題の解答例が Ruby で書かれているのが特徴で(たまに JS もある)、Ruby の機能やライブラリをうまく使うと簡潔に書けることがわかります。

数学パズル的な問題なので、よく順列を列挙する必要に迫られます。順列は、次のように要素列から要素を選んで並べるときの並べかたです。高校数学で場合の数を計算するときに散々やるやつですね。

[1, 2] から 2 個とる順列 → {[1, 2], [2, 1]} の 2 通り
[1, 2, 3] から 2 個とる順列 → {[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]} の 6 通り

プログラミングで順列を解くとき、場合の数は n 個から r 個とるときは n! / (n - r)! を計算すれば求められるので簡単です。一方、実際の列挙ですが、Ruby では Array#permutation という便利メソッドがあり、これを呼び出すだけで OK です。

[1, 2, 3].permutation { |p| puts p }
# [1, 2, 3]
# [1, 3, 2]
# [2, 1, 3]
# [2, 3, 1]
# [3, 1, 2]
# [3, 2, 1]

これはとても便利なのですが、Array#permutation のような順列の列挙アルゴリズムを自前で実装しようとするとどうなるっけ……と不安を感じてしまったので、調べつつ Ruby で再実装してみました。

このスクリプトを実行すると、次の出力を得ます。

[["a", "b", "c"], ["a", "c", "b"], ["b", "a", "c"], ["b", "c", "a"], ["c", "a", "b"], ["c", "b", "a"]]
[["a", "b"], ["a", "c"], ["a", "d"], ["b", "a"], ["b", "c"], ["b", "d"], ["c", "a"], ["c", "b"], ["c", "d"], ["d", "a"], ["d", "b"], ["d", "c"]]

1 行目が ['a', 'b', 'c'] から 3 個とる順列の列挙、2 行目が ['a', 'b', 'c', 'd'] から 2 個とる順列の列挙です。1 行目のほうは何個とるかの引数を省略しているので、渡している配列のサイズ分とるようにしています。

アルゴリズムは次のページを参考にしました。再帰を使って、樹形図の作成をシミュレートすればよいことがわかります。

……こういう筋力的な部分をもっと強くしておきたい人生でした。

Yokohama.rb Monthly Meetup #71 に参加した

Ruby 日記

2016-08-06(土)の Yokohama.rb Monthly Meetup #71 に参加しました。

yokohamarb.doorkeeper.jp

  • 前半はもくもく会
  • 後半は LT 2 本
  • 吉田飯店で懇親会

という流れでした。今回も初参加の方が 2 名いらっしゃいました。

もくもく会

僕は次のようなことをやってました。

LT

1 本目は仮想通貨決済ビジネスをやっておられる方から、Rails で作っているサービスについての話でした。消費者がお店に対する注文を仮想通貨で支払えるように、消費者とお店の間を Web サービスでサポートし、手数料をもらうというビジネスモデルだそうです。仮想通貨のよいところは支払いが速いところで、お店としては売掛金がすぐに回収できてよいという話でした。

2 本目は @hamakn さんから、Rails 5 の新機能である Action Cable について素振りしたという話でした。Action Cable は WebSocket を使って簡単にチャットのようなアプリケーションを作成できる機能です。用意されていたデモアプリケーションを皆で触ったりしていました。

github.com

懇親会

懇親会では、若人の悩みを聞くなかで、最終的には基礎が大事という合意が形成されました。話のなかで SICP(『計算機プログラミングの構造と解釈』)が Web 上で読めるという話が出ていました。調べてみると原文のほか、いくつか和訳もあるようです。僕は読んだことないです……


次回 2016-09-03(土)の Yokohama.rb は以下リンクから申し込めます。

yokohamarb.doorkeeper.jp

Itamae + Vagrant でステージング環境を構築しようとしている

ツール Ruby

ここ数日、構成管理ツールの練習と自作の Rails アプリケーションを本番に近い環境で動かせるようにすることを兼ねて、Itamae を使って Vagrant 上にステージング環境を作ろうとしています。

とりあえず、Rails で構築した自分の web サイトである kymmt.com を動かすべく、Vagrant で CentOS 7 の VM を作って環境構築をやっていて、現状は Itamae で次の項目を実行できるようになりました。

  • rbenv で Ruby をインストール
  • Bundler をインストール
  • GitHub からアプリケーションのリポジトリをダウンロード
  • nginx のインストールと設定
  • PostgreSQL のインストールと設定

あまりキレイではないですが、試行錯誤しつつ作った現在の Itamae レシピは次のとおりです。

ハマった点

ここまでの作業でハマった点をメモしておきます。

psql を使うときは実行ユーザを変える

コマンド itamae ssh --vagrant で Vagrant の VM に対してプロビジョニングするとき、プロビジョニングの実行ユーザは root です。一方、PostgreSQL の DB アクセス用コマンド psql は、postgres というユーザから実行するコマンドとなっています。

ユーザ postgres としてコマンドを実行するために、次のように sudo を使います。

$ sudo -u postgres -i sh -c '<実行したいコマンド>'

sudo にオプション -u をつけると、指定したユーザになることができます。オプション -i/etc/profile.bash_profile などを読み込み直します。

その後ろの sh -c '<実行したいコマンド>' が大事なところです。ここに -u で指定したユーザとして実行したいコマンドを書きます。例えば、

sh -c "psql -c \\"SELECT * FROM pg_user WHERE usename='#{node['kymmt']['dbuser']}'\\""

と書くことで、ユーザ postgres として、psql を叩いて DB 用のユーザ作成を実行しています。

SELinux を無効にする

SELinux が有効なままだと、nginx 起動時に設定ファイルを読み込めないエラーが出たりします。

Itamae プラグインの itamae-recipe-plugin-selinux で SELinux を無効にしました。

include_recipe 'selinux::disabled'

レシピ内で利用できるヘルパーメソッドを作る

今回、リソース内の commandsudo を任意ユーザで実行できるように、ヘルパーメソッドを定義しました。

module ResourceHelper
  def sudo(user); "sudo -u #{user} -i"; end
end

これを Itamae のリソース内で使えるようにするためには、Itamae::Resource::Base::EvalContext にインクルードする必要があります。

Itamae::Resource::Base::EvalContext.include(ResourceHelper)

この方法は次のエントリを参考にしました。

今後の展望

まだ次のような TODO が残っているので、引き続きやっていきます。

  • Best Practice として紹介されているディレクトリ構成にする
  • Rails アプリケーションのデプロイを自動化する
  • Let's Encrypt の設定を自動化できるか調査する

Let's Encrypt は certbot-auto でインストールすると、TUI で対話式になって自動化しにくいので、ACME プロトコルで証明書を取得できるレシピを作らないといけないのかどうかが気になってます……