Rails6 のちょい足しな新機能を試す72（enum _scopes 編）

 # はじめに

(多分）Rails 6 に追加された新機能を試す第72段。 今回は、 `enum _scopes` 編です。
Rails 6 では、 モデルで `enum` を使うときに scope を定義しないようにできるオプション `:_scopes` が追加されました。
Ruby 2.6.3, Rails 6.0.0.rc2 で確認しました。Rails 6.0.0.rc2 は `gem install rails -v 6.0.0rc2 --prerelease` でインストールできます。

（Rails6がリリースされましたが、動作確認当時は、Rails 6.0.0.rc2 が最新でした。悪しからず :bow: ）

```shell
$ rails --version
Rails 6.0.0.rc2
```

今回は、 Child モデルを作成して `rails console` を使って確認します。

# プロジェクトを作る

```shell
rails new rails_sandbox --database postgresql
cd rails_sandbox
```

# Child モデルを作る

name と generation の2つの属性をもつ Child モデルを作ります。
generation は enum にするため、 integer にします。

```shell
bin/rails g model Child name generation:integer
```

# enum を定義する

Child モデルに enum を定義します。

```ruby:app/models/child.rb
class Child < ApplicationRecord
  enum generation: %i[baby toddler preschool gradeschool teen young_adult]
end
```

# seed データを作成する

seed データを作成します。

```ruby:db/seeds.rb
Child.create(name: 'Andy', generation: :baby)
Child.create(name: 'Bob', generation: :toddler)
Child.create(name: 'Cindy', generation: :preschool)
```

# マイグレーションを実行し seed データを登録する

```shell
bin/rails db:create db:migrate db:seed
```

# rails console で確認する

`rails console` で確認します。

`Child.baby` を実行してみます。

```irb
irb(main):001:0> Child.baby
  Child Load (0.4ms)  SELECT "children".* FROM "children" WHERE "children"."generation" = $1 LIMIT $2  [["generation", 0], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Child id: 1, name: "Andy", generation: "baby", created_at: "2019-08-04 08:57:11", updated_at: "2019-08-04 08:57:11">]>
```

ちゃんと動作しています。
`Child.not_baby` を実行してみます。

```irb
irb(main):002:0> Child.not_baby
  Child Load (0.6ms)  SELECT "children".* FROM "children" WHERE "children"."generation" != $1 LIMIT $2  [["generation", 0], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Child id: 2, name: "Bob", generation: "toddler", created_at: "2019-08-04 08:57:11", updated_at: "2019-08-04 08:57:11">, #<Child id: 3, name: "Cindy", generation: "preschool", created_at: "2019-08-04 08:57:11", updated_at: "2019-08-04 08:57:11">]>
```

こちらもちゃんと動作しました。

# _scopes を使う

ここからが本番です。 Child モデルを変更して _scopes を使ってみます。

```ruby:app/models/child.rb
class Child < ApplicationRecord
  enum generation: %i[baby toddler preschool gradeschool teen young_adult], _scopes: false
end
```

# rails console で確認する

修正を反映させるため `reload!` します。

```irb
irb(main):003:0> reload!
Reloading...
=> true
```

`Child.baby`, `Child.not_baby` を試すと`NoMethodError` が発生します。

```irb
irb(main):004:0> Child.baby
Traceback (most recent call last):
        1: from (irb):4
NoMethodError (undefined method `baby' for #<Class:0x0000555a2cfb4808>)
irb(main):005:0> Child.not_baby
Traceback (most recent call last):
        2: from (irb):5
        1: from (irb):5:in `rescue in irb_binding'
NoMethodError (undefined method `not_baby' for #<Class:0x0000555a2cfb4808>)
```

# scope が定義されないが enum は使える

scope は定義されませんが、 それ以外の enum の機能は使えます。


Child オブジェクトの作成

```irb
irb(main):008:0> dave = Child.new(name: 'Dave', generation: :teen)
=> #<Child id: nil, name: "Dave", generation: "teen", created_at: nil, updated_at: nil>
```

`baby?` メソッド や `teen?` メソッド

```irb
irb(main):009:0> dave.baby?
=> false
irb(main):010:0> dave.teen?
=> true
```

データベースへの保存

```irb
irb(main):011:0> dave.save
   (0.2ms)  BEGIN
  Child Create (0.4ms)  INSERT INTO "children" ("name", "generation", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "Dave"], ["generation", 4], ["created_at", "2019-08-04 09:15:05.113455"], ["updated_at", "2019-08-04 09:15:05.113455"]]
   (7.1ms)  COMMIT
=> true
```

データベースから検索して、 dave の generation を確認

```irb
irb(main):012:0> dave = Child.last
  Child Load (0.6ms)  SELECT "children".* FROM "children" ORDER BY "children"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> #<Child id: 4, name: "Dave", generation: "teen", created_at: "2019-08-04 09:15:05", updated_at: "2019-08-04 09:15:05">
irb(main):013:0> dave.generation
=> "teen"
```

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try072_enum_disable_scopes


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [option to disable all scopes that `ActiveRecord.enum` generates](https://github.com/rails/rails/pull/34605)