ruby on rails - query - Alterar la clave primaria en Rails para que sea una cadena
rails join table (9)
Desea seguir las convenciones de Rails. La clave primaria adicional no es un problema de ninguna manera. Solo úsalo.
Así que tengo dos modelos, Estado y Adquisición. El estado tiene muchas adquisiciones. Sentí que una clave primaria entera autoincrementada para 51 registros era bastante tonta. Así que modifiqué el modelo para que el Estado sea el PK (el estado es la abreviatura de dos letras; no estoy almacenando el nombre del estado real en ninguna parte:
class State < ActiveRecord::Base
self.primary_key = "state"
has_many :acquisition_histories
end
El problema es cuando creé mi modelo de Adquisición, creé la columna de la clave externa state_id como un entero. Más específicamente, el script / migración generada hizo:
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
Supongo que el tipo de datos de referencias lo establece en int. El problema es que mi método de creación en mi clase de Adquisición intenta poner una abreviación de estado en el campo state_id en las adquisiciones de la tabla (y sí, se llama state_id en la base de datos, aunque dice: state en el script de migración). El método no falla, pero pone un 0 en el campo state_id y los registros entran en el éter.
En Rails 5.1 puede especificar el tipo de clave principal en la creación:
create_table :states, id: :string do |t|
# ...
end
De la documentación :
Un símbolo se puede usar para especificar el tipo de la columna de clave primaria generada.
Estoy trabajando en un proyecto que usa UUID como claves principales y, sinceramente, no lo recomiendo a menos que esté seguro de que lo necesita. Hay una gran cantidad de complementos de Rails por ahí que no funcionarán sin modificaciones con una base de datos que usa cadenas como claves principales.
Rails funciona mejor cuando no lucha contra los valores predeterminados. ¿Qué daño hace tener una clave primaria entera en su tabla de estado?
A menos que esté atascado con un esquema heredado sobre el que no tiene control, le aconsejo que se adhiera a la convención predeterminada de Rails sobre la configuración, ¿no? Y se concentre en las partes importantes de su aplicación, como la interfaz de usuario y la lógica de negocios.
Sin embargo, estoy de acuerdo en que esto podría ser más problemático de lo que vale la pena considerar el esfuerzo extra de trabajar contra los incumplimientos en cualquier otro lugar, en caso de que realmente desee hacer lo que ha pedido:
Crear migración de estados:
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
modelo de estados:
class State < ActiveRecord::Base
self.primary_key = :state
end
Tenga en cuenta que antes de Rails 3.2, esto era set_primary_key = :state
lugar de self.primary_key=
see: http://guides.rubyonrails.org/3_2_release_notes.html#active-record-deprecations
Tuve un poco de experiencia con la cuerda utilizada como teclas principales y es un dolor en el culo. Recuerde que, de forma predeterminada, si desea pasar un objeto con el patrón predeterminado: controller /: action /: id, el: id será una cadena y esto probablemente dará lugar a problemas de enrutamiento si algunos identificadores se formatean extrañamente;)
si se encuentra aquí ... salga lo más rápido que pueda e vaya a: Usando Rails, ¿cómo puedo configurar mi clave principal para que no sea una columna de tipo entero?
Tenga en cuenta que la respuesta de mkirk crea una clave primaria falsa . Esto explica por qué ActiveRecord necesita que se le diga cuál es la clave principal. Inspeccionar la mesa revela
Table "public.acquisitions"
Column | Type | Modifiers
--------+----------------------+-----------
state | character varying(2) |
name | character varying |
Indexes:
"index_acquisitions_on_state" UNIQUE, btree (state)
En la práctica, esto funciona como se esperaba, así que no hay nada mal allí, pero podría ser mejor.
Podemos mantener la columna de id
y cambiar su tipo a string
*. La migración se ve como
class CreateAcquisitionsTable < ActiveRecord::Migration
def change
create_table :acquisitions do |t|
t.string :name
end
change_column :acquisitions, :id, :string, limit: 2
end
end
La inspección de la tabla revela que tiene una clave primaria real con todas las cosas buenas, como la restricción de clave única (no se necesita un índice único), restricción no nula y clave de incremento automático.
Table "public.acquisitions"
Column | Type | Modifiers
--------+----------------------+---------------------------------------------------
id | character varying(2) | not null default nextval(''acquisitions_id_seq''::regclass)
name | character varying |
Indexes:
"acquisitions_pkey" PRIMARY KEY, btree (id)
Y no tendrá que decirle explícitamente a ActiveRecord cuál es el principal.
Deberá considerar establecer un ID predeterminado si no se proporciona ninguno.
class MyModel < ActiveRecord::Base
before_create do
self.id = SecureRandom.uuid unless self.id
end
end
* Descargo de responsabilidad: no debe cambiar la clave primaria predeterminada a menos que tenga una buena razón para
class CreateAcquisitions < ActiveRecord::Migration
def self.up
create_table :acquisitions, :id => false do |t|
t.date :date
t.string :category
t.text :notes
t.references :state
t.timestamps
end
end
end