DB に NOT NULL と一意性の制約が不足

こんにちは、

モデルには存在するが、データベースには欠けているいくつかのバリデーションや制約について報告したいと考えています。

欠けている NOT NULL 制約

PostDetail - key, value はモデル上では必須ですが、データベースでは NULL 許容となっています。

  1. モデルで必須 (app/models/post_detail.rb):

    validates_presence_of   :key, :value
    

    …しかしデータベースでは NULL 許容

    discourse_development=# \d post_details
                                            Table "public.post_details"
       Column   |            Type             | Collation | Nullable |                 Default
    ------------+-----------------------------+-----------+----------+------------------------------------------
     ...
     key        | character varying           |           |          |
     value      | character varying           |           |          |
    

    もしデータベースに NOT NULL 制約を追加した場合でも、空文字列が通過する可能性は残りますが、少なくとも NOT NULL を設定しておくことで多少は安全になると思います。

欠けている一意性制約

  1. TagGroup - name。モデル内で一意 (app/models/tag_group.rb)

    validates_uniqueness_of :name, case_sensitive: false
    

    しかしデータベースに一意インデックスが欠落

    discourse_development=# \d tag_groups
    ...
    Indexes:
        "tag_groups_pkey" PRIMARY KEY, btree (id)
    
  2. 同じく、WatchedWord - word。(app/models/watched_word.rb)

    validates :word,   presence: true, uniqueness: true, length: { maximum: 50 }
    

    データベースには (action, word) に対しては一意インデックスがありますが、(word) 単独ではありません:

    discourse_development=# \d watched_words
    ...
    Indexes:
        "watched_words_pkey" PRIMARY KEY, btree (id)
        "index_watched_words_on_action_and_word" UNIQUE, btree (action, word)
    
  3. 最後に、WebHookEventType - name。(app/models/web_hook_event_type.rb):

    validates :name, presence: true, uniqueness: true
    

    データベースに一意制約が欠落:

    discourse_development=# \d web_hook_event_types
    ...
    Indexes:
        "web_hook_event_types_pkey" PRIMARY KEY, btree (id)
    

    これらが妥当かどうか確認していただけると幸いです。これらがバグの発生を未然に防ぐのに役立つ可能性があります。また、もしそうであれば、修正は比較的 straightforward であると思われますので、必要であればプルリクエストを作成することも喜んで行います。

ありがとうございます。

大文字小文字を区別しない一意制約は少し厄介です。このために citext 拡張機能を追加するのは気が引けますし、その場合、インデックスを追加するために name_lower というカラムを複製して作成する必要があります。

はい、これは修正すべきですね。

ここにもインデックスを追加するのは問題ありません。