あなたの知ってるRubyGemsTips で LT してきた

あなたの知ってるRubyGemsTips で LT してきました。
LT よかったよー、と言ってもらえたのでよかったよかった。

printf デバッグが捗る gem をつくった話

2年ぐらい前に binding-debug という gem をつくったんですが、最近いろいろと機能拡張したのでそれの紹介をしてきました。
以前は

require "binding/debug"

using BindingDebug

value = 42
binding.p "value"
# => value : 42

みたいに binding.p に文字列を渡して使うようになっていたんですが、いまは Ruby の闇の力を使い以下のように書くことができます。
以下、README にかかれているサンプル。

require "binding/debug"

using BindingDebug

def plus a, b
  a + b
end

foo = "homu"

# puts with blocks
puts {
  foo.to_s.upcase
  plus 1, 2
  (0..20).to_a
  foo.class.name
}
# output:
# foo.to_s.upcase : HOMU
# plus 1, 2 : 3
# (0..20).to_a : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
# foo.class.name : String

今回は5分の LT でユースケースや使い方ぐらいしか話せなかったんですが、機会があれば実装方法なんかも話してみたいですねー。
ご飯も美味しかったですし、運営の方々ありがとうございましたー。

JavaScript で全角スペースはホワイトスペースとして扱われる

JavaScript で全角スペースを書いた場合、ホワイトスペースとして扱われます。知らなかった…。
なので次のように全角スペースが含まれているコードでも実行する事ができます。

if ( true ) {
  console.log("hoge");
}

うーん…便利…なのか?

参照

Ruby でクラス名と同名のメソッドを定義する

Ruby ではクラスと同じ名前のメソッドを定義する事ができます。

class X
end

def X(a = nil)
  "X(#{a})"
end

# 何もつけなかった場合はクラスを参照
p X       # => X
# メソッドぽい呼び出しであればメソッドを参照
p X()     # => "X()"
p X 42    # => "X(42)"

この手のやつでよく利用されているのは Kernel.#Array メソッドや Kernel.#Integer メソッドですねー。

Array(arg) もクラスではなくてメソッドを呼び出しています。

Ruby の private メソッドを特定のコンテキストで public にする

Ruby では次のように private メソッドにすると『レシーバをつけたメソッド呼び出し』ができません。

class X
  private

  def value
    42
  end
end

x = X.new

# error: private method `value' called for #<X:0x00007fabe905fa40> (NoMethodError)
x.value

こういうときに refinements を使うと任意のコンテキストでのみ public 化することができます。

class X
  private

  def value
    42
  end
end

x = X.new
# error
# x.value

# refinements を使って public 化する
using Module.new {
  refine X do
    public :value
  end
}

# OK
x.value

べんり。

Ruby で任意の定数を参照した際に警告が出るようにする

Ruby で任意の定数を参照した際に警告が出るようにしたい場合、 Module#deprecate_constant を利用することができます。

class X
  Hoge = 42
end

# no warning
X::Hoge

# X::Hoge を参照すると警告を出すようにする
X.deprecate_constant :Hoge

# warning: constant X::Hoge is deprecated
X::Hoge

こんなのが標準ライブラリにあるんですねー。 使う機会があれば使ってみたい。

Omotesando.rb #54 で『ActiveRecord のコードを読んでみる』をしてきた

Omotesando.rb #54 で LT してきました。
今回は「コードの読み方」というテーマだったせいかいつもよりもめっちゃ人が集まっていましたねー。人が多いけど懇親会でぼっちだったワイ
やっぱり「コードの読み方」っていうのは初心者から上級者まで興味があるテーマになるんですかねー。

ActiveRecord のコードを読んでみる

ActiveRecord のコードを読んでみる』ってことでスライドは使用する機能の説明だけ書いて実際にいつもどんな感じで ActiveRecord の実装を読んでいるのかのデモをしてきました。
pデバッグ出力したり grep で検索したり binding.irb を駆使したりと割と泥臭い機能を使ってコード読んでいます。
このあたり、使っているエディタによって結構違ってて RubyMine とかは高級な機能を使って便利そうにデバッグしていました。
最近 Vim の拡張はサボり気味なので Vim でもいろいろとやってみたいんですけどねえ…。
あ、あとわたしは binding.pry ではなくて binding.irb を使っているんですが『なんで binding.pry じゃないんですか』って何人かに聞かれました。
わたしも昔は binding.pry 使っていたんですが Railsbinding.pry を使うと変なところで止まっちゃうことが多くで確実に動作する binding.irb を使うようになりました。
binding.pry よりも高級ではないんですがより安定性があるから使っているって感じですねー Ruby 2.7 からは irb のかなり強化されているのでこれからに期待しています!!!

irb で実行結果を pp で出力する

irb で実行結果を pp で出力する手段がいくつかあるのでまとめ。

irb の起動オプションで変更する

irb の起動オプションに --inspect pp を追加することで pp の出力になります。

$ irb --inspect pp
irb(main):001:0> (1..10).to_h { |it| [it, it] }
 = > {1=>1,
 2=>2,
 3=>3,
 4=>4,
 5=>5,
 6=>6,
 7=>7,
 8=>8,
 9=>9,
 10=>10}

irb の起動中に変更する

conf.inspect_mode = :pp を実行することで以降の出力が pp になります。

$ irb
irb(main):001:0> conf.inspect_mode = :pp
irb(main):002:0> (1..10).to_h { |it| [it, it] }
 = > {1=>1,
 2=>2,
 3=>3,
 4=>4,
 5=>5,
 6=>6,
 7=>7,
 8=>8,
 9=>9,
 10=>10}

.irbrc で設定する場合

.irbrc ファイルで制御する場合、以下の設定を追加することで pp で出力できます。

# .irbrc
IRB.conf[:INSPECT_MODE] = :pp

pp 以外にも yamlmarshal 形式で出力することもできるので気になる人は調べてみるといいと思います。

参照