koukiblog

たぶんweb系の話題

Rails5.1からidカラムがbigintになるのでその対応

Rails5.1からidカラムがbigintになるのでその対応メモ。
↓は対応した人のエントリです。bigintが必要になってから変更するのでは間に合わないので最初から設定しちゃおうみたいな感じですね。
Rails 5.1: Default Primary Keys Are Now BIGINT

このPR(Restore the behaviour of the compatibility layer for integer-like PKs by kamipo · Pull Request #27389 · rails/rails · GitHub) にもあるように互換性には気を使って開発してくれていますが、schema.rbは migrate:reset タスクを実施するなどして再生成する必要があるみたいです。

schema.rbが下記のようになっていたとして、

create_table "users" do |t|
  t.string   "name",       null: false

create_table "addresses" do |t|
  t.integer  "user_id"
  t.string   "name",       null: false

 add_foreign_key "addresses", "users"

5.0以前では問題なくテーブルの作成と外部キーの設定が行えていましたが、5.1ではエラーになります。
それはusers,addressテーブルのidカラムがbigintになりますが、外部キーを設定しようとしているaddressesテーブルのuser_idカラムはint, usersテーブルのidカラムはbigintと差異が出てしまうからです。
migrateファイルが正しく管理されている場合は、 migrate:resetタスクを実行することで、Rails5.1でも以前のDB定義を維持することができるschema.rbを出力することができます。

再生成すると以下のようになります。

create_table "users", id: :integer  do |t|
  t.string   "name",       null: false

create_table "addresses", id: :integer do |t|
  t.integer  "user_id"
  t.string   "name",       null: false

 add_foreign_key "addresses", "users"

id: :integerが各テーブルに付与され、エラーが解決されます。

schema.rbを以前のDB定義を維持できるように変更し、そのあとで、必要に応じて各テーブルのidカラムをbigintにしていくのが良いんじゃないかなーと思います。

pm2でhubotを起動するとき

pm2でhubotを起動する場合、

 pm2 start -f bin/hubot -x --name botname -- -a adapter

のように紹介されている記事が多かったのだけど、bin/hubotがJavascriptとして解釈されてしまいうまくいかない。

 pm2 start -f bin/hubot.sh -x --name botname -- -a adapter

としてみると、無事起動。

拡張子で判断しているみたいだったので、ソースを見てみるとそれっぽい記述を見つけたのでたぶんそうなんだと思う

https://github.com/Unitech/pm2/blob/1c3fcb83b65e430a5734d576610d27cc7a0bf4fd/lib/Common.js#L355

  var noInterpreter     = (!app.exec_interpreter || 'none' == app.exec_interpreter),
      extName           = path.extname(app.pm_exec_path),
      betterInterpreter = extItps[extName];

のextItpsはintpreter.jsonで定義されていて以下のような内容になっている
https://github.com/Unitech/pm2/blob/3f5641a67d13b746b861dd2a491206df2eb50cca/lib/API/interpreter.json

拡張子がshだとbashで解釈される。何もないとnodeになる様子。

sprockets-commonerについて

sprocket-commonerというgemがよい感じだったので調べてみました。

sprocket-commonerで何ができるのかは下記qiitaに詳しくかいてあって、僕もこの記事で知りました。
qiita.com

結局のところ
・ES6構文とmoduleのimport/export
・npmモジュール
の2つが使えればよいと思っていたので、ちょうどよい感じです。

sprocket-commonerがなにをやっているのかをざっと眺めてみました。

sprockets-commoner/commoner.rb at master · Shopify/sprockets-commoner · GitHub

module Sprockets
  module Commoner
    def self.sprockets4?
      @@sprockets4 ||= Gem::Version.new(Sprockets::VERSION) >= Gem::Version.new('4.0.0.beta')
    end
  end

  register_postprocessor 'application/javascript', ::Sprockets::Commoner::Processor
  register_transformer 'application/json', 'application/javascript', ::Sprockets::Commoner::JSONProcessor
  register_bundle_metadata_reducer 'application/javascript', :commoner_enabled, false, :|
  register_bundle_metadata_reducer 'application/javascript', :commoner_required, Set.new, :+
  register_bundle_metadata_reducer 'application/javascript', :commoner_used_helpers, Set.new, :+
  register_bundle_processor 'application/javascript', ::Sprockets::Commoner::Bundle
  register_dependency_resolver 'commoner-environment-variable' do |env, str|
    _, variable = str.split(':', 2)
    ENV[variable]
  end
end

Sprockets::Commner::Processor が何かやっていそうです

sprockets-commoner/processor.rb at master · Shopify/sprockets-commoner · GitHub

Schmooze::Baseというクラスを継承しているのですが、
Schmoozeというgemは何をやっているかというと
schmooze/base.rb at master · Shopify/schmooze · GitHub

      def spawn_process
        process_data = Open3.popen3(
          @_schmooze_env,
          'node',
          '-e',
          @_schmooze_code,
          chdir: @_schmooze_root
        )
        ensure_packages_are_initiated(*process_data)
        ObjectSpace.define_finalizer(self, self.class.send(:finalize, *process_data))
        @_schmooze_stdin, @_schmooze_stdout, @_schmooze_stderr, @_schmooze_process_thread = process_data
      end

となっていて、子プロセスでnodeを起動させてそこでJSを実行しているようです。

Sprocketのcompile時に子プロセスでnode.jsを起動して、JSをトランスコンパイルしています。
ExecJSへの依存はありません。

importの辺りはSprocket::Commonerr::Bundleとbabel-plugin-sprockets-commoner-internalで頑張っているみたい。


まとめ

  • Sprocketのcompile時に子プロセスでnode.jsを起動して、JSをトランスコンパイルしてる

 特別なことをせずにnpmモジュールが使える

  • ExecJSへの依存はない

逆にいうと、ExecJSではないので、rubyracerなどは使えない。
  ファイルずつnode起動していくので、パフォーマンスの懸念はあるみたいです。
github.com

  • coffeescriptのimportなど特別な機能を使わなければロックインされることはない

Rails5.1から、SprocketにES6、npmモジュールへの対応が入るし、Webpackerも出るので、5.1が出るまではsprocket-commoner、5.1がリリースされたらRailsデフォルトに戻るのがよいんじゃないかなーと思ってます。

sudoするとdocker-composeがcommand not found

現象:
docker-composeをインストールしているとき、sudo したときだけコマンドが見つからない。

原因:
visudo で編集できる secure_path に/usr/local/bin が含まれていない。
docker-composeは /usr/local/bin 配下にインストールされる

対応:

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

に/usr/local/binを追加

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/local/bin:/usr/bin

何回もやって都度忘れてたのでかいとく

ELB作成時にSSL証明書インストールでエラー

コンソールから

Failed to create load balancer: Server Certificate not found for the key: 

ELBの作成とSSL証明書のインストールを同時にはできないらしい。(コマンドからはできるっぽい?)
一度作成したあとにSSLの設定を追加すればok。

Go言語の関数とループ

A Tour of Goを進めてたのでその備忘


問題:
関数とループを使った簡単な練習として、 ニュートン法 を使った平方根の計算を実装してみましょう。

ニュートン法は、開始点 z を選び、以下の式を繰り返すことによって、 Sqrt(x) を近似します:

https://go-tour-jp.appspot.com/content/img/newton.png


最初は、その計算式を10回だけ繰り返し、 x を(1, 2, 3, ...)と様々な値に対する結果がどれだけ正解値に近づくかを確認してみてください。

次に、ループを回すときの直前に求めたzの値がこれ以上変化しなくなったとき (または、差がとても小さくなったとき)に停止するようにループを変更してみてください。 この変更により、ループ回数が多くなったか、少なくなったのか見てみてください。 math.Sqrt と比べてどれくらい近似できましたか?


回答:
gist.github.com