旧それなりブログの跡地、画像やスタイルやJSなどが壊れてることがあります。

Railsでブロック内の変数はどこから来ているのか

2013年10月28日

突然生じているように見えるブロック内の変数が、
どこから来ているのかを調べました。

例えば、ActiveRecord のこういうコードや:

class Entry < ActiveRecord::Base
  scope :filter, -> {
    entries = arel_table
    where(:id, 1)
  }
end

RSpec のこういうコードで:

describe 'Foo' do
  it 'Bar' do
  end
end

突然出てくる where なり arel_table なり it なりは、
どこで定義されているのかということです。

"where" って、お前こそどっから来たんだよ!

ActiveRecord の方

クラス定義中のスコープである self 以下にあるものでした。

先の where(:id, 1) はこれらのように書いても一緒です:

self.where(:id, 1)
Entry.where(:id, 1)  

-> は lambda と等価ですが、
クラス定義中に lambda を定義した場合は、
クラス定義中のスコープである(省略されている)self も含めて、
束縛したクロージャになっているんですね。

だから where も arel_table も Entry クラスが元々持っている
全クラスメソッドをそのまま呼び出せるのでした。
(あ private の時はどうなるんだろ.. 今度調べる)

そもそも、クラス定義中はスコープが self になるのも知らなかったんですが
それについては以下を参考にしました。
クラス/メソッドの定義 – クラス定義

RSpec の方

これは多分、ブロックの引数で渡しているんだと思いますが..

https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/example_group.rb#L58
https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/example_group.rb#L86

詳しいことは読めていません..

メモ:スコープ内の変数・メソッドを探す方法

Ruby(Motion)でmethodsを使ってメソッド検索