2

今後、すべての SQL テーブルの ID 値をランダム化するように依頼されました。その理由は、競合他社が ID 値の増加に基づいて Web サイトのトラフィックを推測できないようにするためです。

Rails のデフォルトでは、ID をインデックス、外部キー、および URL パスとして使用します。これらの ID は直線的に増加します。

今後、すべてのテーブルの ID として疑似乱数整数を生成する最も簡単な方法は何ですか? 投げ入れるだけの宝石はありますか?

注: Rails では整数以外の値で問題が発生することがあるため、整数に固執したいと考えています。

4

1 に答える 1

1

データベースの慣例では、自動インクリメントの主キーを使用するので、レールとはあまり関係がありません。

新しいテーブルの場合、railsがこの規則を使用しないようにするには、id列を自動的に作成しないように指示し、代わりに自分で作成する必要があります。

# example of creating a users table

create_table :users, id: false do |t|
  t.integer :id
  # other column definitions
end

add_index :users, [:id], unique: true, name: 'index_id_on_users'

次に、モデルで、レコードを作成する前にこれを明示的に設定する必要があります。

class User < ActiveRecord::Base
  before_create :set_id

  def set_id
    loop do
      self.id = rand(1<<32)
      break unless User.exists?(self.id)
    end
  end
end

ループは、一意のキーを取得することを確認しているだけです。そうしないと、db制約によってエラーが発生します。競合状態はまだありますが、衝突が心配な場合は、UUIDやSHAなどを使用するよりも多くなります。

非整数キーの問題については、私自身は問題に遭遇したことがなく、UUIDキーとSHAキーの両方を使用したほか、id列ではない主キーを使用したことがあります。これにはもう少し構成が必要です。

現在のモデルに関しては、すべてのIDから自動インクリメントを削除する必要があります。そうしないと、データベースはユーザーからの指示をすべて無視するはずです。これは明らかに、idで列変更の移行を発行するだけで実行できます。

change_column :users, :id, :integer

ここでの注意点は、db / schema.rbが変更を反映しないため、db:schema:loadが適切なデータベースを生成しないことです。ただし、とにかくデータベースをロードするためにそのrakeタスクを使用したことはありません。db:migrateを使用するだけで、すべて問題ありません。

そしていつものように、このようなコマンドを実行する前に、必ずDBをバックアップしてください。開発環境のsqlite3で実行したところ、問題なく動作したようです。



アップデート#1

URLだけが関係している場合の代替ルートは、IDの代わりにスラッグを使用することです。少しの構成といくつかの新しい列でこれを処理するいくつかの宝石があります。基本的には、URLパラメータとして列を使用するという考え方です。したがって、/ resources / 1を出力する代わりにURLヘルパーを使用すると、/ resources/some-url-friendly-slugが出力されます。これは、UUIDやSHAのような不可解なものでも、SEOに適したものでもかまいません。モデルにスラッギングできるものがあるかどうかによって異なります。たとえば、それがproduct_pathであり、製品にタイトルが付いている場合、スラッグは製品タイトルのURLに適したバージョンであり、SEOに最適です。

于 2013-02-22T00:46:34.973 に答える