如何在 Rails 应用程序中使用长 id?

发布于 2024-07-25 10:12:18 字数 85 浏览 3 评论 0原文

如何更改 ActiveRecord ID 的(默认)类型? int 不够长,我更喜欢 long。 我很惊讶迁移没有 :long - 是否只使用一些小数?

How can I change the (default) type for ActiveRecord's IDs? int is not long enough, I would prefer long. I was surprised that there is no :long for the migrations - does one just use some decimal?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

爱本泡沫多脆弱 2024-08-01 10:12:18

致谢 http://moeffju.net/blog/using-bigint-columns -in-rails-migrations

class CreateDemo < ActiveRecord::Migration
  def self.up
    create_table :demo, :id => false do |t|
      t.integer :id, :limit => 8
    end
  end
end
  • 查看选项 :id => false 禁止自动创建 id 字段
  • t.integer :id, :limit => 8行将产生一个64位整数字段

Credits to http://moeffju.net/blog/using-bigint-columns-in-rails-migrations

class CreateDemo < ActiveRecord::Migration
  def self.up
    create_table :demo, :id => false do |t|
      t.integer :id, :limit => 8
    end
  end
end
  • See the option :id => false which disables the automatic creation of the id field
  • The t.integer :id, :limit => 8 line will produce a 64 bit integer field
揽月 2024-08-01 10:12:18

要设置默认主键列类型,迁移文件不是一个可以搞乱的地方。

相反,只需将其粘贴在 config/environment.rb 的底部,

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

并且所有表都应使用 id 的预期列类型创建:

+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| id           | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment | 

完成后你已经开始做...下一个问题可能是“如何使我的外键列具有相同的列类型?” 因为主键 people.idbigint(20) unsignedperson_idint(11) 是没有意义的) 还是其他什么?

对于这些列,您可以参考其他建议,例如

t.column :author_id, 'BIGINT UNSIGNED'
t.integer :author_id, :limit => 8

UPDATE:@Notinlist,要在任意表上使用任意列作为主键,您需要执行create_table-change_column dance:

create_table(:users) do |t|
  # column definitions here..
end
change_column :users, :id, :float # or some other column type

例如,如果我想要 guid 而不是自动递增整数,

create_table(:users, :primary_key => 'guid') do |t|
  # column definitions here..
end
change_column :users, :guid, :string, :limit => 36

To set the default primary key column type, the migration files are not the place to mess with.

Instead, just stick this at the bottom of your config/environment.rb

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

And all your tables should be created with the intended column type for id:

+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| id           | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment | 

After you've done what you've set out to do... the next question is probably "How do I make my foreign key columns the same column type?" since it does not make sense to have primary key people.id as bigint(20) unsigned, and person_id be int(11) or anything else?

For those columns, you can refer to the other suggestions, e.g.

t.column :author_id, 'BIGINT UNSIGNED'
t.integer :author_id, :limit => 8

UPDATE: @Notinlist, to use arbitrary column for primary key on arbitrary tables you need to do the create_table-change_column dance:

create_table(:users) do |t|
  # column definitions here..
end
change_column :users, :id, :float # or some other column type

e.g. if I wanted guid instead of auto-increment integers,

create_table(:users, :primary_key => 'guid') do |t|
  # column definitions here..
end
change_column :users, :guid, :string, :limit => 36
太阳公公是暖光 2024-08-01 10:12:18

这很难通过迁移来设置主键,因为 Rails 会自动将其放入。

您可以稍后更改任何列,如下所示:

change_column :foobars, :something_id, 'bigint'

您可以在初始迁移中将非主 ID 指定为自定义类型,如下所示:

create_table :tweets do |t|
  t.column :twitter_id, 'bigint'
  t.column :twitter_in_reply_to_status_id, 'bigint'
end

Where I have "bigint" you可以放置数据库将用于您要使用的数据库列类型的任何文本(例如“unsigned long”)。

如果您需要 id 列为 bigint,最简单的方法是创建表,然后在同一迁移中使用change_column 更改列。

对于 PostgreSQL 和 SQLite,架构更改是原子的,因此如果迁移失败,数据库不会处于奇怪的状态。 使用 MySQL 时你需要更加小心。

This is hard to set for the primary key with migrations because Rails puts it in automatically.

You can change any column later like this:

change_column :foobars, :something_id, 'bigint'

You can specify non-primary IDs as custom types in your initial migration like this:

create_table :tweets do |t|
  t.column :twitter_id, 'bigint'
  t.column :twitter_in_reply_to_status_id, 'bigint'
end

Where I have "bigint" you can put any text that your database would use for the database column type you want to use (e.g., "unsigned long").

If you need your id column to be a bigint, the easiest way to do it would be to create the table, then change the column in the same migration with change_column.

With PostgreSQL and SQLite, schema changes are atomic so this won't leave your database in a weird state if the migration fails. With MySQL you need to be more careful.

凑诗 2024-08-01 10:12:18

根据 Rails API 文档,类型的可能选项有:

:string
:text
:integer
:float
:decimal
:datetime
:timestamp
:time
:date
:binary
:boolean

您可以使用 :decimal,或者如果需要,您可以直接执行命令:

class MyMigration
  def self.up
    execute "ALTER TABLE my_table ADD id LONG"
  end
end

正如 wappos 指出的,您可以使用辅助选项,如 :limit 来告诉 ActiveRecord 有多大你想要的列是。 因此,您可以使用具有更大 :limit 的 :int 列。

According to the Rails API documentation, the possible options for type are:

:string
:text
:integer
:float
:decimal
:datetime
:timestamp
:time
:date
:binary
:boolean

