Utilizzando ROR con una tabella precedente che utilizza E-A-V
-
12-09-2019 - |
Domanda
Ho bisogno di connettersi a un database legacy e tirare un sottoinsieme di dati da una tabella che utilizza il modello entità-attributo-valore per memorizzare le informazioni di un contatto. La tabella è simile al seguente:
subscriberid fieldid data 1 2 Jack 1 3 Sparrow 2 2 Dan 2 3 Smith
dove fieldid
è una chiave esterna a una tabella che elenca fields
campi personalizzati un determinato cliente può avere (ad esempio nome, cognome, telefono). Lo SQL coinvolto è piuttosto peloso come devo unire la tabella con se stessa per ogni campo che voglio indietro (al momento ho bisogno di 6 campi), così come l'adesione ad una lista di contatti maestro che si basa su l'utente corrente.
L'SQL è qualcosa di simile:
select t0.data as FirstName, t1.data as LastName, t2.data as SmsOnly
from subscribers_data t0 inner join subscribers_data t1
on t0.subscriberid = t1.subscriberid
inner join subscribers_data t2
on t2.subscriberid = t1.subscriberid
inner join list_subscribers ls
on (t0.subscriberid = ls.subscriberid and t1.subscriberid = ls.subscriberid)
inner join lists l
on ls.listid = l.listid
where l.name = 'My Contacts'
and t0.fieldid = 2
and t1.fieldid = 3;
Come devo fare per la manipolazione di questo con la mia applicazione RoR? Vorrei abstracat questa via ed essere in grado di utilizzare il normale "notazione punto" per tirare fuori gli attributi ancora. Per fortuna i dati è di sola lettura per il prossimo futuro.
Soluzione
Questo è esattamente ciò che è stato progettato per #find_by_sql. Vorrei reimplementare #find di fare ciò che è necessario fare, qualcosa di simile a questo:
class Contact < ActiveRecord::Base
set_table_table "subscribers_data"
def self.find(options={})
find_by_sql <<EOS
select t0.data as FirstName, t1.data as LastName, t2.data as SmsOnly
from subscribers_data t0 inner join subscribers_data t1
on t0.subscriberid = t1.subscriberid
inner join subscribers_data t2
on t2.subscriberid = t1.subscriberid
inner join list_subscribers ls
on (t0.subscriberid = ls.subscriberid and t1.subscriberid = ls.subscriberid)
inner join lists l
on ls.listid = l.listid
where l.name = 'My Contacts'
and t0.fieldid = 2
and t1.fieldid = 3;
EOS
end
end
Le istanze di contatto avranno #FirstName e #LastName come attributi. Si potrebbe rinominare loro come AR si aspetta troppo, in modo tale che #first_name e #last_name avrebbe funzionato. È sufficiente modificare le clausole durante la vostra SELECT.
Altri suggerimenti
Io non sono sicuro che è totalmente germano alla tua domanda, ma si potrebbe desiderare di dare un'occhiata a MagicModel . E 'in grado di generare modelli per, sulla base di un database legacy. Potrebbe abbassare la quantità di lavoro che devi fare.