Ruby でメソッドの定義元をシュッと調べる

デバッグなどしている時に Rails の実装を読みたい!、ということはよくあると思うんですが、そういう時にシュッと定義元を開きたいですよね。
優秀な IDE とかだとそういう機能もあるかもしれませんが、irb や pry を実行している時にサクッと調べたいですよね。

Method#source_location を使う

そういうときには Method#source_location を利用する事が出来ます。

# まず #method で Method のインスタンスを取得して、#source_location を呼び出す
User.method(:pluck).source_location
# => ["~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.0/lib/active_record/querying.rb", 16]

こんな感じでどのファイルの何行目で定義されているメソッドなのかを取得する事が出来ます。
Ruby に組み込まれているメソッドなので Rails のように闇の深いライブラリでもだいたい定義場所を調べることが出来ます。

注意

Method#source_location ですが、Ruby のコードの定義場所を調べることは出来ますが、C拡張で実装されているメソッドの場合は nil を返すので、標準ライブラリを調べる場合は注意しましょう。

[].method(:===).source_location
# => nil

[CombNaf x 学生LT] 第12回 学生エンジニアLT大会!!!で LT してきた

してきました。
相変わらず学生ではないんですが、遠目で見ていたりします。
今回は普段の学生LT とは違い CombNaf という別のコミュニティと合同で開催されました。
そのため、参加者が多かったり、普段の学生LT とは結構雰囲気が違っていたような感じでしたね。

Ruboty で Discord-Bot をつくろう

チョット前に Ruboty を使って Discord-Bot をつくろうとしていたのでその LT をしてきました。
LT と言ってもデモとかやってたらガッツリ時間食っていたんですが()。
やっぱり Ruboty 便利ですね。
こういう Bot がサクッとつくれるのがよきよき。
今回は参加者も多かったので Twitter とかでの反応も多くよかったです。
やはりレスポンスがあるとモチベーションがあがりますね。
あとやっぱり全体的に Ruby 使っている人が少なかったのでもっとこういうのを広めて行きたい気持ち。

補足

デモで使用していたお天気 bot ですが、各種 API のキーを設定しないと使えないので使いたい方がいれば注意してください。

Vim 8.1 がリリース!!

朝起きたら Vim 8.1 がリリースされていました。
Vim 8.0 のリリースが 2016/09/12 なので約1年8ヶ月ぶりとなるリリースです。
大きな追加点としてはやはり :terminal が実装されたことですかね。
わたしは :terminal はクソだと思っているんですが、リリースされたのでもう1度試してみようかなあ…。

3,4月で気になった Ruby のパッチ、提案

書こう書こうと思っていて結局書いてなかったシリーズ。
とりあえず、現状まとめていたやつだけ放出。

Feature #14579: Hash value omission - Ruby trunk - Ruby Issue Tracking System

JavaScript みたいに Hash を定義する時に『値を省略してキーだけ渡して Hash を定義する』みたいな記法の提案。
これ、JavaScript を書いていた時に結構多用していたので Ruby にもめっちゃほしかったんですが、Reject されてしまった模様…。

Feature #14473: Add Range#subrange? - Ruby trunk - Ruby Issue Tracking System

任意の Range が任意の Range の範囲内かどうかを判定するメソッドの提案。
あれば便利そう。

Feature #4824: Provide method Kernel#executed? - Ruby trunk - Ruby Issue Tracking System

Ruby だと『実行したファイルがコマンドラインから呼ばれたかどうか』を判定する場合に

if __FILE__ == $0
  my_main()          # call any method or execute any code
end

みたいに書くんですが、この __FILE__ == $0 をメソッド化してわかりやすくしたいよねーみたいな提案。
かなり前から議論されているんですが、いいメソッド名がないらしくてまだ決まってない模様。

Feature #14585: Array#each_pair - Ruby trunk - Ruby Issue Tracking System

ほしいのはわかるけど名前がいまいち。

Feature #14593: Add Enumerator#concat - Ruby trunk - Ruby Issue Tracking System

今までなんでなかったのか理由が気になる。

Feature #14594: Rethink yield_self's name - Ruby trunk - Ruby Issue Tracking System

yield_self の別名を考える、ということで色々と議論されていたみたいですが、ほぼほぼ then に決まったぽい。

Feature #14022: String#surround - Ruby trunk - Ruby Issue Tracking System

これ、稀によく欲しくなるのでちょっと期待していたんですが、Reject されてしまった模様。

Feature #13383: [PATCH] Module#source_location - Ruby trunk - Ruby Issue Tracking System

Module#source_location の提案 文字通りクラスの定義場所を取得するメソッドだけど、Ruby の場合はオープンクラスをいろんな場所で呼び出す事が出来るので複数ヶ所を取得する必要があって止まってるみたい。
ただ、最後の定義場所を取得できるだけでも便利そう

