LoginSignup
1
1

More than 3 years have passed since last update.

Rails6 のちょい足しな新機能を試す 121(PostgreSQL index_exists?編)

Posted at

はじめに

Rails 6 に追加された新機能を試す第121段。 今回は、PostgreSQL index_exists? 編です。
Rails 6 (と Rails 5.2.4.1) では、 index_exists? が正しく動作しないバグが fix されています。

Ruby 2.6.5, Rails 6.0.2.1, Rails 5.2.4.1, Rails 5.2.3, PostgreSQL 12.0 で確認しました。 (Rails 6.0.0 でこの修正が入っています。)

$ rails --version
Rails 6.0.2.1

今回は、 name の属性を持つ User モデルを作り、インデックスを追加して確認してみます。

Rails プロジェクトを作る

Rails プロジェクトを新たに作成します。

$ rails new rails_sandbox
$ cd rails_sandbox

User モデルを作る

name 属性を持つ User モデルを作ります。

$ bin/rails g model User name

インデックスを追加する

今回は2つのインデックスを作成します。 lower(name) を指定したインデックスと、単純に name カラムを指定したインデックスです。

bin/rails g migration add_index_lower_name_to_users
db/migrate/20200207213234_add_index_lower_name_to_users.rb
class AddIndexLowerNameToUsers < ActiveRecord::Migration[6.0]
  def change
    add_index :users, 'lower(name)', name: 'index_lower_name'
    add_index :users, 'name', name: 'index_name'
  end
end

マイグレーションを実行する

マイグレーションを実行します。

bin/rails db:create db:migrate

rails console で確認する

rails c を実行します。

$ bin/rails c
Running via Spring preloader in process 344
Loading development environment (Rails 6.0.2.1)

indexes で登録されているインデックスを調べてみましょう。
(わかりやすいように表示は折り返してます。)

irb(main):001:0> User.connection.indexes(:users)
=> [
#<ActiveRecord::ConnectionAdapters::IndexDefinition:0x00005617bc6ef580 
@table=:users, 
@name="index_lower_name", 
@unique=false, 
@columns="lower((name)::text)",  # <=  ここに注目
@lengths={}, 
@orders={}, 
@opclasses={}, 
@where=nil, 
@type=nil, 
@using=:btree, 
@comment=nil>, 
#<ActiveRecord::ConnectionAdapters::IndexDefinition:0x00005617bc8c3be0 
@table=:users, 
@name="index_name", 
@unique=false, 
@columns=["name"],  # <= ここに注目
@lengths={}, 
@orders={}, 
@opclasses={}, 
@where=nil, 
@type=nil, 
@using=:btree, 
@comment=nil>
]

index_lower_name に対応する @columns'lower((name)::text)' で String であるのに対して、 index_name に対応する @columns["name"] とArray になっていることに注意してください。

index_exists? を使って index_name が存在することを確認します。

irb(main):002:0> User.connection.index_exists?(:users, "name", name: :index_name)
=> true

今度は、 index_lower_name が存在することを確認します。

irb(main):003:0> User.connection.index_exists?(:users, "lower((name)::text)", name: :index_lower_name)
=> true

Rails 5 では

Rails 5.2.4.1 では、 Rails 6 と同じ動作ですが、 Rails 5.2.3 では、 index_lower_name の存在を確認したとき false を返します。

irb(main):001:0> User.connection.index_exists?(:users, "name", name: :index_name)
=> true
irb(main):002:0> User.connection.index_exists?(:users, "lower((name)::text)", name: :index_lower_name)
=> false

試したソース

参考情報

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1