将Rails中的主键更改为字符串

fr0*_*man 26 ruby activerecord ruby-on-rails

所以我有两个模型,State和Acquisition.State has_many收购.我觉得51个记录的自动增量整数主键是相当愚蠢的.所以我将State的模型改为PK(State是两个字母的缩写;我没有在任何地方存储实际的州名:

class State < ActiveRecord::Base  
  self.primary_key = "state"  
  has_many :acquisition_histories  
end
Run Code Online (Sandbox Code Playgroud)

问题是当我创建我的Acquisition模型时,它创建了外键列state_id作为整数.更具体地说,脚本/生成的迁移确实:

class CreateAcquisitions < ActiveRecord::Migration  
  def self.up  
    create_table :acquisitions do |t|  
      t.date :date  
      t.string :category  
      t.text :notes  
      t.references :state  
      t.timestamps  
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我假设t.references数据类型将其设置为int.问题是我的Acquisition类上的create方法试图将状态缩写放入表获取的state_id字段中(是的,它在数据库上称为state_id,即使它表示:迁移脚本中的状态).该方法不会失败,但它会在state_id字段中输入0并且记录进入以太.

mki*_*irk 36

虽然,我同意这可能考虑在其他地方违反默认值的额外努力更值得考虑,以防万一你真的想要做你所问的事情:

创建状态迁移:

class CreateStatesTable < ActiveRecord::Migration  
  def change
    create_table :states, id: false do |t|
      t.string :state, limit: 2
      t.string :name
      t.index :state, unique: true
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

国家模型:

class State < ActiveRecord::Base
  self.primary_key = :state
end
Run Code Online (Sandbox Code Playgroud)

请注意,在Rails 3.2之前,这set_primary_key = :state不是self.primary_key=看到:http://guides.rubyonrails.org/3_2_release_notes.html#active-record-deprecations


Wil*_*elm 32

如果你发现自己在这里...尽可能快地离开并转到: 使用Rails,如何将我的主键设置为不是整数类型的列?

  • 如果您认为答案回答了这个问题,请不要将其发布为答案;将此问题标记为重复。 (2认同)

blo*_*ilk 14

在 Rails 5.1 中,您可以在创建时指定主键的类型:

create_table :states, id: :string do |t|
# ...
end
Run Code Online (Sandbox Code Playgroud)

文档

Symbol 可用于指定生成的主键列的类型。


Bob*_*man 6

我正在开发一个使用UUID作为主键的项目,老实说,除非你确定你绝对需要它,否则我不推荐它.有大量的Rails插件无法使用字符串作为主键的数据库进行修改.


Joh*_*ley -28

当您不反对默认设置时,Rails 会发挥最佳效果。在状态表上使用整数主键有什么危害?

除非您陷入无法控制的遗留模式,否则我建议您坚持 Rails 默认设置(约定优于配置,对吗?)并专注于应用程序的重要部分,例如 UI 和业务逻辑。

  • 不幸的是,实际上在某些用例中您可能想要做一些开箱即用的事情。对于 99 人来说,会议可能是理想的,但在少数情况下,可能需要更有帮助的回应。 (28认同)
  • 我同意 @JohnTopley 的观点,最好不要与 Rails 作斗争,但答案实际上并没有回答问题。我认为可以用 Rails 来实现(但还不知道如何实现)。有很多合理的原因导致无法使用自动递增整数作为主键(例如,可扩展性要求迫使分布式实现根本不能有任何集中式组件)。 (10认同)
  • 对于这类事情,我倾向于在 State 类中定义一个常量,即 ALL = State.all,然后使用 State::ALL 作为下拉列表等的源。这样,SQL 查询仅在 Production 启动时运行。 (2认同)