2

我被要求随机化所有 SQL 表的 ID 值,继续前进。原因是竞争对手无法根据我们 ID 值的增长来推断网站流量。

rails 中的默认设置是使用 ID 作为索引、外键和 URL 路径。这些 ID 线性递增。

生成伪随机整数作为所有表的 ID 的最简单方法是什么?有没有我可以扔进去的宝石?

注意:Rails 有时会遇到非整数值的问题,所以我想坚持使用整数。

4

1 回答 1

1

它与 Rails 的关系不大,因为数据库的约定是使用自动增量主键。

对于新表,要防止 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 就可以了。

和往常一样,请确保在运行这样的命令之前备份您的数据库。我刚刚在我的开发环境中的 sqlite3 上运行它,它似乎工作正常。



更新#1

如果您只关心 URL,则另一种方法是使用 slug 而不是 ID。有一些 gem 可以通过一些配置和一些新列来处理这个问题。基本上这个想法是有一个列用作 url 参数。因此,当您使用 URL 助手而不是输出 /resources/1 时,它将输出 /resources/some-url-friendly-slug。这可以是像 UUID 或 SHA 这样神秘的东西,也可以是对 SEO 友好的东西。这取决于模型中是否有可以击打的东西。例如,如果它是 product_path 并且产品有标题,那么 slug 可能是产品标题的 url 友好版本,非常适合 SEO。

于 2013-02-22T00:46:34.973 回答