@kyanny's blog

My thoughts, my life. Views/opinions are my own.

サムライズムで RubyMine のパーソナルライセンスを買った

PayPal 払いを選んだらクレジットカード払いよりも三百円くらい高くなってしまった(どうでもいい)

仕事で使うソフトウェアのライセンスは会社の経費で買ってもらえることになっており、実際にそうやって JetBrains 製品を使っている同僚もいる。参考: Quipperで働く環境・制度について - Quipper プロダクトチームのブログ

だけどあえて自腹で買った。理由はいくつかある。

まず、自分は自腹を切ったほうが「ちゃんと元をとろう」という意識が働いて、モノを活用するタイプである。逆にいうと、会社の経費で買ったモノや他人からもらったモノは、「タダで手に入れた」という意識が抜けず、真面目に活用しないことが多々あった。なので、経費で落としたけど結局使わず無駄になった、となるおそれがある。それは避けたかった。

次に、やや感傷的な話だが、自分は「キーボードは鞍である」という Happy Hacking Keyboard にまつわる談話や、「一つのエディタを熟知すること」という達人プログラマーの教えに共感している。そういう話の根底には、自分が使う道具は自分の意志で選び、使うものである、という考え方、思想があると思う。であれば、(ここちょっと考えが飛躍していると自覚あるが)自分で RubyMine を使うと決めたのであれば、経費で落ちようが落ちまいがライセンスは買うわけだ。そこに、わずかばかりであっても、「もし経費で落ちなかったらライセンスは買わないし、 RubyMine を使わない」という可能性があってはならないだろう、と思うのだ。仕事でどのエディタを使うかは 100% 自分の考えで決めたい。自分がコントロールできない何かに影響を受けないために、自分のお金で買う、ということだ。

最後に、これまた感傷的な話だが、ソフトウェアを作って生計を立てている身として、良いソフトウェアにちゃんとお金が支払われるサイクルが回ることを応援したい、というのもある。寄付とかではなく、ちゃんと持続性があるビジネスとしてソフトウェアの販売が成立するのはとても良いことだと思うので、個人としてそれをサポートしているよ、という意思表明をしたかった。まぁ実際にはコマーシャルライセンスのほうが JetBrains の売上は多いわけで、これでは言ってることとやってることが矛盾しているよなと自分でも思うのだが(もっといえば、自腹でコマーシャルライセンスを買えば落とす金額を多くできるじゃん、なんでそうしないの、って話にもなっちゃうのだが)、たぶん言いたいことは伝わるだろうと信じたい。

11月9日に RubyMine を 30 日間のフリートライアルとして使いはじめて程なくして、今回はライセンスを買うところまでいきそうだなぁという手応えはあった。なので、 JetBrains 本家から購入するか、日本代理店のサムライズムから購入するかで迷っていたが、 RubyMine を利用中にポップアップで出てきたアンケートに「代理店から買うと何か違いがあるの?」と聞いてみたら、

Samuraism

It's an official reseller so there is no difference (apart from the possibility to talk in Japanese and pay in Yen).

とのことだったので一安心。それでもなお公式から買っても良かったのだが、さっきの「お金の流れに貢献したい」のと同じ考えから、日本でそういうビジネスをやっていることを応援する意味を込めて代理店で買うことにした。正直なところ、ライセンス形態についての日本語の FAQ を用意してくれているのは有り難いし(英語でも読めなくはないし、当初は公式から買うつもりだったのでライセンス形態についても英語の説明を読んで把握していたが)、 Twitter などオンラインコミュニティの場で質問に答えたり、日本人向けに日本語で情報発信してくれたりしているのも評価できる。彼らがそういった活動をできるのも、代理店を経由して製品を買うユーザーがいて売上と利益がでてこそだと思うし、代理店という形で「良いソフトウェアを軸としたビジネスが成り立つ」というサイクルも応援したかった。なんかこれも書いててずいぶんまとまりがない感じがしているけど、言わんとすることは伝わると思いたい。

そんなことを書いてたらさっそくライセンスが発行された。 RubyMine を使い始めるタイミングで JetBrains アカウントを作っておいたようで、すでにサインイン済みだったので、メールに記載のアクティベート用のリンクを踏んだらすぐにアカウントにライセンスが追加された。 RubyMine の Welcome to RubyMine のウィンドウから、右下の Configure -> Manage License... を開いて JetBrains アカウントでログインしたらアクティベートされた。

