es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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.table
name # 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

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El método Sequel::Model en la biblioteca Sequel devuelve una clase que hereda de la clase Sequel::Model, con ciertas configuraciones ya establecidas. El argumento pasado al método Sequel::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 datos DB[:enumerations] se pasa al método Sequel::Model, que devuelve una clase que hereda de Sequel::Model y utiliza la tabla enumerations en la base de datos DB 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 clase Enumeration. Sin embargo, el problema con la implementación es que el atributo table_name se establece en la clase anónima, no en la clase MyModel de la que finalmente hereda la clase Enumeration.

    Para solucionar la implementación, el atributo table_name debe establecerse en la propia clase MyModel, de la siguiente manera:

    module MySequel
      class MyModel
        attr_accessor :table_name
    
        def self.model(table_name)
          klass = Class.new(self)
          klass.table_name = table_name
          klass
        end
    
        MyModel.table_name = :enumerations
      end
    end
    
    class Enumeration < MySequel::MyModel.model(:enumerations); end
    
    p Enumeration.table_name # imprime :enumerations
    

    En cuanto a la clase Status, la construcción de Ruby que le permite saber que está restringida a un registro en la tabla enumerations con el nombre establecido en 'status' es el método where encadenado al conjunto de datos DB[:enumerations]. El método where 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étodo Sequel::Model, que crea una clase que utiliza ese conjunto de datos como fuente para las consultas.

Comments are closed.