2010-02-04 1 views
7

Sapete come alcuni bug tracker (e altri software) consentono di aggiungere campi personalizzati?Rails - Aggiunta di campi personalizzati in fase di runtime in ActiveRecord

In genere questo è fatto con una struttura dati che sembra qualcosa di simile:

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


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

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

Sto cercando di capire il modo migliore per affrontare questo progetto in Rails. Ci saranno molti modelli che voglio permettere di estendere le proprietà semplici.

Quando si recupera uno Item Mi piacerebbe che includesse un hash dei valori del campo di addizione che sono stati definiti per quel modello.

risposta

6

Qualcosa come ...?

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 

Oppure, si potrebbe cambiare

cfh[fv.field_definition] = fv 

... al ...

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

L'uso di iniettare sarebbe probabilmente una forma migliore. Come self.field_values.inject ({}) {| memo, fv | memo [fv.field_definition] = fv} o simile. –

+0

Questo è quello che stavo pensando di usare ... mi chiedevo se c'era un modo più "rubino" per farlo ... –

+0

Il solito modo probabilmente non usare affatto un hash e basta usare l'associazione generata metodi, ma immagino ci sia una ragione per cui eri particolarmente ricercato un hash ...? –

1

Date un'occhiata al Friendly ORM. Ti permette di lavorare con mysql senza uno schema. È stato ispirato da questo blog post su come Friendfeed usa mysql per archiviare i dati degli schemi.

Friendly sostituirà ActiveRecord, anche se è possibile utilizzare i modelli ActiveRecord accanto ai modelli Friendly abbastanza facilmente.

+0

Non esattamente quello che sto cercando, ma comunque una bella scoperta. +1 –

+0

Se si considerano dati senza schema, si potrebbe voler utilizzare un database di documenti come CouchDB o MongoDB (consultare http://railscasts.com/episodes/194-mongodb-and-mongomapper per un webcast sull'utilizzo MongoDB e la gemma di MongoMapper in un'app per rails: Ryan Bates è fantastico per quanto riguarda btw). –

+0

Sì, sono decisamente interessato a questo. Sono su Heroku, che attualmente non funzionerà con MongoDB. –

1

Se la vostra intenzione è quella di avere i tuoi FieldDefinition record appartenenti a diversi modelli (ad esempio, una colonna item_id che punta a sia un SqueekyToyItem o un BalloonItem) allora ciò che si desidera è un'associazione polimorfica.

In pratica consente di disporre di una colonna item_type (accanto alla colonna item_id), che quindi specifica il tipo effettivo di oggetto a cui punta.

C'è un'intestazione "Associazioni polimorfiche" nella documentazione per ActiveRecord::Associations::ClassMethods.

+0

Ho intenzione di averli su molti modelli, ma erediteranno tutti da Item (o qualsiasi altra cosa la mia classe base finisca per essere) –