2009-05-24 9 views
48

Tengo una clase de comentario con una: foreign_key de post_id en la clase Post.Definición de relaciones de claves foráneas para los modelos de Rails

class Comment < ActiveRecord::Base 
    belongs_to :post, :class_name => "Post", :foreign_key => "post_id", :counter_cache => true 
    belongs_to :author, :class_name => "User", :foreign_key => "author_id" 
end 

Pero mi migración CreateComments no define una clave externa a nivel de base de datos:

class CreateComments < ActiveRecord::Migration 
    def self.up 
    create_table :comments do |t| 
     t.column "post_id",  :integer, :default => 0, :null => false 
     t.column "author",  :string, :default => "", :limit => 25, :null => false 
     t.column "author_email", :string, :default => "", :limit => 50, :null => false 
     t.column "content",  :text,  :null => false 
     t.column "status",  :string, :default => "", :limit => 25, :null => false 
     t.timestamps 
    end 
    end 

    def self.down 
    drop_table :comments 
    end 
end 

lugar post_id es una columna de enteros simples.

Parece que esta relación de clave externa existe solo en la mente de Rails, no en el nivel de la base de datos.

¿Es esto correcto?

Además, ¿es necesario que el correspondiente modelo de publicación también declare su relación de clave externa recíproca con Comentarios usando el atributo: foreign_key o podría omitirse?

class Post < ActiveRecord::Base 
    set_table_name("blog_posts") 
    belongs_to :author, :class_name => "User", :foreign_key => 'author_id' 
    has_many :comments, :class_name => "Comment", 
    :foreign_key => 'post_id', :order => "created_at desc", :dependent => :destroy 
    has_many :categorizations 
    has_many :categories, :through => :categorizations 
    named_scope :recent, :order => "created_at desc", :limit => 5 

end 
+0

Comparto su sorpresa de que Rails no utiliza claves externas SQL. Hace que sea difícil usar herramientas sin rieles en los DB. – Greg

+2

Rails sigue la convención de que "TODAS las lógicas comerciales deben definirse en la aplicación" ... por lo que utiliza DB solo como un almacenamiento "tonto". Sin claves externas, sin procedimientos almacenados, sin restricciones (soportado en postgres por ejemplo). EDITAR: Acabo de encontrar esta respuesta que dice lo mismo - http://stackoverflow.com/questions/8334602/need-to-create-a-foreign-key-when-creating-a-table-on-rails –

+1

https://github.com/matthuhiggins/foreigner – wberry

Respuesta

69

El comportamiento predeterminado Rails es que la columna se utiliza para mantener la clave externa en un modelo es el nombre de la asociación con el sufijo _id añadió. La opción :foreign_key le permite establecer el nombre de la clave externa directamente. Las asociaciones entre sus Post y Comment clases del modelo debe tener este aspecto:

class Post < ActiveRecord::Base 
    has_many :comments 
end 

class Comment < ActiveRecord::Base 
    belongs_to :post 
end 

— Tenga en cuenta que no es necesario :class_name => "Post" en su modelo Comment. Rails ya tiene esa información. Solo debe especificar :class_name y :foreign_key cuando necesite anular las convenciones de Rails.

Tiene razón en que Rails mantiene las relaciones de claves foráneas para usted. Puede aplicarlos en la capa de la base de datos si lo desea agregando restricciones de clave externa.

+0

Dado que la conexión foreign_key no está en el nivel de la base de datos y solo en los rieles. Si se elimina un registro de la publicación, ¿se eliminará también su fila asociada en el comentario? Ese es otro beneficio de mantener foreign_key. ¿Recibiré este beneficio? –

+0

Si también desea eliminar la columna asociada. Debes agregar 'dependent: destroy' al final de la línea que escribiste asociación. – Lavika

Cuestiones relacionadas