Rails6 のちょい足しな新機能を試す66（query with large number編）

# はじめに

Rails 6 に追加されそうな新機能を試す第66段。 今回は、 `query with large number` 編です。
Rails 6 では、 検索条件の値が Integer などの型の範囲外の値であっても検索できるようになりました。

Ruby 2.6.3, Rails 6.0.0.rc1, Rails 5.2.3 で確認しました。Rails 6.0.0.rc1 は `gem install rails --prerelease` でインストールできます。

(Rails 6.0.0 がリリースされましたが、確認当時は Rails 6.0.0.rc1 がリリースされた時でした。悪しからず。）

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

今回は、　User モデルに　`:bigint` を指定した `age` を追加して、 `age` の範囲外の値を検索条件にして検索してみます。

# プロジェクトを作る

```shell
rails new rails6_0_0rc1
cd rails6_0_0rc1
```

# model を作る

User モデルを作ります。
`name` の他に `:bigint` を指定した `age` を追加します。

```shell
bin/rails g model User name age:bigint
```

# seed データを作る

1件だけですが、 seed データを作成します。

```ruby:db/seeds.rb
User.create(name: 'Taro', age: 1)
```

# User モデルを修正する

User モデルに scope を5つ作ります。

ここで条件に age の値の範囲に含まれない大きな値と小さな値を指定します。

```ruby:app/models/user.rb
class User < ApplicationRecord
  LARGE = 9223372036854775808
  SMALL = -9223372036854775809
  scope :age_in_large, -> { where(age: [1..LARGE]) }
  scope :age_eq_large, -> { where(age: LARGE) }
  scope :age_not_eq_large, -> { where.not(age: LARGE) }
  scope :age_in_small, -> { where(age: [SMALL..1]) }
  scope :age_in_small_large, -> { where(age: [SMALL..LARGE]) }
end
```

# seed データを登録します。


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

# rails console で確認する

`rails console` で確認してみます。

```irb
irb(main):001:0> User.age_in_large
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."age" >= $1 LIMIT $2  [["age", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>
irb(main):002:0> User.age_eq_large
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE 1=0 LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):003:0> User.age_not_eq_large
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE 1=1 LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>
irb(main):004:0> User.age_in_small
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."age" <= $1 LIMIT $2  [["age", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>
irb(main):005:0> User.age_in_small_large
  User Load (0.8ms)  SELECT "users".* FROM "users" WHERE 1=1 LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Taro", age: 1, created_at: "2019-07-26 21:21:06", updated_at: "2019-07-26 21:21:06">]>
```

ここで、実際に発行されているSQLに注目してください。SQL自体には、 -9223372036854775809 や 9223372036854775808 は登場しません。
これは、 age の値として、 -9223372036854775809 や 9223372036854775808 は、あり得ない範囲外の値なので、検索条件に含まなくても良いためです。
工夫されてますね。 `User.age_not_eq_large` の条件の `where 1=1` など、なるほどと思ってしまいます。


# Rails 5では

検索条件の値が、 `age` の範囲に収まらないため、 RangeError になってしまいます。

```irb
irb(main):001:0> User.age_eq_large
Traceback (most recent call last):
ActiveModel::RangeError (9223372036854775808 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):002:0> User.age_not_eq_large
Traceback (most recent call last):
ActiveModel::RangeError (9223372036854775808 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):003:0> User.age_in_large
Traceback (most recent call last):
ActiveModel::RangeError (9223372036854775808 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):004:0> User.age_in_small
Traceback (most recent call last):
ActiveModel::RangeError (-9223372036854775809 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
irb(main):005:0> User.age_in_small_large
Traceback (most recent call last):
ActiveModel::RangeError (-9223372036854775809 is out of range for ActiveModel::Type::Integer with limit 8 bytes)
```

# 試したソース

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


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [All of queries should return correct result even if including large number](https://github.com/rails/rails/pull/30000)