ActiveRecord::Base.connection#table_exists? と ActiveRecord::Base#table_exists? の違い
イントロ
似ているメソッドで、微妙に挙動が異なり、ちょっとハマったのでメモ
違い
引数、結果をキャッシュするかどうかが違う
引数
ActiveRecord::Base.connection#table_exists?
- 引数を一つ取る
ActiveRecord::Base.connection.table_exists?("users") #=> 引数で受け取ったテーブルが存在していれば true, なかったら false
ActiveRecord::Base.table_exists?
- 引数を取らない
class User < ActiveRecord::Base end user = User.first user.class.table_exists? #=> モデルに対応したテーブルが存在していれば true, なかったら false
キャッシュするかどうか
ActiveRecord::Base.connection#table_exists?
- キャッシュしない
- 毎回 database とやり取りして、テーブルが存在するかどうかを確認するメソッド
ActiveRecord::Base.connection.table_exists?('users') #=> true ActiveRecord::Base.connection.drop_table('users') ActiveRecord::Base.connection.table_exists?('users') #=> false
ActiveRecord::Base.table_exists?
- 一度呼びだされたらキャッシュされる
- キャッシュ先は
ActiveRecord::Base.connection
- キャッシュ先は
- 一度呼びだされたらキャッシュされる
user = User.first user.class.table_exists? #=> true ActiveRecord::Base.connection.drop_table('users') user.class.table_exists? # => true # DROP TABLE `users` したのに true が返る! ActiveRecord::Base.connection.schema_cache.table_exists?('users') # => true # # * `ActiveRecord::ConnectionAdapters::SchemaCache` によってメソッド呼び出し結果が保存されている。 # * `ActiveRecord::ConnectionAdapters::SchemaCache` インスタンスは `ActiveRecord::Base.connection` のインスタンスが保持している
結論
上にも書いたとおり、引数と、メソッド呼び出しの結果をキャッシュするかどうかが違う。
ActiveRecord::Base.table_exists?
は通常ActiveRecord::Base
継承したモデル(例だとUser
)が対象となるので、引数を取らない- また、table の存在判定は、一般的には変更されにくい値であるので、一度
table_exits?
を呼び出したらキャッシュされる
と覚えれば良い。
私は動的テーブルを作ったり消したりしていてハマってしまいました。
ActiveRecord を使って、頻繁にテーブルを作成したり削除したりする場合は注意が必要。かも。