railsのプルリクを読んでみた(#24203)


## はじめに
この記事は今の自分がrailsのプルリクを見た時にどう読むかをまとめたものであるので
効率のいい読み方であるとは限りません。
なんかいい方法あったら教えてほしいです。

この記事は、2017年09月24日に書きました。

結論が知りたい方は[まとめ](#まとめ)を見て下さい。

<br>

## [#24203](https://github.com/rails/rails/pull/24203)はどのようなプルリクか

deliveryのidが1〜2のものが何個あるかを取得するメソッド `num_deliveries_1_2` を
 `select` でなくて `count` で呼びたいというもの

```diff
class Order < ActiveRecord::Base
	has_many :deliveries
	
	def num_deliveries_1_2
-		deliveries.select { |delivery| delivery.id.in?(1..2) }.size
+		deliveries.count { |delivery| delivery.id.in?(1..2) }
	end
end
```

[参考]

> ActiveRecord::Relation#countの修正: 従来は引数にブロックを渡すとエラーなしで無視されたが、RubyのEnumerable#countでレコード数をカウントするようになった 
[rails 5.1.0から出来るようになった](https://railsguides.jp/5_1_release_notes.html#active-record)


[注意]
一部(ActiveRecord::Associations::CollectionProxy Class)がこのプルリクで書き換わっている
[Remove unnecessary `count` method for collection proxy](https://github.com/rails/rails/commit/8ad03c97da0c84b9e96587ea22e9a4a0e107b3c1#diff-bee622c17de67f292adf310f75288e25L765)

<br>

## 動作確認用のrubyスクリプト

まず動作確認用のrubyスクリプト(24203.rb)を作ります。
使うgem(特にrials)に `binding.pry` を使ったりしたいのでGemfileでgemを管理することにします。
railsのバージョンは5.1.0にします。
`bundle && ruby 24203.rb` してエラーが起きないことを確認します。

```zsh
$ touch 24203.rb
$ bundle init
$ bundle install --path=vendor/bundle
$ $ tree -L 2 
.
├── .bundle
│   └── config
├── 24203.rb
├── Gemfile
├── Gemfile.lock
└── vendor
    └── bundle
```

`Gemfile`と`24203.rb`は以下のようになります。


```Gemfile
# frozen_string_literal: true
source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem "rails", "5.1.0"
gem "arel", "~> 8.0"
gem "sqlite3"
gem "pry"

```

```24203.rb
require 'bundler'
Bundler.require

require "active_record"
require "minitest/autorun"
require "logger"

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :orders, force: true do |t|
  end

  create_table :deliveries, force: true do |t|
    t.integer 'order_id'
  end
end

class Order < ActiveRecord::Base
  has_many :deliveries

  def num_deliveries_1_2
    deliveries.count do |delivery|
      delivery.id.in?(1..2)
    end
  end
end

class Delivery < ActiveRecord::Base
end

# 適当にモデルを作成する
@o = Order.create
3.times { @o.deliveries.create }
p @o.num_deliveries_1_2 # 2
```

<br>

## 準備(大事)
以下の機能が使えるとソースコドリーディングがしやすくなるかもです。

#### 1. cool-peco (シェルはzshである必要がある)
シェルをbashでなくzshにしてcool-pecoをいれておくと便利です。
[cool-peco](https://qiita.com/ryoppy/items/4819d0911bf937dba821)

#### 2. bundle cd
Gemfileでいれたgemにbundle cdします。頻繁にrailsに`binding.pry`するのであったがいいです。
[Gemfileでいれたgemにbundle cdする](https://qiita.com/yuku_t/items/78107016af9eb78d5804)

#### 3. ff (シェルがzshが必要である必要がある)
findで`git grep`みたいにファイルを検索できるようにする機能。
Gemfileでいれたgemなので`git grep`が使えないので必要です。
ffは適当に名前つけた。使うにはcool-pecoが必要。
EDITORは自分が使っているエディタに書き換えてください。

```~/.zshrc
# pecoでfind
export EDITOR=subl
function peco-find-grep() {
  local res
  local base=$(find -type f | xargs grep -n $1 | peco)
  local file=$(echo $base | awk -F: '{print $1}')
  local file_index=$(echo $base | awk -F: '{print $2}')
  if [ -n "$file" ]; then
    res="$EDITOR $file:$file_index"
  fi

  _cool-peco-insert-command-line $res
}
alias ff=peco-find-grep
```

#### 4. extended_moduels
extendしたmoduleを表示できるようにするメソッドをModuleクラスに生やす。
[gistで見つけたました。](# https://gist.github.com/adzap/158109)`24203.rb`にこんな感じで書きます。

```diff
class Delivery < ActiveRecord::Base
end

+# https://gist.github.com/adzap/158109
+class Module
+  def extended_modules
+    # this exposes the metaclass and for any code inside, +self is scoped to the metaclass
+    class << self
+      self.included_modules
+    end
+  end
+end
```

さぁ、いよいよ始めていきましょう。


<br>

## deliveries.count { |delivery|　delivery.id.in?(1..2) }の理解

結果的に理解するべきものは以下の項目である。


|No.|項目|内容|
|---|---|----|
|1|deliveries.count|[active_record/relations/caluculations.rb(モジュール)](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/relation/calculations.rb#L39-L42)|
|2|ActiveRecord::Base#count|[ActiveRecord::Querying(モジュール)](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/querying.rb#L13)|
|3|delegate :count, to: :all|[Module(クラス)](https://github.com/rails/rails/blob/5-1-stable/activesupport/lib/active_support/core_ext/module/delegation.rb#L155-L217)|
|4|all.count(*args, &block)||
|5|Enumerable.count(*args, &block)|[rubyのEnumerableモジュール](https://ref.xaio.jp/ruby/classes/enumerable/count)|
|6|ActiveRecord::Base#all|[ ActiveRecord::Scoping::Named::ClassMethods(モジュール)](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/scoping/named.rb#L24-L30)|
|7|ActiveRecord::Base#default_scoped|[ ActiveRecord::Scoping::Named::ClassMethods(モジュール)](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/scoping/named.rb#L42-L44)|
|8|ActiveRecord::Base#relation|[ ActiveRecord::Core::ClassMethods(モジュール)](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/core.rb#L307-L315)|


適当な所で `binding.pry` して調べる。
だが、適当に `binding.pry` すると理解するまでに時間がかかってしまう。
ではどうすればいいのか？

## binding.pryを効果的にかける方法
「`binding.pry` を掛けて何がしたいか？」
それは `deliveries.count`の詳細をみるためである。そのため、①Order#num_deliveriesの内部で一箇所まずかけている。
私は`binding.pry`の他に`$binding_pry=true`というグローバル変数を定義した。これをどう使うのかというと、`@o.deliveries`が定義されたあとの`rails`のコードに`binding.pry`を掛けるために使うのである。
こんな感じに使う。

```
def hoge
	binding.pry if $binding_pry
end
```

```diff
class Order < ActiveRecord::Base
  has_many :deliveries

  def num_deliveries_1_2
+   binding.pry
    deliveries.count do |delivery|
      delivery.id.in?(1..2)
    end
  end
end

class Delivery < ActiveRecord::Base
end

# 適当にモデルを作成する
@o = Order.create
10.times { @o.deliveries.create }
+ $binding_pry = true
p @o.num_deliveries_1_2 # 2
```

<br>

## 1. [deliveries.count](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/relation/calculations.rb#L39-L42)
```
[2] pry(main)> $ @o.deliveries.count

From: ./vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/relation/calculations.rb @ line 39:
Owner: ActiveRecord::Calculations
Visibility: public
Number of lines: 5

def count(column_name = nil)
  return super() if block_given?
  calculate(:count, column_name)
end
[3] pry(main)> 
```

`active_record/relation/calculations.rb`に定義してあるとある。ここで私が見るべきポイントは２つで

>
1. 何かインスタンス変数に対してメソッドが呼ばれているか？
2. superでメソッドが呼ばれているか？

1か２かの場合は、このファイルに直接 `binding.pry if $binding_pry` を書いて、superが何かなどを調べるようにしている。
[gemにbinding.pryする便利な方法がある]()

実際に `binding.pry if $binding_pry` して止めると以下のようになる。

```ruby
From: ./vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/relation/calculations.rb @ line 40 ActiveRecord::Calculations#count:

    39: def count(column_name = nil)
 => 40:   binding.pry if $binding_pry
    41:   return super() if block_given?
    42:   calculate(:count, column_name)
    43: end

[14] pry(#<Delivery::ActiveRecord_Associations_CollectionProxy>)> self.class.ancestors.select { |a| a.class==Class }
=> [
Delivery(id: integer, order_id: integer), 
ActiveRecord::Base, 
Object, 
BasicObject
] # 見やすいように表示を加工している
[15] pry(#<Delivery::ActiveRecord_Associations_CollectionProxy>)>
[4] pry(#<Delivery::ActiveRecord_Associations_CollectionProxy>)> self.superclass
=> ActiveRecord::Base
```

`self.ancestors.select { |a| a.class==Class }` は selfの先祖でクラスのものを調べている。[super()](https://docs.ruby-lang.org/ja/latest/doc/spec=2fcall.html)は `ActiveRecord::Base` クラスに定義して有りそうだ。(前提知識としてActiveRecord::Baseクラスを継承したクラスでcountクラス・メソッドを呼べることを知ってたら想像がつく。)

<br>

## 2. [ActiveRecord::Base#count](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/querying.rb#L13)
pryに続きで以下のようにすると定義が得られる。

```ruby
[4] pry(#<Delivery::ActiveRecord_Associations_CollectionProxy>)> cd ActiveRecord::Base
[5] pry(ActiveRecord::Base):1> $ count

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/querying.rb @ line 16:
Owner: ActiveRecord::Querying
Visibility: public
Number of lines: 1

delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all

```

`all`?ってなるかもしれないがこれもpryで調べれば良い。
だがそれは一旦置いといて`delegate :count, to: :all`が何かを調べないと答えにはたどり着かない。

## 3. [delegate :count, to: :all](https://github.com/rails/rails/blob/5-1-stable/activesupport/lib/active_support/core_ext/module/delegation.rb#L155-L217)
以下のように調べれば良い。

```
[8] pry(ActiveRecord::Base):1> $ delegate

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activesupport-5.1.0/lib/active_support/core_ext/module/delegation.rb @ line 156:
Owner: Module
Visibility: public
Number of lines: 65

  def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
    unless to
      raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter)."
    end

    if prefix == true && /^[^a-z_]/.match?(to)
      raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
    end

    method_prefix = \
      if prefix
        "#{prefix == true ? to : prefix}_"
      else
        ""
      end

    location = caller_locations(1, 1).first
    file, line = location.path, location.lineno

    to = to.to_s
    to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)

    methods.each do |method|
      # Attribute writer methods only accept one argument. Makes sure []=
      # methods still accept two arguments.
      definition = /[^\]]=$/.match?(method) ? "arg" : "*args, &block"

      # The following generated method calls the target exactly once, storing
      # the returned value in a dummy variable.
      #
      # Reason is twofold: On one hand doing less calls is in general better.
      # On the other hand it could be that the target has side-effects,
      # whereas conceptually, from the user point of view, the delegator should
      # be doing one call.
      if allow_nil
        method_def = [
          "def #{method_prefix}#{method}(#{definition})",
          "_ = #{to}",
          "if !_.nil? || nil.respond_to?(:#{method})",
          "  _.#{method}(#{definition})",
          "end",
        "end"
        ].join ";"
      else
        exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")

        method_def = [
          "def #{method_prefix}#{method}(#{definition})",
          " _ = #{to}",
          "  _.#{method}(#{definition})",
          "rescue NoMethodError => e",
          "  if _.nil? && e.name == :#{method}",
          "    #{exception}",
          "  else",
          "    raise",
          "  end",
          "end"
        ].join ";"
      end

      module_eval(method_def, file, line)
    end
  end
```

最後の `module_eval(method_def, file, line)` が全てである。
このメソッドはrailsが読み込まれる際に実行される。
さて、実際に`delegate :count, to: :all` されると何が実行されるのか
見てみよう。

<br>

## 4. delegate :count, to: :all　を追う。
```diff
+ require 'pry'
def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
#
# 省略
#
+      binding.pry if file.match?(/querying/) && method_def.match?(/def count/)

      module_eval(method_def, file, line)
    end
  end
```

`delegate :count, to: :all`は`ActiveRecord::Querying`モジュールで定義されているので`file.match?(/querying/)`。見たいメソッドは、
`def count; #省略 end;`なので`method_def.match?(/def count/)`
である。

さて、この状態で実行し直してみよう。
binding.pryで止めた場所でmethod_defを実行しております。

```ruby
From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activesupport-5.1.0/lib/active_support/core_ext/module/delegation.rb @ line 216 Module#delegate:

    211:           "  end",
    212:           "end"
    213:         ].join ";"
    214:       end
    215: 
 => 216:       binding.pry if file.match?(/querying/) && method_def.match?(/def count/)
    217: 
    218:       module_eval(method_def, file, line)
    219:     end
    220:   end
    221: 

[1] pry(ActiveRecord::Querying)> method_def
=> "def count(*args, &block); _ = all;  _.count(*args, &block);rescue NoMethodError => e;  if _.nil? && e.name == :count;    raise DelegationError, \"ActiveRecord::Querying#count delegated to all.count, but all is nil: \#{self.inspect}\";  else;    raise;  end;end"
[2] pry(ActiveRecord::Querying)>

```

`method_def`がActiveRecord::Baseに動的に定義されるクラス・メソッドcountになる。文字列なので適当なファイルに書き出してみると、

```ruby
def count(*args, &block)
	_ = all
	_.count(*args, &block)
rescue NoMethodError => e
	if _.nil? && e.name == :count
		raise DelegationError, \"ActiveRecord::Querying#count delegated to all.count, but all is nil: \#{self.inspect}\"
	else
		raise
	end
end
```

`delegate :count, to: :all`によってなされることは、
ActiveRecord::Baseを継承したクラスでcountを呼ぶと、
`all.count(*args, &block)` が呼ばれることになる。

`all.count(*args, &block)`を実施に呼び出すとどうなるのか
次に見ていく。

<br>

## 5. all.count(*args, &block)
`all.count(*args, &block)`のcountメソッドは`ActiveRecord::Calculations` に定義してあるが既に見ているように
このメソッドの中にはsuper()がある。

```ruby
From: ./vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/relation/calculations.rb @ line 39:
Owner: ActiveRecord::Calculations
Visibility: public
Number of lines: 5

def count(column_name = nil)
  return super() if block_given?
  calculate(:count, column_name)
end
```


このsuper()が何を呼び出すのかというと[rubyで定義してあるEnumerable.count(*args, &block)を呼び出す](https://ref.xaio.jp/ruby/classes/enumerable/count)のである。
なぜなら先祖が以下のようになっているからである。
名前からある程度想像出来るが、実際Enumerableのやつが呼ばれているのを調べる

```ruby
[4] pry(Delivery)> all.class.ancestors
[1] pry(Delivery)> 
=> [Delivery::ActiveRecord_Relation,
 ActiveRecord::Delegation::ClassSpecificRelation,
 ActiveRecord::Relation,
 ActiveRecord::FinderMethods,
 ActiveRecord::Calculations,
 ActiveRecord::SpawnMethods,
 ActiveRecord::QueryMethods,
 ActiveModel::ForbiddenAttributesProtection,
 ActiveRecord::Batches,
 ActiveRecord::Explain,
 ActiveRecord::Delegation,
 Enumerable,
 ActiveSupport::ToJsonWithActiveSupportEncoder,
 Object,
 ActiveSupport::Dependencies::Loadable,
 Minitest::Expectations,
 JSON::Ext::Generator::GeneratorMethods::Object,
 ActiveSupport::Tryable,
 PP::ObjectMixin,
 Kernel,
 BasicObject]
```

先祖は上のようなのでcountが定義してあるかどうかは

```zsh
ff 'module Calculations'
ff 'module SpawnMethods'
ff 'module QueryMethods'
ff 'module ForbiddenAttributesProtection'
ff 'module Batches'
ff 'module Explain'
ff 'module Delegation'
ff 'module Enumerable'
```  

としていってファイルを開いて`def count`があるかどうかを調べれば良い。

<br>

最後に、allが何なのかを調べて終わることにする。
結論的には、`relation`。ActiveRecord::Relationクラスのインスタンスになる。この場合だと、

```ruby
[1] pry(Delivery)> relation
D, [2017-09-24T20:53:54.096435 #29138] DEBUG -- :   Delivery Load (0.2ms)  SELECT "deliveries".* FROM "deliveries"
=> [#<Delivery:0x007fa6934699c0 id: 1, order_id: 1>,
 #<Delivery:0x007fa693469858 id: 2, order_id: 1>,
 #<Delivery:0x007fa693469718 id: 3, order_id: 1>]
[2] pry(Delivery)> relation.class
=> Delivery::ActiveRecord_Relation

```

<br>

## 6. [ActiveRecord::Base.all](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/scoping/named.rb#L24-L30)
```ruby
[6] pry(ActiveRecord::Base):1> $ all

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/scoping/named.rb @ line 24:
Owner: ActiveRecord::Scoping::Named::ClassMethods
Visibility: public
Number of lines: 7

def all
  if current_scope
    current_scope.clone
  else
    default_scoped
  end
end

```

次は `current_scope` と `default_scoped` を調べる必要がありそうだ。
今現在の状況でどっちの場合が実行されているかを調べるために、 `binding.pry if $binding_pry` を挟む

```diff
def all
  if current_scope
+   binding.pry if $binding_pry
    current_scope.clone
  else
+   binding.pry if $binding_pry
    default_scoped
  end
end
```

すると以下のようになるので `default_scoped` を調べれば良さそうだ。

```zsh
[6] pry(#<Delivery::ActiveRecord_Associations_CollectionProxy>)>

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/scoping/named.rb @ line 29 ActiveRecord::Scoping::Named::ClassMethods#all:

    24: def all
    25:   if current_scope
    26:     binding.pry if $binding_pry
    27:     current_scope.clone
    28:   else
 => 29:     binding.pry if $binding_pry
    30:     default_scoped
    31:   end
    32: end

[1] pry(Delivery)>
```

<br>

## 7. [ActiveRecord::Base#default_scoped](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/scoping/named.rb#L42-L44)

```ruby
[1] pry(Delivery)> $ default_scoped

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/scoping/named.rb @ line 34:
Owner: ActiveRecord::Scoping::Named::ClassMethods
Visibility: public
Number of lines: 9

def default_scoped # :nodoc:
  scope = build_default_scope

  if scope
    relation.spawn.merge!(scope)
  else
    relation
  end
end

```

`build_default_scope`のT/Fによって処理がわかれるので、
`binding.pry if $binding_pry`を挟む必要がある。

```diff
def default_scoped # :nodoc:
  scope = build_default_scope

  if scope
+   binding.pry if $binding_pry
    relation.spawn.merge!(scope)
  else
+   binding.pry if $binding_pry
    relation
  end
end

```

再度、実行し直すと

```ruby
[1] pry(Delivery)> 

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/scoping/named.rb @ line 41 ActiveRecord::Scoping::Named::ClassMethods#default_scoped:

    34: def default_scoped # :nodoc:
    35:   scope = build_default_scope
    36: 
    37:   if scope
    38:     binding.pry if $binding_pry
    39:     relation.spawn.merge!(scope)
    40:   else
 => 41:     binding.pry if $binding_pry
    42:     relation
    43:   end
    44: end
```

`relation` が何かわかれば良さそうだ。

<br>

## 8. [ActiveRecord::Base#relation](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/scoping/named.rb#L42-L44)

```ruby
[2] pry(Delivery)> $ relation

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/core.rb @ line 307:
Owner: ActiveRecord::Core::ClassMethods
Visibility: private
Number of lines: 9

def relation
  relation = Relation.create(self, arel_table, predicate_builder)

  if finder_needs_type_condition? && !ignore_default_scope?
    relation.where(type_condition).create_with(inheritance_column.to_s => sti_name)
  else
    relation
  end
end
[3] pry(Delivery)> 
```

if文があるから、`binding.pry if bindig.pry` を描いて調べてみる

```diff
def relation
  relation = Relation.create(self, arel_table, predicate_builder)

  if finder_needs_type_condition? && !ignore_default_scope?
+  binding.pry if $binding_pry
    relation.where(type_condition).create_with(inheritance_column.to_s => sti_name)
  else
+	 binding.pry
    relation
  end
end
```

再度実行しなおす。

```ruby
From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/core.rb @ line 314 ActiveRecord::Core::ClassMethods#relation:

    307: def relation
    308:   relation = Relation.create(self, arel_table, predicate_builder)
    309: 
    310:   if finder_needs_type_condition? && !ignore_default_scope?
    311:     binding.pry if $binding_pry
    312:     relation.where(type_condition).create_with(inheritance_column.to_s => sti_name)
    313:   else
 => 314:     binding.pry if $binding_pry
    315:     relation
    316:   end
    317: end
```

単純に`relation`であるとわかる。

## 9. [ActiveRecord::Relationのインスタンスrelation](https://github.com/rails/rails/blob/5-1-stable/activerecord/lib/active_record/relation.rb)
`relation`はActiveRecord::Relationのインスタンスである。
何故ならば、

```ruby
[3] pry(Delivery)> $ relation

From: /Users/fukudayukihiro/RubymineProjects/rails-issue/vendor/bundle/ruby/2.4.0/gems/activerecord-5.1.0/lib/active_record/relation.rb @ line 3:
Class name: ActiveRecord::Relation
Number of lines: 701

** Warning: Cannot find code for ActiveRecord::Relation. Showing superclass ActiveRecord::Relation instead. **

class Relation
  MULTI_VALUE_METHODS  = [:includes, :eager_load, :preload, :select, :group,
                          :order, :joins, :left_joins, :left_outer_joins, :references,
                          :extending, :unscope]

  SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
:...skipping...
```

`$ relation`したらRelationクラスが引っかかるからである。
実際に実行してみても

```ruby
[10] pry(Delivery)> relation.class.ancestors.select{|a| a.class==Class}
=> [
Delivery::ActiveRecord_Relation, 
ActiveRecord::Relation, 
Object, 
BasicObject
]
```

ちなみに実態は、

```
[5] pry(Delivery)> relation
=> [#<Delivery:0x007fa6934699c0 id: 1, order_id: 1>,
 #<Delivery:0x007fa693469858 id: 2, order_id: 1>,
 #<Delivery:0x007fa693469718 id: 3, order_id: 1>]
[6] pry(Delivery)> 
```

となる。

<br>

## まとめ

最後にまとめておく。

deliveries.count { |delivery| delivery.id.in?(1..2) }
↓
[ActiveRecord::Calculationsモジュール]()のcount
↓
block_given?=trueなのでsuper()が呼ばれる
↓
deliveries.superclass=ActiveRecord::Base
↓
ActiveRecord::Base.countが呼ばれる
↓
delegate :count, to: :allに定義してある
↓
delegateが実行してあるのは、[Moduleクラス]()
↓
ActiveRecord::Base.countの実態は以下のようになる。

```ruby
def count(*args, &block)
	_ = all
	_.count(*args, &block)
rescue NoMethodError => e
	if _.nil? && e.name == :count
		raise DelegationError, \"ActiveRecord::Querying#count delegated to all.count, but all is nil: \#{self.inspect}\"
	else
		raise
	end
end
```

↓
all.count(*args, &blcok)が呼ばれる
↓
all.class.ancestorsは

```ruby
 [Delivery::ActiveRecord_Relation,
 ActiveRecord::Delegation::ClassSpecificRelation,
 ActiveRecord::Relation,
 ActiveRecord::FinderMethods,
 ActiveRecord::Calculations,
 ActiveRecord::SpawnMethods,
 ActiveRecord::QueryMethods,
 ActiveModel::ForbiddenAttributesProtection,
 ActiveRecord::Batches,
 ActiveRecord::Explain,
 ActiveRecord::Delegation,
 Enumerable,
 ActiveSupport::ToJsonWithActiveSupportEncoder,
 Object,
 ActiveSupport::Dependencies::Loadable,
 Minitest::Expectations,
 JSON::Ext::Generator::GeneratorMethods::Object,
 ActiveSupport::Tryable,
 PP::ObjectMixin,
 Kernel,
 BasicObject]
```

↓
[ActiveRecord::Calculationsモジュール]()のcountが呼ばれる
↓
block_given?=trueなのでsuper()が呼ばれる
↓
[rubyのEnumerableのモジュール]()のcountが呼ばれる。

以上。

## 最後に
手を動かしながらやったほうが理解が深まると思います。