Railsのscopeを読む

Railsのscopeのソースコードを読んでいきます。

```
u = User.new(name: 'sample name')
```

scopeを読んでいくために、上記のようなオブジェクトをサンプルとして作成します。

```ruby
    1: class User < ApplicationRecord
    2: 
    3: binding.pry
 => 4:   scope :recent, -> { order(id: :desc).limit(5) }
    5: end
```

中を読んでいきます。

```ruby

    165:         # We are able to call the methods like this:
    166:         #
    167:         #   Article.published.featured.latest_article
    168:         #   Article.featured.titles
    169:         def scope(name, body, &block)
 => 170:           unless body.respond_to?(:call)
    171:             raise ArgumentError, "The scope body needs to be callable."
    172:           end
    173: 
    174:           if dangerous_class_method?(name)
    175:             raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
```

bodyがcallを呼べなかったら、例外を返す。
今はbodyがcallを呼べるので次へ。

``` ruby
    169:         def scope(name, body, &block)
    170:           unless body.respond_to?(:call)
    171:             raise ArgumentError, "The scope body needs to be callable."
    172:           end
    173: 
 => 174:           if dangerous_class_method?(name)
    175:             raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
    176:               "on the model \"#{self.name}\", but Active Record already defined " \
    177:               "a class method with the same name."
    178:           end
    179: 
```

nameがクラスメソッドとして定義されていないか判定。
今は定義されていないので次へ。

``` ruby
    175:             raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
    176:               "on the model \"#{self.name}\", but Active Record already defined " \
    177:               "a class method with the same name."
    178:           end
    179: 
 => 180:           if method_defined_within?(name, Relation)
    181:             raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
    182:               "on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
    183:               "an instance method with the same name."
    184:           end
    185: 
```

nameがインスタンスメソッドとして定義されていないか判定。
今は定義されていないので次へ。

``` ruby
    181:             raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
    182:               "on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
    183:               "an instance method with the same name."
    184:           end
    185: 
 => 186:           valid_scope_name?(name)
    187:           extension = Module.new(&block) if block
    188: 
    189:           if body.respond_to?(:to_proc)
    190:             singleton_class.define_method(name) do |*args|
    191:               scope = all._exec_scope(name, *args, &body)
```

scopeの名前として有効かどうか判定する。nameがメソッドとして定義されていないので、次へ。

``` ruby
    182:               "on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
    183:               "an instance method with the same name."
    184:           end
    185: 
    186:           valid_scope_name?(name)
 => 187:           extension = Module.new(&block) if block
    188: 
    189:           if body.respond_to?(:to_proc)
    190:             singleton_class.define_method(name) do |*args|
    191:               scope = all._exec_scope(name, *args, &body)
    192:               scope = scope.extending(extension) if extension
```

blockが存在しているなら、blockを引数としたてModuleを新しく作る。今回はblockが存在しないので、次へ。

``` ruby
    184:           end
    185: 
    186:           valid_scope_name?(name)
    187:           extension = Module.new(&block) if block
    188: 
 => 189:           if body.respond_to?(:to_proc)
    190:             singleton_class.define_method(name) do |*args|
    191:               scope = all._exec_scope(name, *args, &body)
    192:               scope = scope.extending(extension) if extension
    193:               scope
    194:             end
```

bodyがto_procメソッドをを呼べるか判定。呼べるので、if分の中へ。

```ruby
    185: 
    186:           valid_scope_name?(name)
    187:           extension = Module.new(&block) if block
    188: 
    189:           if body.respond_to?(:to_proc)
 => 190:             singleton_class.define_method(name) do |*args|
    191:               scope = all._exec_scope(name, *args, &body)
    192:               scope = scope.extending(extension) if extension
    193:               scope
    194:             end
    195:           else
```

bodyで与えられた処理を実装する、nameというクラスメソッドを定義する。

```ruby
    198:               scope = scope.extending(extension) if extension
    199:               scope
    200:             end
    201:           end
    202: 
 => 203:           generate_relation_method(name)
    204:         end
```