:has_many vers différents modèles

Bonjour,

J’ai besoin de votre aide pour un problème de conception.

Je veux faire une interface pour visualiser des logs de différentes
sondes (relevé de température, d’humidité, sonde d’interruption). Les
données sont transmises directement par les sondes dans plusieurs table
MySQL (une table pour chaque type de logs). Comme les sondes elles-même
ont toutes les même spécifications, j’ai créé une seule table pour les
représenter.

J’ai donc un modèle Sensor qui possède plusieurs logs dans différents
modèles (TemperatureLog, HumidityLog, etc.).

Ma question est comment puis-je, dans le modèle Sensor, indiquer dans
quel modèle de Log (donc dans quelle table) aller chercher mes données.
J’ai regardé du côté des associations polymorphiques, mais je ne suis
pas sûr que ça puisse fonctionner dans ce sens.

Bref, vos avis ou votre aide et la bienvenue.

Merci d’avance,
Nicolas

Le 06/01/10 08:23, Liste diff a écrit :

Bref, vos avis ou votre aide et la bienvenue.

Merci d’avance,
Nicolas

Une des techniques simple est :

class TemperatureLog < SensorLog
end

class HumidityLog < SensorLog
end

class Sensor
has_many :temperatures,
:conditions => ‘type = TemperatureLog’,
:class_name => “TemperatureLog”,
:foreign_key => “sensor_id”

has_many :humidities,
:conditions => ‘type = HumidityLog’,
:class_name => “HumidityLog”,
:foreign_key => “sensor_id”
end

Merci Cyril de ta réponse, mais ce que j’aimerai faire est du genre:

@logs = sensor.logs

sans me soucier du genre de log à récupérer. Le choix de la table doit
se faire automatiquement. Je n’ai pas de moyen de changer le schéma de
la table des logs, mais je peux introduire un type de sonde.

Y-a-t’il une solution, en spécifiant le type de log dans mon modèle
Sensor, de retrouver le modèle qui correspond au logs de la sonde
spécifique?

Désolé pour ces questions sans doute basique, mais je suis novice en
Rails.

Cordialement,
Nicolas

Le 6 janv. 2010 à 10:54, Cyril M. a écrit :

Le 07/01/10 07:23, Liste diff a écrit :

Merci Cyril de ta réponse, mais ce que j’aimerai faire est du genre:

@logs = sensor.logs

sans me soucier du genre de log à récupérer. Le choix de la table doit se faire automatiquement. Je n’ai pas de moyen de changer le schéma de la table des logs, mais je peux introduire un type de sonde.

Y-a-t’il une solution, en spécifiant le type de log dans mon modèle Sensor, de retrouver le modèle qui correspond au logs de la sonde spécifique?

Désolé pour ces questions sans doute basique, mais je suis novice en Rails.

Dans ce cas un simple has_many :logs suffit

class SensorLog < ActiveRecord::Base
end

class TemperatureLog < SensorLog
end

class HumidityLog < SensorLog
end

class Sensor
has_many :logs,
:class_name => “SensorLog”,
:foreign_key => “sensor_id”
end

Lorsque tu feras sensor.logs tu auras une liste de SensorLog
indépendamment de leur Type.

A tester, mais je crois même que le cast de la sous-classe se fait
automatiquement. Sinon, il suffit de faire une mini-méthode dans
SensorLog qui check le type et cast dans la bonne classe.

Le 07/01/10 11:49, Liste diff a écrit :

En fait je n’ai pas de modèle SensorLog.
J’aimerai pouvoir, directement à partir de mon modèle Sensor déterminer sur quelle modèle (TemperatureLog, HumidityLog, etc.) me connecter pour extraire les logs correspondant au type de sonde. Il me semble que ça doit pas être sorcier, mais je m’en sort pas. Je dois sans doute réviser les bases d’ActiveRecord :wink:

HumidityLog et TemperatureLog sont dans la même table ou pas ?

En fait je n’ai pas de modèle SensorLog.
J’aimerai pouvoir, directement à partir de mon modèle Sensor déterminer
sur quelle modèle (TemperatureLog, HumidityLog, etc.) me connecter pour
extraire les logs correspondant au type de sonde. Il me semble que ça
doit pas être sorcier, mais je m’en sort pas. Je dois sans doute réviser
les bases d’ActiveRecord :wink:

Nicolas

Le 7 janv. 2010 à 11:09, Cyril M. a écrit :

