Stockage des différents formats de données dans Rails définies dynamiquement par admin
-
26-09-2019 - |
Question
Je suis face à un problème où je ne peux pas décider de façon permanente les colonnes un de mes modèles auront. Un cas d'utilisation sera ceci:
Un administrateur crée un nouvel ensemble de données, il souhaite que les utilisateurs de répondre. Dans l'ensemble de données définit l'administrateur plusieurs points de données de différents formats et unités.
Je pourrais imaginer les classes pour ressembler à ceci:
class Dataset < ActiveRecord::Base
has_many :measurements
has_many :profiles, :through => :measurements
has_many :datapoints, :through => :dataset_datapoint
end
# Join table
class Dataset_datapoint < ActiveRecord::Base
belongs_to :dataset
belongs_to :datapoint
end
class Datapoint < ActiveRecord::Base
has_many :dataset, :through => :dataset_datapoint
has_many :data
# create_table "datapoints" do |t|
# t.string :name
# t.string :format # e.g. string, decimal etc.
# t.string :unit # e.g. CM, pounds etc.
end
class Data < ActiveRecord::Base
belongs_to :datapoint
# create_table "data" do |t|
# t.integer :datapoint_id
# t.string :value # This column could be anything from string to decimal
end
Dans ma tête, cela semble assez dynamique, mais encore assez facile à mettre en œuvre. Ce que je suis inquiet, est de savoir comment faire la validation sur tous les modèles de données qui est créé? Puisque je ne peux pas hardcode la validation dans le modèle? Et pour le rendre encore plus compliqué, si certains ont besoin datapoints supplémentaires, comme des validations comme valeur minimale et maximale?
Merci d'avance, Jonas
La solution
Vous devez énumérer la liste des validations disponibles.
Ensuite, vous pouvez créer un modèle de validation et de la table (et peut-être une table de jointure si vous souhaitez que les utilisateurs soient en mesure de réutiliser leurs validations - dépend de vos cas d'utilisation):
class Validation < ActiveRecord::Base
belongs_to :dataset
# create_table 'validations' do |t|
# t.references :dataset
# t.string :type
# ... and columns for each restriction you could apply, ie:
# t.integer :max_value
# t.integer :min_value
# t.string :regexp
# ...etc...
end
Ensuite, dans votre modèle data
, ajouter un filtre before_save
pour appeler votre méthode de validation personnalisée:
class Data < ActiveRecord::Base
belongs_to :datapoint
has_many :validations, :through => :datapoint
before_save :custom_validation
private
def custom_validation
validations.each do |validation|
if validation.type == 'integer_range'
unless value < validation.max_value and value > validation.min_value
# return false, or add an error on the value attribute, or whatever
end
# More validations here - use a case statement probably
end
end
end
Je ne sais pas si j'ai vos relations exactement compris, mais quelque chose comme cela devrait vous donner un point de départ.