Rails模型-自定义主键,ID作为自定义列



我挣扎着用自定义主键将我的表建模为Rails模型和id作为正则(非空)列。

问题是我的表有:

  1. auto_id主键列AUTO_INCREMENT
  2. id为自定义列,NOT NULL约束(保存前由应用端设置)
class InitialMigration < ActiveRecord::Migration[6.1]
def change
create_table :cars, id: false, force: true do |t|
t.primary_key :auto_id
t.string :id, null: false
end
end
end

我想:

  1. 使primary_key由数据库自动生成
  2. 在保存模型之前,直接在应用程序中设置id值。

但是当我试图将汽车实例保存到数据库时,我有一个从应用程序设置id的问题。

class Car < ActiveRecord::Base
self.primary_key = "auto_id"
before_create do
binding.pry
end
end

即使在binding.pry行,当我调用self.id = '1234'时,它被重新分配给auto_id字段,而不是id

因此id列始终保持NULL,导致DB错误Field 'id' doesn't have a default value

[2] pry(#<Car>)> self.id = '9'
=> "9"
[3] pry(#<Car>)> self
=> #<Car:0x00007fcdb34ebe60
auto_id: 9,
id: nil>

p。这是Rails 6。

我会通过将其重命名为其他东西来避免使用id。在rails中,id@primary_key设置的值。有一个完整的模块专门用于定义id属性方法:

https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/PrimaryKey.html

这些方法可以被覆盖,但不应该被覆盖:

class Car < ApplicationRecord
self.primary_key = "auto_id"
def id= value
_write_attribute("id", value)
end
def id
_read_attribute("id")
end
end

"id"是硬编码在write_attribute使用primary_key,所以我们不能使用write_attribute来设置id属性本身。

同样,id方法也在其他地方使用。重写它们是一个坏主意。

>> Car.create(id: "99")
=> #<Car:0x00007f723e801788 auto_id: nil, id: "99">
#                                    ^
# NOTE: Even though car has been saved, `auto_id` is still `nil`
#       but only in `car` object. Because we have overridden
#       `id`, primary key is read from `id` column and then `id` 
#       attribute is set in `id=`. `auto_id` is bypassed.
>> Car.last
=> #<Car:0x00007f774d9e8dd0 auto_id: 1, id: "99">
# NOTE: Other methods are broken whenever `id` is used
>> Car.last.to_key
=> ["99"]
>> Car.last.to_gid
=> #<GlobalID:0x00007f774f4def68 @uri=#<URI::GID gid://stackoverflow/Car/99>>

一个更好的方法是不碰id方法:

class Car < ApplicationRecord
self.primary_key = "auto_id"
def id_attribute= value
_write_attribute("id", value)
end
def id_attribute
_read_attribute("id")
end
end
>> car = Car.create(id_attribute: "99")
=> #<Car:0x00007fb1e44d9458 auto_id: 2, id: "99">
>> car.id_attribute
=> "99"
>> car.id
=> 2
>> car.auto_id
=> 2

相关内容

  • 没有找到相关文章

最新更新