Feature #14197: Enumerable#{select,reject accept a pattern argument - Ruby trunk - Ruby Issue Tracking System}

collection.reject(/re/) みたいに『#reject にも値を渡したいよねー』という提案。
まあわからなくはない。

第9回 学生エンジニア限定LT大会!!!でスライドの作り方の LT してきた

もう1週間以上も経ってしまいましたが第9回 学生エンジニア限定LT大会!!!に遊びに行ってきました。
自分でブログ書けと言って書いてなかった 今回は寿司とピザを食べることが出来たぞ!!!

[reveal.js + markdown でスライドをつくろう!!]

と、言うことでわたしもスライドをつくる時に利用している reveal.js の紹介なんかをしてきました。
markdown でスライドを書くことが出来るのでそんなに凝らないスライドだとサクッと書くことが出来るのでかなり重宝しています。
スライドにも載せていますがここにテンプレートを用意していたりするので気になる人は使ってみるとよいと思います。
使い方はここ ってか、最近学生じゃないのに学生LT関連でLTしまくっとるな…。

C++ で std::tuple を使ってバージョン番号を比較する

元ネタ:C++ バージョン番号を比較する方法 - イネマルのプログラミング備忘録

#include <tuple>
#include <iostream>

int
main(){
    // 適当なバージョンデータ
    auto appA = std::tuple{ 2, 0, 101, 2 };
    auto appB = std::tuple{ 2, 0, 100, 3 };
    // C++11 で使いたいなら std::make_tuple を使う
//     auto appA = std::make_tuple(2, 0, 101, 2);
//     auto appB = std::make_tuple(2, 0, 100, 3);

    // 比較(appA < appB)
    bool result = appA < appB;

    // 結果
    if (result) {
        std::cout << "appAの方が古い" << std::endl;
    }
    else {
        std::cout << "appBの方が古い" << std::endl;
    }

    return 0;
}
/*
output:
appBの方が古い
*/

こういう場合は std::tuple 便利だよね!!!といいたかっただけの記事。

参照

1,2月で気になった Ruby のパッチ、提案

去年、Ruby のパッチを書き始めた頃から開発者向けの ML に参加しているんですが、その中で面白そうなパッチや提案が結構目に付くので定期的にまとめてみようかと。

Feature #13784: Add Enumerable#filter as an alias of Enumerable#select - Ruby trunk - Ruby Issue Tracking System

Enumerable#filterEnumerable#select の alias にする提案。 提案自体は去年されていたんですが、最近取り込まれました。 先日リリースされた Ruby 2.6 preview 版にもすでに実装されています。 確かに名前は filter の方が直感的だと思うんですが、これにより find_allselectfilter と同等のメソッドが3つ存在することに…。

Feature #14371: New option "recursive: true"; for Hash#transform_keys! - Ruby trunk - Ruby Issue Tracking System

Ruby 2.5 で追加された Hash#transform_keys!再帰的に適用させたい、みたいな提案だったんですが、残念ながら reject されました。 これに関しては matz がコメントしているのでそっちを参照してください。

Feature #14390: UnboundMethod#to_proc - Ruby trunk - Ruby Issue Tracking System

UnboundMethod#to_proc を追加して、第一引数をレシーバとして扱うような提案…かな? 多分以下のような挙動を想定。

to_s = Integer.instance_method(:to_s)

# 従来の使い方
p to_s.bind(42).call 2
# => "101010"

# 提案された使い方
# 第一引数を bind する
p to_s.to_proc.call 42, 2
# => "101010"

確かにこれがあるといろいろとできそうな気がする。

Feature #13581: Syntax sugar for method reference - CommonRuby - Ruby Issue Tracking System

これ、スレッド内でかなり議論されているんですが、やりたいことは単純で X.method(:hoge)シンタックスシュガーがほしいという要求です。 わたしもこれがめちゃくちゃ欲しいんですが、どういうシンタックスシュガーがいいのか…。 あと instance_methodシンタックスシュガーがほしい〜〜〜〜〜〜。

Feature #5120: String#split needs to be logical - Ruby trunk - Ruby Issue Tracking System

これもかなり昔から提案されていたみたいなんですが、最近ちょっと話題になって正式に reject されました。 確かに "".split('') # => [''] になったほうが自然な気がしますが、まあいまから仕様を変えるのも大変そう。

Feature #14498: Class#to_proc - Ruby trunk - Ruby Issue Tracking System

Class#to_procClass#new を呼び出す提案。 ぱっとみ便利そうなんですが、to_proc を潰すのはもったいないので、これぐらいなら Dog.method(:new) 使えばいいかなーという感じ。 可読性の観点からもよくないということで reject されています。