You can use :decimal, or you can execute a command directly if you need to:

class MyMigration
  def self.up
    execute "ALTER TABLE my_table ADD id LONG"
  end
end

As wappos pointed out, you can use auxiliary options like :limit to tell ActiveRecord how large you want the column to be. So you would use the :int column with a larger :limit.

弥繁 2024-08-01 10:12:18

如果有人需要这个来与 PostgreSQL 一起工作,请创建一个如下的初始化程序:

# config/initializers/bigint_primary_keys.rb
ActiveRecord::Base.establish_connection
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key'

由于 Rails 3.2(甚至可能是更早版本)中的延迟加载,因此不需要 ActiveRecord::ConnectionAdapters::PostgreSQLAdapter 直到您建立数据库连接。

If anyone needs this to work with PostgreSQL, create an initializer like this:

# config/initializers/bigint_primary_keys.rb
ActiveRecord::Base.establish_connection
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key'

Because of lazy loading in Rails 3.2 (and maybe even earlier versions), ActiveRecord::ConnectionAdapters::PostgreSQLAdapter won't be required until you establish the database connection.

梦行七里 2024-08-01 10:12:18

在rails4中,你可以做到。

以下是在 rails4 中创建 Dummy 模型的示例 postgres

xxx_migrate_dummies.rb:

class CreateDummies < ActiveRecord::Migration
  def change
    create_table :dummies, :id => false do |t|
      t.column :id, :serial8, primary_key: true
      t.string :name, :limit => 50, null: false
      t.integer :size, null: false

      t.column :create_date, :timestamptz, null: false
    end
  end
end

它做了什么:

  • 它使用serial8作为id类型,它是64位整数,并将其定义为主键
  • 它使用 timestamptz 作为日期时间类型,其中包含时区信息,这对于跨多个时区的应用程序很重要。

In rails4, you can do it.

Following is an example to create a Dummy model in rails4 & postgres,

xxx_migrate_dummies.rb:

class CreateDummies < ActiveRecord::Migration
  def change
    create_table :dummies, :id => false do |t|
      t.column :id, :serial8, primary_key: true
      t.string :name, :limit => 50, null: false
      t.integer :size, null: false

      t.column :create_date, :timestamptz, null: false
    end
  end
end

What it did:

  • It use serial8 as id type, which is 64 bit integer, and define it as primary key.
  • It use timestamptz as datetime type, which contain the timezone info, this is important for a application that go across multiple timezones.
沧笙踏歌 2024-08-01 10:12:18

Rails 3,MySQL:

t.column :foobar, :int, :limit => 8

没有给我一个bigint,只有一个int。 不过,

t.column :twitter_id, 'bigint'

效果很好。 (尽管它确实将我与 MySQL 联系在一起。)

Rails 3, MySQL:

t.column :foobar, :int, :limit => 8

Does not give me a bigint, only an int. However,

t.column :twitter_id, 'bigint'

works fine. (Although it does tie me to MySQL.)

世界和平 2024-08-01 10:12:18

借鉴其他解决方案,根据最近对我有用的方法进行调整。

添加到 config/initializers 中的文件。 它声明了一个新的列类型(改编自 chookeat 的建议)。

ActiveRecord::ConnectionAdapters::Mysql2Adapter::NATIVE_DATABASE_TYPES[:long_primary_key] = "BIGINT(20) DEFAULT NULL auto_increment PRIMARY KEY"

使用长 id 的迁移如下:

    create_table :notification_logs, :id => false do |t|

      t.column :id, :long_primary_key
      # ...
    end

Borrowing from other solutions, adjusted for what worked for me recently.

Add to a file in config/initializers. It declares a new column type (adapted from chookeat's suggestion).

ActiveRecord::ConnectionAdapters::Mysql2Adapter::NATIVE_DATABASE_TYPES[:long_primary_key] = "BIGINT(20) DEFAULT NULL auto_increment PRIMARY KEY"

Migrations that use a long id are as such:

    create_table :notification_logs, :id => false do |t|

      t.column :id, :long_primary_key
      # ...
    end
数理化全能战士 2024-08-01 10:12:18

我编写了一个名为 activerecord-native_db_types_override 的 gem,它允许您更改将在迁移中使用的数据类型。

在 Gemfile 中,添加:

gem 'activerecord-native_db_types_override'

然后在 config/environment.rb 中,要在 postgres 中使用长 ID,添加:

NativeDbTypesOverride.configure({
  postgres: {
    primary_key: { name: "bigserial primary key"}
  }
})

请参阅其 自述文件以获取最新信息。

I wrote a gem called activerecord-native_db_types_override that lets you alter the datatypes that will be used in your migrations.

In your Gemfile, add:

gem 'activerecord-native_db_types_override'

then in config/environment.rb, to use long ids in postgres, add:

NativeDbTypesOverride.configure({
  postgres: {
    primary_key: { name: "bigserial primary key"}
  }
})

See its README for up-to-date info.

千と千尋 2024-08-01 10:12:18

你可以这样做:

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users, id: :bigserial do |t|
      t.string :name
    end
  end
end

You can do it like this:

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users, id: :bigserial do |t|
      t.string :name
    end
  end
end
没有心的人 2024-08-01 10:12:18

更正如何更改默认主键列类型:

而不是:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

您应该这样做:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT(8) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

否则您将无法在数据库层添加外键限制。

Correction to how to change the default primary key column type:

Instead of:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

you should do:

ActiveRecord::ConnectionAdapters::MysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "BIGINT(8) UNSIGNED DEFAULT NULL auto_increment PRIMARY KEY"

or else you won't be able to add foreign key restrictions in the database layer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文