Non, ce sont 2 tables séparées. Les logs sont directement générés par
des sondes physiques. Les sondes de températures envoient leurs mesures
de température à la table temperature_logs et les sondes d’humidité Ã
humidity_logs. Il y a également d’autres sondes qui envoient d’autres
valeurs.

L’application que je dois créer consiste à détecter les logs d’une sonde
qui vient d’être mise en service et de permettre à l’utilisateur de
donner un nom à cette sonde (dans la table sensors). Cette table est la
même pour tous les logs, car les caractéristiques de toutes les sondes
sont identiques.

Je veux ensuite pouvoir afficher les logs d’une sonde en faisant
logs = Sensor.find(1).logs
Dans la table sensors, je connais le type de sonde, je dois donc pouvoir
faire une requête sur la bonne table. Malheureusement je ne maîtrise pas
assez ActiveRecord et ruby pour savoir de quelle manière.

Merci de ton aide,
Nicolas

Le 7 janv. 2010 à 12:02, Cyril M. a écrit :

Le 07/01/10 12:38, Liste diff a écrit :

Non, ce sont 2 tables séparées. Les logs sont directement générés par des sondes physiques. Les sondes de températures envoient leurs mesures de température à la table temperature_logs et les sondes d’humidité à humidity_logs. Il y a également d’autres sondes qui envoient d’autres valeurs.

L’application que je dois créer consiste à détecter les logs d’une sonde qui vient d’être mise en service et de permettre à l’utilisateur de donner un nom à cette sonde (dans la table sensors). Cette table est la même pour tous les logs, car les caractéristiques de toutes les sondes sont identiques.

Je veux ensuite pouvoir afficher les logs d’une sonde en faisant
logs = Sensor.find(1).logs
Dans la table sensors, je connais le type de sonde, je dois donc pouvoir faire une requête sur la bonne table. Malheureusement je ne maîtrise pas assez ActiveRecord et ruby pour savoir de quelle manière.

Dans ton cas il faut se palucher les requêtes à la main alors.

def logs
humiditylogs + temperaturelogs
end

Bien sûr tu récupéreras tout d’un coup. Il faut donc gérer au cas pas
cas de tes besoins. Le schéma que tu as n’es pas adapté à ta logique. En
effet, tu as les même donnée dans des tables différentes. C’est donc de
la dé-normalisation. Je suis pour la dé-normalisation en terme de
performance, mais forcement, cela implique plus de code à écrire car la
dé-normalisation est comme elle l’indique, contraire au règle. Le
contraire au règle implique forcement une logique qui t’es personnel ou
tout du moins à ton cas précis.

Le 07/01/10 14:06, Liste diff a écrit :

cas de tes besoins. Le schéma que tu as n’es pas adapté à ta logique. En
effet, tu as les même donnée dans des tables différentes. C’est donc de
la dé-normalisation. Je suis pour la dé-normalisation en terme de
performance, mais forcement, cela implique plus de code à écrire car la
dé-normalisation est comme elle l’indique, contraire au règle. Le
contraire au règle implique forcement une logique qui t’es personnel ou
tout du moins à ton cas précis.

Les tables de logs sont toutes différentes, avec un nombre de champs variable en fonction du type de sonde. Il me semble donc judicieux d’utiliser des tables différentes. Mais je peux me tromper et suis ouvert à une meilleure proposition.

C’est judicieux en terme de performance. En terme de normalisation,
c’est pas évident. Ça dépend de ton cas.

Rails n’est qu’une aide a faire plus rapidement des cas plus ou moins
simple. Il ne faut pas forcement essayer de rentrer à tous les coups
dans le moule.

Ok, je vais voir quel est le design le plus approprié et j’adapterai mon
code Rails en fonction.

Merci beaucoup pour ton aide et ta patience,
Nicolas

Le 7 janv. 2010 à 14:17, Cyril M. a écrit :

Le 7 janv. 2010 à 12:44, Cyril M. a écrit :

performance, mais forcement, cela implique plus de code à écrire car la
dé-normalisation est comme elle l’indique, contraire au règle. Le
contraire au règle implique forcement une logique qui t’es personnel ou
tout du moins à ton cas précis.

Les tables de logs sont toutes différentes, avec un nombre de champs
variable en fonction du type de sonde. Il me semble donc judicieux
d’utiliser des tables différentes. Mais je peux me tromper et suis
ouvert à une meilleure proposition.