f:id:a666666:20161204020524p:plain

MongoMapper で one association を持つモデルを STI するときは one association を :foreign_key オプション付きで再定義する

以下のようなモデルを定義して、 User を継承した WrapUser のインスタンスが one アソシエーションのメソッド呼び出しをすると関連モデルではなく nil が返る、というので少しハマった。

class User
  include MongoMapper::Document
  one :membership
end

class Membership
  include MongoMapper::Document
  belongs_to :user
end

class WrapUser < User
end

悪い実装のサンプルコードと実行結果: https://gist.github.com/kyanny/cb3cfb759dd0fc8c0ec8e0ad175bfd47

MongoMapper のソースのあちこちに byebug を仕込んだりしたが、 MongoDB のクエリのログを見れば一目瞭然で、 Single Table Inheritance するとインスタンスのクラス名が変わるので、 MongoMapper が内部で MongoDB の find クエリを組み立てる際の条件に使われるキー名も変わってしまう。

testing['memberships'].find({:wrap_user_id=>BSON::ObjectId('583c72606200b03f8b000001')}).limit(-1)

今回の例でいうと、 wrap_user_id というキーはどこにも定義されておらず、コレクション内のドキュメントもこのキーを持っていないので、このクエリにマッチするドキュメントは無く、結果として nil が返る。

これに対処するには、 one アソシエーションの定義時に :foreign_key オプションを付けて、誤った外部キー名が自動生成されないようにすればよい。

class WrapUser < User
  one :membership, foreign_key: :user_id
end

正しい実装のサンプルコードと実行結果: https://gist.github.com/kyanny/42d961b252a5f1aca797f8482d959ca5

クエリはこうなる testing['memberships'].find({:user_id=>BSON::ObjectId('583c72996200b0416a000001')}).limit(-1)

差分はこれだけ。 gist.github.com


特定の条件を満たしたときだけ MongoMapper なモデルに MixIn されるモジュールがあって、それに対するユニットテストの実装に問題があった。テストスイートの実行中、ターゲットのモデルは MixIn されていない綺麗な状態を保ちたいので、ターゲットのモデルを継承したモデルをテストスクリプトの中で定義し、そのモデルのインスタンスに対して MixIn が提供するインスタンスメソッドのユニットテストを書いていた。その中で one アソシエーションの関連先モデルを呼び出すコードを実行したら、 nil で落ちてしまった、というのがことの発端だった。上に書いたのと同じ処置を施したら nil で落ちなくなった。

げんしけん(21)

アフタヌーンの連載で読んでいたけどまぁ買った。内容はすでに気が済むまで読んでいたのでさらっと。四コマとオマケ漫画もこれといって特に何かある感じでもなく、不完全燃焼というか、むしろとっくに燃え尽きてて灰しかないというか。おれが三十代のうちに「三代目」を読みたいような、もういいような。

げんしけん(21) (アフタヌーンコミックス)

げんしけん(21) (アフタヌーンコミックス)

Gmail で GitHub の通知メールのパーマリンクをキーボードから開く Chrome 拡張

GitHub の通知を Gmail で読んでいると、view it on GitHub というリンクをクリックして URL を開くことがしばしばある。キーボード操作で完結したくなったので、 Chrome 拡張を作った。

github.com

2017/10/13 更新 Chrome 拡張ではなく Tampermonkey Script で書き直して Greasy Fork で公開した

https://greasyfork.org/ja/scripts/34099-open-github-url-for-gmail

使い方

1. Gmail Labs から「カスタム キーボード ショートカット」を有効にする

f:id:a666666:20161123211140p:plain

2. 「[移動] メニューを開く」のキーボードショートカットを v 以外のキーに変更する

f:id:a666666:20161123211239p:plain

3. Gmail で GitHub からの通知メールのスレッドを開いた状態で v キーを押す

すると画面内で最初に見つかった view it on GitHub なリンクを別タブで開く。 View it on GitHub でも ok (大文字小文字を区別しない)

スレッドが長くなって view it on GitHub が Gmail の画面上で折りたたまれていても、展開不要で開いてくれるので便利。

f:id:a666666:20161123211915p:plain

皆さん GitHub の未読消化にはたぶん Jasper を使っているんだろうけど、 Gmail 派の方はぜひご利用ください。