rails query left joins includes active ruby-on-rails ruby activerecord

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;)



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