我被要求随机化所有 SQL 表的 ID 值,继续前进。原因是竞争对手无法根据我们 ID 值的增长来推断网站流量。
rails 中的默认设置是使用 ID 作为索引、外键和 URL 路径。这些 ID 线性递增。
生成伪随机整数作为所有表的 ID 的最简单方法是什么?有没有我可以扔进去的宝石?
注意:Rails 有时会遇到非整数值的问题,所以我想坚持使用整数。
我被要求随机化所有 SQL 表的 ID 值,继续前进。原因是竞争对手无法根据我们 ID 值的增长来推断网站流量。
rails 中的默认设置是使用 ID 作为索引、外键和 URL 路径。这些 ID 线性递增。
生成伪随机整数作为所有表的 ID 的最简单方法是什么?有没有我可以扔进去的宝石?
注意:Rails 有时会遇到非整数值的问题,所以我想坚持使用整数。
它与 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。