ぼっち演算子を使える2.3系にアップデート。

$ CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline`" rbenv install 2.3.1

railsのプロジェクトでbundleしたらeventmachineのインストールでコケた。

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7/ext
/usr/local/var/rbenv/versions/2.3.1/bin/ruby -r ./siteconf20160518-21178-1i9l3os.rb extconf.rb
checking for rb_trap_immediate in ruby.h,rubysig.h... no
checking for rb_thread_blocking_region()... no
checking for ruby/thread.h... yes
checking for rb_thread_call_without_gvl() in ruby/thread.h... yes
checking for inotify_init() in sys/inotify.h... no
checking for __NR_inotify_init in sys/syscall.h... no
checking for writev() in sys/uio.h... yes
checking for rb_thread_fd_select()... yes
checking for rb_fdset_t in ruby/intern.h... yes
checking for rb_wait_for_single_fd()... yes
checking for rb_enable_interrupt()... no
checking for rb_time_new()... yes
checking for sys/event.h... yes
checking for sys/queue.h... yes
checking for clock_gettime()... no
checking for gethrtime()... no
creating Makefile

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/eventmachine-1.0.7/mkmf.log

current directory: /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7/ext
make "DESTDIR=" clean

current directory: /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7/ext
make "DESTDIR="
compiling binder.cpp
In file included from binder.cpp:20:
./project.h:116:10: fatal error: 'openssl/ssl.h' file not found
#include 
         ^
1 error generated.
make: *** [binder.o] Error 1

make failed, exit code 2

Gem files will remain installed in /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7 for inspection.
Results logged to /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/eventmachine-1.0.7/gem_make.out

下記を参考にして設定したらいけました。

$ bundle config build.eventmachine --with-cppflags=-I$(brew --prefix openssl)/include
参照:Ruby2.3.0 igaiga diary(2015-12-25)

railsらしいやり方、turbolinksともマッチするjavascriptの書き方ができるturboctrlというgemをリリースしました。

komagata/turboctrl

これは何?

/posts/1にアクセスしたらapp/assets/javascripts/controllers/posts_controller.js.coffeeにあるPostsControllerクラスのshowメソッドが呼ばれるというものです。
# app/assets/javascripts/controllers/posts_controller.js.coffee:
class @PostsController
  show: ->
    console.log "Hey!"

なぜ作ったのか

「さっさとwebアプリを書きたい。」

「RailsのRailから外れる面倒なことはしたくない。」

「Railsはjsの書き方についてRailがなさすぎる。」

「Railsっぽいままjsを書きたい」

「Sprockets捨てるとかではなく、既存の仕組みのまま行きたい」

というのがモチベーションです。

「coffeeの1ファイルに1クラスだけ書く」というルールすら共有されてないと行くプロジェクト行くプロジェクトで辛いんですよね。

class @Foo

sprocketsを使う以上、上記のようなクラスの書き方しますよってとこも共通認識にしたい。

ご意見、ご要望、Issue、PR歓迎です。

検索順位のチェック

Google検索で自分のサイトがあるキーワードで何番目に来るかというのはサイトを運営する上で非常に重要なデータであり指標だと思うんですが、なかなか簡単で正しい取得方法というのが無いような気がします。

要はブラウザでシークレットアクセスで検索した時の順位がプログラムから取得できればいいんですが、Googleの検索結果ページというのは例外的に「検索エンジンからどう見えるか?」というのを無視した作りになっており(自分自身が世界一の検索エンジンだから)、超速度重視のページ構造になっています。

seleniumやcapybara-webkitやphantomjsでスクレイプするスクリプトを書いたとしてもクラス名がgとか_Rmなんでxpathやcss selectorがすぐ変わりそうで信用できません。

そこでプラグラムから取得する真っ当な方法はGoogle Custom Search APIを使って取ることだと思います。(これが本当にシークレットアクセスでブラウザから取った時と全く同じかどうかはわかりませんが、自分の実用上は誤差の範囲のように思います)

Custom Search APIは無料枠が1日100リクエストかつ1リクエスト辺り10件まで取得可能で100位までなので、1日1回だけ調べるとすると最悪10キーワードまでしか無料でできないことになります。

しかし有料といっても大した金額にはならないですし、Google検索結果は重要なデータなので怖話のダッシュボードを作るときにこのCustom Search APIを使いました。

gem作った

ただ、GoogleのAPIは扱いが面倒なので検索順位が簡単に取れるgemを作りました。

komagata/google-search_rank

$ gem install google-search_rank
client = Google::SearchRank.new(api_key: "xxxx", cse_id: "xxxx")
client.find("怖い話", %r{http://kowabana.jp/.*}) # => 3

怖話は「怖い話」で検索すると今は3番目に出てくるので3が取得できます。

Google Cloud Platform

Google Custom Search APIで検索するにはAPI KeyとCSE ID(CustomSearchEngine ID)が必要です。Google Developers Consoleから下記の要領でProjectとCustom Search Engineを作成してKeyとIDをゲットしてください。

Custom Search APIを有効にする。

公開APIのサーバーキーを作成する。

カスタム検索エンジンを作成し、カスタム検索エンジンID(CSE ID)を取得する。

Google Cloud Platformはちょっと取っ付きづらいですが、Googleの全てのAPIを統一的に扱うことができるので一度慣れれば凄く便利です。

APIを検索するAPIがあって、そこでAPIのエンドポイントを取ってきてから使うみたいな感じになっています。

認証も課金もGoogle関係の全てのサービスが共通のAPIで使えるのは超汎用的ですが、昔の個別のAPIからマイグレーションをする必要が発生した人にとってはとても煩雑に見えることでしょう。

毎回ゲストとペアプロする画面を公開するペアプロキャストの2回目の後編を公開しました。

@kjirouがドライバー、@komagataがナビゲーターでkowabana.jp(rails)をペアプロしています。rails4.1でdeprecatedになった機能を外していくという非常に地味な内容になっています。

railsでkowabana.jpを開発 - ペアプロキャストep2後編@kjirou - YouTube

railsでkowabana.jpを開発 - ペアプロキャストep2後編@kjirou - ニコニコ動画:GINZA

flunkとか使ってます?ニコ動コメント等でフィードバックいただけるとありがたいです。

ペアプロキャスト - YouTube再生リスト

ペアプロキャスト - ニコニコ動画マイリスト

有料化どうこう以前にピンチ。Herokuが6月16日でbambooスタックの全dynoを停止するそうです。

未だにbambooスタックで動いてたアプリなんてレガシーに決まってるので、普通にcedar-14にするとruby 2.0.0になって動かない。

cedar-14で対応してる最も古いrubyは1.9.3-p551だそうなのでGemfileに明示的に書けばなるべく穏便に移行できます。

source 'https://rubygems.org'
ruby '1.9.3'

Heroku Ruby Support | Heroku Dev Center

Lokkaで沢山作っていたブログなども移行出来てホッとしました。

一時期は乱立したgemのgeneratorをbundle gemがほぼ統一。travisのファイルが入ってたり、Code of Conductが入ったり、rspecかminitestか選べたりといろいろ新しくなってました。

% bundle gem google-search_rank
Creating gem 'google-search_rank'...
Do you want to include a code of conduct in gems you generate?
Codes of conduct can increase contributions to your project by contributors who prefer collaborative, safe spaces. You can read more about the code of conduct at contributor-covenat.org. Having a code of conduct means agreeing to the responsibility of enforcing it, so be sure that you are prepared to do that. For suggestions about how to enforce codes of conuct, see bit.ly/coc-enforcement. y/(n): y
Do you want to license your code permissively under the MIT license?
This means that any other developer or company will be legally allowed to use your code for free as long as they admit you created it. You can read more about the MIT license at choosealicense.com/licenses/mit. y/(n): y
Do you want to generate tests with your gem?
Type 'rspec' or 'minitest' to generate those test files now and in the future. rspec/minitest/(none): minitest
      create  google-search_rank/Gemfile
      create  google-search_rank/.gitignore
      create  google-search_rank/lib/google/search_rank.rb
      create  google-search_rank/lib/google/search_rank/version.rb
      create  google-search_rank/google-search_rank.gemspec
      create  google-search_rank/Rakefile
      create  google-search_rank/README.md
      create  google-search_rank/bin/console
      create  google-search_rank/bin/setup
      create  google-search_rank/CODE_OF_CONDUCT.md
      create  google-search_rank/LICENSE.txt
      create  google-search_rank/.travis.yml
      create  google-search_rank/test/minitest_helper.rb
      create  google-search_rank/test/test_google/search_rank.rb
Initializing git repo in /Users/komagata/code/google-search_rank

一回選択したら設定ファイルに書かれるみたいです。

% cat ~/.bundle/config 
---
BUNDLE_GEM__COC: true
BUNDLE_GEM__MIT: true
BUNDLE_GEM__TEST: minitest

もちろん僕はminitestちゃん!

Ruby OpenSSL ホスト名検証の脆弱性が修正されているそうです。

$ CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline`" rbenv install 2.2.2

