2012-09-17 12 views
5

implemento una jerarquía de clases utilizando el patrón de ITSUsando alcance, definido en el modelo de los padres, por dentro, es hijo (patrón ITS)

class A 
    scope :aaa, where([someField]:[someValue]) 
end 

class B < A 
end 

El problema es que cuando intento llamar algo así como:

B.limit(5).aaa 
=> SELECT "[table]".* FROM "[table]" WHERE "[table]"."type" IN ('A') AND ([someField] = [someValue]) LIMIT 5 

Así que estoy recibiendo 5 objetos de tipo a, que satisface alcance: aaa Pero tengo que hacer lo mismo con las filas donde type = "B"

¿hay alguna manera de utilizar los ámbitos de padre, sin redifinción en niños en el patrón STI?

Gracias de antemano

EDITADAS

acabo de hablar con mi frind y me mostraron una cosa importante. A no es la clase raíz de STI. De hecho toda la jerarquía parece

class O < ActiveRecord::Base 
end 

class A < O 
    scope ..... ..... 
end 

class B < A 
end 

tal vez la razón es en sí misma jerarquía? ...

Respuesta

2

Tiene razón en que esto es el resultado de la jerarquía de niveles múltiples.

El alcance funcionaría como se esperaba si solo tuviera un nivel de herencia (es decir, si A se hereda de ActiveRecord::Base en lugar de heredar de O).

STI in Rails no siempre funciona como se esperaba una vez que tiene clases intermedias.

No estoy seguro de si esto es un error en Rails o simplemente porque no es posible inferir exactamente lo que se debe hacer. Tendré que investigar eso más.

El problema de alcance que experimentó es solo un ejemplo del comportamiento inesperado. Otro ejemplo es que la consulta de la clase intermedia solo consultará los tipos de clases que conoce, que pueden no incluir todas sus subclases a menos que usted específicamente los requiera:

Consulte el siguiente hilo para obtener más información, especialmente la publicación en la parte inferior por MatthewRudy: https://groups.google.com/forum/#!topic/hkror/iCg3kxXkxnA

Si aún desea utilizar ámbitos en lugar de los métodos de clase según lo sugerido por @Atastor, se puede poner en el alcance O en lugar de A. Esto no es ideal ya que el alcance puede no ser aplicable a todas las subclases de O, pero parece hacer que Rails consulte las clases correctas en la columna type, y es una solución rápida.

1

Me gustaría cambiar al uso de un método de clase en lugar de un ámbito, por ejemplo, en la clase A

def self.aaa 
    A.where([someField]:[someValue]) 
end 

y después en la clase B

def self.bbb 
    self.aaa.where("type = ?","B") 
end 
+0

Funciona, pero aún curioso por qué mi ejemplo funciona no lo que yo esperaba – AntonTkachov

0

Tenga cuidado con las clases intermedias de STI porque puede arruinar el alcance que está intentando.

En mi caso tuve:

class A < ActiveRecord 
blabla 
end 
class B < A 
scope :dates, ->(start_date, end_date) { where(:date => start_date..end_date) } 
end 
class C < B 
<call scope_dates> 
end 
class D < B 
<call scope_dates> 
end 

Y el alcance era en realidad incluyendo la clase C y clase D combinado.

Por lo tanto, si usted tiene infecciones de transmisión sexual en los carriles Por favor, ponga los alcances de la clase base, no clases intermedias

Cuestiones relacionadas