2010-11-03 22 views
7

Tengo dos modelos en mi aplicación de rieles con un tiene muchos y pertenece a la asociación. Categoría tiene muchos artículos y el artículo pertenece a la categoría.Buscar todos los objetos con asociación rota

Estos modelos se asocian de forma normal a través de una columna category_id en el modelo del artículo.

Estoy buscando una forma rápida de encontrar todos los elementos en la base de datos con asociaciones rotas. es decir, encuentre todas las categorías que existen sin elementos asociados y elementos que existen sin categoría asociada.

Por ejemplo, si tengo un artículo con un category_id de 7, pero la categoría con id 7 se ha eliminado, esto se consideraría roto.

+0

Hay una nueva, carriles 3 variación y cerca víctima aquí : http://stackoverflow.com/questions/9471395/rail s-3-find-condition-to-filter-broken-reference-integrity-associations –

Respuesta

2

Una forma muy efectiva está utilizando find_by_sql para que la base de datos haga el trabajo pesado:

uncategorized_items = Item.find_by_sql("select * from items where category_id IS NULL") 

Otra forma es un ámbito con nombre:

class Item < ActiveRecord::Base 
    scope :uncategorized, where(:category_id => nil) # rails 3 

    # or... 

    named_scope :uncategorized, :conditions => 'category_id IS NULL' 
end 

Estos son sólo un par de ideas. Supongo que una vez que haya encontrado estas asociaciones rotas, planea arreglarlas, ¿verdad? Es posible que desee utilizar validates_associated en ambos modelos si es importante para usted que esto no vuelva a suceder.

Puede usar find_by_sql y una combinación externa izquierda para encontrar todos los elementos en una tabla pero no en otra. Aquí, utilizo una mesa de descargas y una mesa image_files (yo sólo he incluido el SQL):

SELECT d.*, d.image_file_id 
from downloads as d 
LEFT OUTER JOIN image_files as i 
ON i.id = d.image_file_id 
WHERE d.image_file_id IS NULL 
+1

Eso solo encontrará objetos cuyo category_id sea nulo. Lo que estoy buscando es una forma de encontrar objetos cuyo category_id está lleno pero el objeto asociado no existe. Por ejemplo, si category_id es 7 pero la categoría asociada con id 7 ya no existe. – KJF

+1

'find_by_sql' y una combinación externa izquierda son sus amigos. Aquí hay un ejemplo usando una tabla de downloads y image_files (respuesta original editada). –

5

Para su ejemplo, para encontrar elementos con la category_id para las categorías que no existen más:

Item.where('NOT EXISTS (SELECT * FROM categories where category.id = item.category_id)') 

es posible que desee ver en esto también: una tarea rastrillo para localizar a los desaparecidos índices de base de datos (no claves externas sin embargo, pero los índices): https://github.com/eladmeidar/rails_indexes

Cuestiones relacionadas