現時点の最新版であるRails4.2.1以下MySQLデフォルトだと絵文字が保存できません。コンシューマー向けサービスのコメント欄など今どきは普通に絵文字を入力されるのですぐに問題になります。(Incorrect string valueエラーになる)

実直な対応方法はmysqlでutf8ではなくutf8mb4を使うというものです。4byteのunicodeも保存できるようになるので絵文字も問題無しです。絵文字の種類が増えても問題無いでしょう。

ActiveRecordをutf8mb4で動かす - Qiita

穏便な解決方法

rails + mysqlデフォで動かないのと、一部のカラムでだけ対応したいこと、全テーブルのインデックスが長くなるとパフォーマンスに影響でそう、mysqlが古いと対応してない、など後ろ向きの理由があって、怖話ではDBに格納するときだけhuman friendlyな文字に変換し、出すときに戻すという実装にしました。

前向きの理由としては、画像への変換と組み合わせて怖話独自の絵文字を追加し易いという点があります。(LINEスタンプ的なのやりたかった)

実装

class Comment
  def body=(text)
    write_attribute(:body, Rumoji.encode(text))
  end
    
  def body
    text = read_attribute(:body)    
    Rumoji.decode(text) if text.present?
  end
end
mysql> select body from comments order by id desc limit 1;
+-----------------------------------------+
| body                                    |
+-----------------------------------------+
| テスト:poop::thumbsup::musical_note:    |
+-----------------------------------------+
1 row in set (0.00 sec)

rumojiはまさにそのために作られたgemでとっても簡単です。

絵文字共通化問題

非対応プラットフォームでも表示できるよう、画像に変換するというのはまた別のお話・・・。

カラー絵文字ライセンス問題 - komagata

Initial content

$ CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline`" rbenv install 2.2.1

debianだと2.1.2から2.2.1にアップデートするのに必要なpackageにlibffi-devが増えてるので注意。

定期購読しているWeb+DB Press vol.82 ”切りひらくRuby”を読んで知りました。(俺はタバコ吸わないので仕事の休憩時は適当に置いてある雑誌を読む)

今はbrewで入るみたい。rbenvとruby-buildに依存してるからこれからrbenv入れる時はこっちを入れれば一発で全部入りますな。

$ brew install rbenv-default-gems
$ vi ~/.rbenv/default-gems
bundler
rbenv-rehash

中身はbash scriptで俺の知らないテクがたくさんあってよくわかんなかった。