2010-02-04 9 views
7

¿Sabe cómo algunos rastreadores de errores (y otro software) le permiten agregar campos personalizados?Rieles: adición de campos personalizados en el tiempo de ejecución en ActiveRecord

Normalmente esto se hace con una estructura de datos que se ve algo como esto:

Items 
---------- 
ID | NAME | ITEM_TYPE_ID 


FieldDefinitions 
--------------------------------------- 
ID | ITEM_TYPE_ID | FIELD_NAME | FIELD_TYPE 

FieldValues 
--------------------------------------- 
ID | FIELD_ID | ITEM_ID | VALUE 

Estoy tratando de averiguar la mejor manera de acercarse a este diseño en Rails. Habrá muchos modelos que quiero permitir extender propiedades simples.

Cuando recupere un Item me gustaría que incluya un hash de los valores de campo de adición que se han definido para ese modelo.

Respuesta

6

Algo como ...?

class Item < ActiveRecord::Base 
    has_many :field_values 
    has_many :field_definitions, :through => :field_values 

    def custom_fields_hash 
    cfh = {} 
    self.field_values.each |fv| 
     cfh[fv.field_definition] = fv 
    end 
    cfh 
    end 
end 

class FieldValue < ActiveRecord::Base 
    belongs_to :item 
    belongs_to :field_definition 
end 

class FieldDefinition < ActiveRecord::Base 
    has_many :field_values 
    has_many :items, :through => field_values 
end 

O, usted podría cambiar

cfh[fv.field_definition] = fv 

... a ...

cfh[fv.field_definition.field_name] = fv.value 
+1

El uso de inyectar probablemente sería una mejor forma. Como self.field_values.inject ({}) {| memo, fv | memo [fv.field_definition] = fv} o similar. –

+0

Esto es lo que estaba pensando que usaría ... me preguntaba si había una forma más de "ruby" de hacer esto ... –

+0

La forma habitual probablemente no sea utilizar un hash en absoluto y simplemente usar la asociación generada métodos, pero supongo que hay una razón por la que se quería especialmente un hash ...? –

1

Tome un vistazo a la Friendly ORM. Le permite trabajar con mysql sin un esquema. Fue inspirado por este blog post sobre cómo Friendfeed usa mysql para almacenar datos sin esquema.

Friendly reemplazará a ActiveRecord, aunque puede usar los modelos ActiveRecord junto a los modelos Friendly con bastante facilidad.

+0

No es exactamente lo que estoy buscando, pero un hallazgo genial, no obstante. +1 –

+0

Si considera datos sin esquema, puede utilizar una base de datos de documentos como CouchDB o MongoDB (consulte http://railscasts.com/episodes/194-mongodb-and-mongomapper para obtener una transmisión por Internet sobre el uso de MongoDB y la joya MongoMapper en una aplicación de rieles, Ryan Bates es increíble por cierto). –

+0

Sí, definitivamente estoy interesado en eso. Estoy en Heroku, que actualmente no funcionará con MongoDB. –

1

Si su intención es tener sus registros FieldDefinition perteneciente a modelos diferentes (por ejemplo, una columna item_id que apunta a un bien o una SqueekyToyItemBalloonItem), entonces lo que quiere es una asociación polimórfica.

Básicamente le permite tener una columna item_type (al lado de su columna item_id), que luego especifica el tipo real de elemento al que apunta.

Hay un encabezado "Asociaciones polimórficas" en la documentación para ActiveRecord::Associations::ClassMethods.

+0

Tengo la intención de tenerlos en muchos modelos, pero todos heredarán de Item (o lo que sea que mi clase base termine siendo) –

Cuestiones relacionadas