Clases dinámicas en Ruby, Class.new, desempaquetando Sequel::Model
Soy nuevo en Ruby y estoy tratando de entender cómo funciona la declaración de clase a continuación desde la gema Sequel.
class Enumeration < Sequel::Model(DB[:enumerations]); end
Tras una rápida investigación del código de la gema Sequel, me parece que el método de módulo Sequel::Model devuelve una instancia de clase con un atributo de clase configurado. La instancia de retorno de Class es luego utilizada en la jerarquía de herencia, así que traté de probar mi comprensión a través del código:
module MySequel
class MyModel
module ClassMethods
attr<em>accessor :table</em>name
<pre><code> def model(table_name)
klass = Class.new(self)
klass.table_name = table_name
puts klass.table_name # imprime table_name, se establece para el primer objeto Class klass
klass
end
end
extend ClassMethods
end
end
class Enumeration < MySequel::MyModel.model(:enumerations); end
class EnumerationValue < MySequel::MyModel.model(:enumeration_values); end
p Enumeration.tablename # imprime nil
p EnumerationValue.tablename # imprime nil
Basado en mi comprensión, la variable de clase table_name
se establece al crear una instancia de Clase y se propaga en su clase hija. Sin embargo, eso no parece ser el caso.
¿Alguien podría explicar el concepto detrás de Sequel::Model y el problema con mi implementación de muestra para lograr el mismo resultado?
El comportamiento en este ejemplo es similar al uso de las clases anónimas anteriores.
class TestModel
@@table_name = 'test'
def TestModel.table<em>name
@@table</em>name
end
def TestModel.table<em>name=(value)
@@table</em>name = value
end
end
TestModel.table<em>name = 'posts'
p TestModel.table</em>name # imprime posts
class ChildTestModel < TestModel; end
puts Enumeration.table_name # imprime nil
La biblioteca Sequel aparentemente está propagando la información sobre el conjunto de datos establecido a través de la llamada al método de módulo a la clase hija (a través de la clase anónima).
Sin embargo, no puedo entender qué construcción del lenguaje Ruby permite que la clase Status a continuación sepa que está restringida a un registro en la tabla enumerations con el nombre establecido en ‘status’.
ruby
class Status < Sequel::Model(DB[:enumerations].where(name: 'status')); end
davy.ai
El método
Sequel::Model
en la biblioteca Sequel devuelve una clase que hereda de la claseSequel::Model
, con ciertas configuraciones ya establecidas. El argumento pasado al métodoSequel::Model
es el conjunto de datos que el modelo utilizará para sus consultas a la base de datos.En el caso de la declaración de la clase
Enumeration
, el conjunto de datosDB[:enumerations]
se pasa al métodoSequel::Model
, que devuelve una clase que hereda deSequel::Model
y utiliza la tablaenumerations
en la base de datosDB
como conjunto de datos para sus consultas.Tu implementación de muestra con el módulo
MySequel
parece estar tratando de lograr un resultado similar mediante el uso de una clase anónima como paso intermedio para crear la claseEnumeration
. Sin embargo, el problema con la implementación es que el atributotable_name
se establece en la clase anónima, no en la claseMyModel
de la que finalmente hereda la claseEnumeration
.Para solucionar la implementación, el atributo
table_name
debe establecerse en la propia claseMyModel
, de la siguiente manera:En cuanto a la clase
Status
, la construcción de Ruby que le permite saber que está restringida a un registro en la tablaenumerations
con el nombre establecido en'status'
es el métodowhere
encadenado al conjunto de datosDB[:enumerations]
. El métodowhere
restringe el conjunto de registros en el conjunto de datos solo a aquellos que cumplen con la condición especificada (en este caso, un registro con el nombre ‘status’). El conjunto de datos resultante se pasa al métodoSequel::Model
, que crea una clase que utiliza ese conjunto de datos como fuente para las consultas.