ruby-on-rails - rails - rake db:rollback
MigraciĆ³n de carriles: add_reference a Table pero diferente nombre de columna para Foreign Key than Rails Convention (6)
Tengo los siguientes dos modelos:
class Store < ActiveRecord::Base
belongs_to :person
end
class Person < ActiveRecord::Base
has_one :store
end
Aquí está el problema: estoy tratando de crear una migración para crear la clave externa dentro de la tabla de personas. Sin embargo, la columna que hace referencia a la clave externa de Store no se llama store_id como sería la convención de rails, sino que se denomina foo_bar_store_id .
Si estuviera siguiendo la convención de rieles, haría la migración de esta manera:
class AddReferencesToPeople < ActiveRecord::Migration
def change
add_reference :people, :store, index: true
end
end
Sin embargo, esto no funcionará porque el nombre de la columna no es store_id, sino que es foo_bar_store_id . Entonces, ¿cómo especifico que el nombre de la clave externa es simplemente diferente, pero todavía mantengo index: true para mantener un rendimiento rápido?
Debajo de las cubiertas add_reference solo está delegando add_column y add_index por lo que solo tiene que encargarse usted mismo:
add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id
En Rails 4.2, también puede configurar el modelo o la migración con un nombre de clave externa personalizado. En su ejemplo, la migración sería:
class AddReferencesToPeople < ActiveRecord::Migration
def change
add_column :people, :foo_bar_store_id, :integer, index: true
add_foreign_key :people, :stores, column: :foo_bar_store_id
end
end
Here hay una interesante publicación de blog sobre este tema. Here está la sección semi-críptica en las Guías Rails. La publicación del blog definitivamente me ayudó.
En cuanto a las asociaciones, indique explícitamente la clave foránea o nombre de clase como este (creo que sus asociaciones originales se cambiaron ya que ''belongs_to'' entra en la clase con la clave externa):
class Store < ActiveRecord::Base
has_one :person, foreign_key: :foo_bar_store_id
end
class Person < ActiveRecord::Base
belongs_to :foo_bar_store, class_name: ''Store''
end
Tenga en cuenta que el elemento class_name debe ser una cadena. El elemento foreign_key puede ser una cadena o un símbolo. Esto esencialmente le permite acceder a los ingeniosos accesos directos de ActiveRecord con sus asociaciones nombradas semánticamente, de la siguiente manera:
person = Person.first
person.foo_bar_store
# returns the instance of store equal to person''s foo_bar_store_id
belongs_to más información sobre las opciones de asociación en la documentación de belongs_to y has_one .
En su migración AddReferencesToPeople
puede agregar manualmente el campo y el índice usando:
add_column :people, :foo_bar_store_id, :integer
add_index :people, :foo_bar_store_id
Y luego, deje que su modelo conozca la clave externa de la siguiente manera:
class Person < ActiveRecord::Base
has_one :store, foreign_key: ''foo_bar_store_id''
end
Para expandir la respuesta de Schpet, esto funciona en una directiva de migración create_table
Rails 5 como esta:
create_table :chapter do |t|
t.references :novel, foreign_key: {to_table: :books}
t.timestamps
end
en los rieles más nuevos puede agregar una clave externa a una tabla con un nombre diferente como este:
class AddFooBarStoreToPeople < ActiveRecord::Migration[5.0]
def change
add_reference :people, :foo_bar_store, foreign_key: { to_table: :stores }
end
end
# Migration
change_table :people do |t|
t.references :foo_bar_store, references: :store #-> foo_bar_store_id
end
# Model
# app/models/person.rb
class Person < ActiveRecord::Base
has_one :foo_bar_store, class_name: "Store"
end