2011-01-24 9 views
7

Usando el registro activo, ¿cómo puedo devolver los resultados para un modelo si no existe en una cierta relación en otro lugar. Por ejemplo, supongamos que tengo un modelo Recipe que pertenece a categories (a través de una tabla de combinación category_recipes).Rieles: devolución de registros para los cuales no existe una relación

Así que, básicamente, tengo una tarea de Rake que repasa cada receta y su descripción y trata de ponerla en una categoría, pero la tarea lleva mucho tiempo y tendré que ejecutarla de forma regular, por lo que solo quiero ejecutarlo si el Recipe en cuestión aún no ha sido categorizado y prefiero no agregar una columna superflua como categorized, por lo que creo que hay una forma de recuperar solo las Recetas que no existen en la tabla de unión. ¿Alguna idea?

Respuesta

14

Puede resolver esta consulta con un LEFT OUTER JOIN:

Recipe.joins('LEFT OUTER JOIN recipe_categories ON recipes.id = recipe_categories.recipe_id').where('recipe_categories.recipe_id IS NULL') 
+0

Funciona muy bien! Se siente un poco sucio con todo ese sql en bruto allí, pero eso es probablemente porque he estado acostumbrado a AREL durante tanto tiempo: D –

3

Puede hacer esto con una selección SQL, tal vez.

@uncategorized_recipes = Recipe.find_by_sql("select * from recipes 
    where id not in (select recipe_id from category_recipes)") 

La sintaxis exacta puede variar según su base de datos.

1

Yo no lo he probado pero puede tratar

Recipe.joins(:categories).select('recipes.*, categories.count(*) as category_count').where(:category_count => 0).group('recipes.id') 
10

tuvieron que resolver esto por mí mismo hoy y creo que esto hará el truco :

Recipe.includes(:categories).where('categories.id IS NULL').references(:categories) 
+1

Esta es la mejor respuesta ... En Rieles 4 puede que necesite agregar referencias. Recipe.includes (: category) .where ("categories.id IS NULL"). References (: category) – hellion

2

Puede hacer esto usando el método de arranque para Receta y CategoríaRecetar.

Pasos:

  • R = Receipe.pluck (: id)

    #provides una matriz de todos los identificadores dentro del modelo. Ex: [1, 2, 3, 4, 5 ...]

  • cr = CategoryRecipe.pluck (: receta_id)

    #provides una matriz todos los identificadores de la columna receta_id que son presente.

  • resto = r - cr

    #Este toma las dos matrices de ID y receta_id y evalúa a una nueva matriz. Esta nueva matriz solo tendrá aquellos identificadores que no están presentes en CategoryRecipe.

A continuación, puede ejecutar su operación en esta nueva matriz: Recipe.where (id: resto).contar

#gives usted el número de registros que se deben actualizar

prefiero este método porque se puede hacer en una función separada, que se puede utilizar en la evaluación de múltiples asociaciones sin reescribir el código . Esto también es extremadamente fácil de probar.

Cuestiones relacionadas