relations raw rails query left guide active ruby-on-rails ruby activerecord

ruby-on-rails - left - raw query ruby on rails



Conversión de una matriz de objetos a ActiveRecord:: Relation (3)

Tengo una variedad de objetos, llamémoslo Indicator . Quiero ejecutar los métodos de la clase Indicador (los de la variedad def self.subjects , def self.subjects , etc.) en esta matriz. La única manera que conozco de ejecutar métodos de clase en un grupo de objetos es hacer que sean una ActiveRecord :: Relation. Así que termino recurriendo a agregar un método to_indicators a Array .

def to_indicators # TODO: Make this less terrible. Indicator.where id: self.pluck(:id) end

A veces encadenó bastantes de estos ámbitos para filtrar los resultados, dentro de los métodos de clase. Entonces, aunque llamo a un método en una Relación ActiveRecord ::, no sé cómo acceder a ese objeto. Solo puedo acceder a su contenido a través de all . Pero all es un Array. Entonces, debo convertir esa matriz a ActiveRecord :: Relation. Por ejemplo, esto es parte de uno de los métodos:

all.to_indicators.applicable_for_bank(id).each do |indicator| total += indicator.residual_risk_for(id) indicator_count += 1 if indicator.completed_by?(id) end

Supongo que esto se reduce a dos preguntas.

  1. ¿Cómo puedo convertir una matriz de objetos en una relación ActiveRecord ::? Preferiblemente sin hacer un where cada vez.
  2. Al ejecutar un método de def self.subjects tipo def self.subjects en ActiveRecord :: Relation, ¿cómo def self.subjects a ese objeto ActiveRecord :: Relation?

Gracias. Si necesito aclarar algo, házmelo saber.


¿Cómo puedo convertir una matriz de objetos en una relación ActiveRecord ::? Preferiblemente sin hacer un donde cada vez.

No puede convertir una matriz en una relación ActiveRecord :: ya que una relación es solo un generador para una consulta SQL y sus métodos no funcionan en datos reales.

Sin embargo, si lo que quieres es una relación, entonces:

  • para ActiveRecord 3.x, no llame a all y en su lugar llame al scoped , lo que le devolverá una relación que representa los mismos registros que all le daría en una matriz.

  • para ActiveRecord 4.x, simplemente llame a all , que devuelve una relación.

Al ejecutar un método de def self.subjects tipo def self.subjects en ActiveRecord :: Relation, ¿cómo def self.subjects a ese objeto ActiveRecord :: Relation?

Cuando se llama al método en un objeto de relación, self es la relación (a diferencia de la clase de modelo en la que se define).


Bueno, en mi caso, necesito convertir una matriz de objetos a ActiveRecord :: Relation así como ordenarlos con una columna específica (id por ejemplo). Como estoy usando MySQL, la función de campo podría ser útil.

MyModel.where(''id in (?)'',ids).order("field(id,#{ids.join(",")})")

El SQL se ve así:

SELECT ... FROM ... WHERE (id in (11,5,6,7,8,9,10)) ORDER BY field(id,11,5,6,7,8,9,10)

Función de campo MySQL


Puede convertir una matriz de objetos arr en una relación ActiveRecord :: como esta (suponiendo que sepa qué clase son los objetos, lo que probablemente haga)

MyModel.where(id: arr.map(&:id))

Sin embargo, debe usarlo where sea ​​una herramienta útil que no debería ser reacio a usar. Y ahora tienes una línea única que convierte una matriz en una relación.

map(&:id) convertirá su matriz de objetos a una matriz que contiene solo sus id. Y pasar una matriz a una cláusula where generará una instrucción SQL con IN que se parece a algo así:

SELECT .... WHERE `my_models`.id IN (2, 3, 4, 6, ....

Tenga en cuenta que se perderá el orden de la matriz . Pero dado que su objetivo es solo ejecutar un método de clase en la colección de estos objetos, supongo que no será un problema.