redis-rb v5 での変更点

 [redis | RubyGems.org](https://rubygems.org/gems/redis?locale=ja) が 2022/08/29 に[5\.0\.0](https://rubygems.org/gems/redis/versions/5.0.0) になった。
[4\.8\.0](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md) から [5\.0\.0](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md) にアップデートしようとしたらいろいろエラーが出たので自分が踏んだ変更点をメモ。

## Redis.new の引数

`Redis.new` の引数は Hash を取るが、v4 まではキーは文字列でも、シンボルでもどちらでも良かったが、V5 ではシンボルのみになった。

redis-rb V4 までは次の様に文字列キーのハッシュでも初期化できた。
もちろんシンボルキーも使えた。
```ruby:redis-rb_V4
config = {  
  'host' => 'redis-host-name',  
  'port' => 6379,  
}

redis = Redis.new(config)
```

redis-rb V5 では次の様にシンボルキーで設定しないとエラーになるようになった。

```ruby:redis-rb_V5
config = {  
  host: 'redis-host-name',  
  port: 6379,  
}

redis = Redis.new(config)
```

文字列のキーで設定すると次のようなエラーが発生する。

```
unknown keywords: "host", "port" (ArgumentError)
```

V4 では[文字列キーをシンボルキーに置き換えるような実装](https://github.com/redis/redis-rb/blob/4.x/lib/redis/client.rb#L449-L450)しているのになんでなくしたのかな。

## ListとHashで値に設定できる型がチェックされるようになった

V5 では List と Hash では要素にセットできる値の型が制限されるようになった。

まずは List 。
redis-rb V4 までは次の様にどんな型でも特にエラーなく値を入れることができた。
```ruby:redis-rb_V4
redis = Redis.new(config)  
  
key = 'key-rpush'  
redis.del(key)  
redis.rpush(key, 'hello')  
redis.rpush(key, 100)  
redis.rpush(key, true) 
redis.rpush(key, nil)
redis.rpush(key, MyClass)  # クラスを入れようとしている
  
pp redis.lrange(key,0,-1)
=> ["hello", "100", "true", "", "MyClass"] # Redis から取り出すと結局全部文字列として取れる。
```

上記コードを redis-rb v5 で実装すると次のエラーが発生する。
```ruby
Unsupported command argument type: TrueClass (TypeError)
```
`true` をセットしようとしているのがダメ。

V4と同じ結果を得ようとすると次の様に数値か文字列として値をセットするようにする。

```ruby:redis-rb_V5
redis = Redis.new(config)  
  
key = 'key-rpush'  
redis.del(key)  
redis.rpush(key, 'hello')  
redis.rpush(key, 100)  
redis.rpush(key, 'true')  
redis.rpush(key, nil || '')  
redis.rpush(key, MyClass.to_s)  
  
pp redis.lrange(key,0,-1)
=> ["hello", "100", "true", "", "MyClass"]
```

[ソース](https://github.com/redis-rb/redis-client/blob/master/lib/redis_client/command_builder.rb#L28-L39)を見ると `String`, `Symbol`, `Integer`, `Float` 以外はエラーにしている。

Hash も同様。

V4 では次のコードを実行できる。
```ruby:redis-rb_V4
redis = Redis.new(config)  
key = 'key-hash'  
values = {  
  'field1' => 'string',  
  'field2' => 100,  
  'field3' => true,  
  'field4' => nil,  
  'field5' => MyClass,  
}  
redis.mapped_hmset(key, values)  
  
pp redis.hgetall(key)
=> {"field1"=>"string", "field2"=>"100", "field3"=>"true", "field4"=>"", "field5"=>"MyClass"}
```

V5 では上のコードのままだとListと[同じ箇所](https://github.com/redis-rb/redis-client/blob/master/lib/redis_client/command_builder.rb#L28-L39)でチェックされエラーになる。
同様の結果を得るには次のコードになる。

```ruby
redis = Redis.new(config)  
key = 'key-hash'  
values = {  # シンボルキーでも結果は同じ
  'field1' => 'string',  
  'field2' => 100,  
  'field3' => true.to_s,  
  'field4' => nil.to_s,  
  'field5' => MyClass.to_s,  
}  
redis.mapped_hmset(key, values)  
  
pp redis.hgetall(key)
=> {"field1"=>"string", "field2"=>"100", "field3"=>"true", "field5"=>"MyClass", "field4"=>""}
```

結局の所、値を `to_s` してやれば良いようだ。

## hiredis を利用するためのgemも変更されている。

hiredis ドライバーを利用する場合に必要なGemも変更されている。

redis-rb v4 の場合は次の様に [hiredis\-rb](https://github.com/redis/hiredis-rb) が必要だった。

```ruby:Gemfile
# for redis-rb V4
gem 'hiredis'  
gem 'redis', '4.8.0', :require => ['redis', 'redis/connection/hiredis']
```

redis-rb v5 では [hiredis\-client](https://github.com/redis-rb/redis-client/tree/master/hiredis-client) に変わった。

```ruby:Gemfile
gem 'hiredis-client'
gem 'redis', '5.0.5'  
```

いずれのバージョンでも gem を `require` した時点で、デフォルトの *driver* が `hiredis` となるのでわざわざ `Redis.new(driver: :hiredis)` と指定する必要はない。

## まとめ

- シンボルキーで設定する
- List、Hash の値は `to_s` する
- *hiredis* から *hiredis-client*