Class: Clir::DataManager::Manager
- Inherits:
-
Object
- Object
- Clir::DataManager::Manager
- Defined in:
- lib/clir/data_manager/Manager.rb,
lib/clir/data_manager/Editor.rb,
lib/clir/data_manager/Displayer.rb,
lib/clir/data_manager/Validator.rb
Overview
/<< self module
Defined Under Namespace
Classes: Displayer, Editor, Validator
Instance Attribute Summary collapse
-
#classe ⇒ Object
readonly
Returns the value of attribute classe.
-
#data_properties ⇒ Object
readonly
Returns the value of attribute data_properties.
-
#items ⇒ Object
readonly
Returns the value of attribute items.
Class Method Summary collapse
Instance Method Summary collapse
-
#__last_id ⇒ Integer
Last used ID for objet/instance.
-
#__new_id ⇒ Object
Méthode qui retourne un nouvel identifiant pour la classe propriétaire.
- #add(item) ⇒ Object
-
#choose(**options) ⇒ Object
Permet de choisir une instance.
-
#choose_in_list_of_grouped_items(group, options) ⇒ Any
Any instance chosen in
group
. - #choose_precedence_set(id) ⇒ Object
-
#class_name ⇒ Object
Le nom simple de la classe propriétaire, sans module.
-
#create(instance, options = nil) ⇒ Object
To create a instance.
- #display(instance, options = nil) ⇒ Object
-
#display_items(options = nil) ⇒ Object
Pour afficher des items les uns sur les autres, avec des informations réduites.
-
#each_property(&block) ⇒ Object
Loop on every property (as instances).
- #edit(instance, options = nil) ⇒ Object
-
#ensure_last_id_by_card(sid) ⇒ Integer
Méthode qui s’assure de retourner un identifiant qui n’existe vraiment pas.
-
#filter_items_of_list(list, options = nil) ⇒ Array
Filtre la liste
list
avec le filtreoptions[:filter]
s’il existe. -
#full_loaded? ⇒ Boolean
Pour savoir si toutes les données sont chargées.
-
#get(item_id) ⇒ Any
Any instance with ID
item_id
. -
#get_choices_with_precedences(options) ⇒ Array
pour choisir une instance de la classe.
-
#get_classe_from(class_min) ⇒ Object
Reçoit quelque chose comme ‘edic_test_class’ et retourne Edic::TestClass en mémorisant pour accélérer le processus.
-
#get_default_choices(cs, options) ⇒ Object
Les sélectionnés sont définis par leur identifiant dans options.
-
#group_items_of_list(list, options = nil) ⇒ Array
Groupe les éléments dans la liste
list
suivant la variable de classe @@group_by ouoptions[:group_by]
. -
#initialize(classe, data_properties = nil) ⇒ Manager
constructor
A new instance of Manager.
-
#item_match_filter?(item, filter) ⇒ Boolean
filter
. - #items_grouped_by ⇒ Object
-
#last_id_path ⇒ Object
— Path Methods —.
-
#load_data ⇒ Object
— Data Methods —.
- #load_data_from_cards ⇒ Object
- #load_data_from_uniq_file ⇒ Object
-
#owner_class_valid? ⇒ Boolean
True si la classe propriétaire est valide.
- #precedence_ids ⇒ Object
- #precedence_list ⇒ Object
- #prepare_class_methods ⇒ Object
-
#prepare_instance_methods_of_class ⇒ Object
Add instance methods to managed class (:create, :edit, :display and :remove/:destroy).
- #prepare_properties_methods ⇒ Object
- #prepare_save_methods ⇒ Object
-
#properties ⇒ Array<Property>
All data properties as instance.
- #remove(instances, options = nil) ⇒ Object
-
#save_all ⇒ Object
Méthode principale du manager, quand le :save_system est :file, qui enregistre toutes les données.
- #save_format ⇒ Object
- #save_location ⇒ Object
- #save_system ⇒ Object
-
#table_properties ⇒ Hash
is DataManager::Property instance.
- #tmp_folder ⇒ Object
- #traite_property_as_other_class_instance(dproperty) ⇒ Object
-
#tty_name_for(item, options) ⇒ Object
Le string à utiliser pour l’attribut :name de TTY prompt.
- #validator ⇒ Object
Constructor Details
#initialize(classe, data_properties = nil) ⇒ Manager
Returns a new instance of Manager.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/clir/data_manager/Manager.rb', line 84 def initialize(classe, data_properties = nil) @data_properties = data_properties || begin defined?(classe::DATA_PROPERTIES) || raise(ERRORS[:require_data_properties] % classe.name) classe::DATA_PROPERTIES end @classe = classe # # Pour que rubocop ne râle pas… # @table = nil @is_full_loaded = false # # Méthodes d'instance # prepare_instance_methods_of_class # # Méthodes de classe # prepare_class_methods # # On doit s'assurer que la class propriétaire du manager est # valide, c'est-à-dire définit et contient tous les éléments # nécessaires. # owner_class_valid? || raise(ExitSilently) # # On doit s'assurer que la classe définit bien son système de # sauvegarde et son lieu de sauvegarde # end |
Instance Attribute Details
#classe ⇒ Object (readonly)
Returns the value of attribute classe.
80 81 82 |
# File 'lib/clir/data_manager/Manager.rb', line 80 def classe @classe end |
#data_properties ⇒ Object (readonly)
Returns the value of attribute data_properties.
81 82 83 |
# File 'lib/clir/data_manager/Manager.rb', line 81 def data_properties @data_properties end |
#items ⇒ Object (readonly)
Returns the value of attribute items.
82 83 84 |
# File 'lib/clir/data_manager/Manager.rb', line 82 def items @items end |
Class Method Details
.get_class_from_class_mmin(class_min) ⇒ Object
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 |
# File 'lib/clir/data_manager/Manager.rb', line 690 def self.get_class_from_class_mmin(class_min) @@class4classMin ||= {} @@class4classMin[class_min] ||= begin dclass = class_min.split('_').map{|n|n.titleize} cc = Object # la classe courante en tant que classe ss = nil # le string courant en tan que classe en recherche while dclass.count > 0 x = dclass.shift # puts "Étude de dclass.shift = #{x.inspect}" if cc.const_defined?(x) cc = cc.const_get(x) # => class x = nil elsif ss.nil? ss = x elsif ss != nil if cc.const_defined?(ss + x) cc = cc.const_get(ss + x) ss = nil else ss = ss + x # => "Data" + "Manager" => "DataManager" # Et on poursuit end end end cc = nil if cc == Object if cc.nil? raise ERRORS[:unable_to_get_class_from_class_min] % [class_min, "."] elsif not(x.nil?) || not(ss.nil?) raise ERRORS[:unable_to_get_class_from_class_min] % [class_min, " : #{MSG[:not_treated] % "#{x}#{ss}".inspect}."] end cc end end |
Instance Method Details
#__last_id ⇒ Integer
Returns Last used ID for objet/instance.
71 72 73 74 75 76 77 78 |
# File 'lib/clir/data_manager/Manager.rb', line 71 def __last_id if File.exist?(last_id_path) File.read(last_id_path).strip.to_i else mkdir(File.dirname(last_id_path)) # to make sure folder exists 0 end end |
#__new_id ⇒ Object
Méthode qui retourne un nouvel identifiant pour la classe propriétaire.
Suivant le type de données, on trouve le dernier identifiant :
- dans un fichier contenant les informations générales sur
la classe d'objets
- en relevant les ID d'un fichier YAML et en prenant le
dernier.
- en fouillant dans un dossier de fiches pour trouver la
dernière.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/clir/data_manager/Manager.rb', line 30 def __new_id case save_system when :card id = ensure_last_id_by_card(__last_id + 1) # # On peut enregistrer le nouvel identifiant # File.write(last_id_path, id.to_s) return id when :file, :csv @last_id || begin load_data @last_id end return @last_id += 1 when :conf puts "Je ne sais pas encore gérer le système de sauvegarde :conf.".orange raise(ExitSilently) end end |
#add(item) ⇒ Object
147 148 149 150 151 152 153 |
# File 'lib/clir/data_manager/Manager.rb', line 147 def add(item) item.data.merge!(id: __new_id) if item.data[:id].nil? @items ||= [] @items << item @table ||= {} @table.merge!(item.id => item) end |
#choose(**options) ⇒ Object
Permet de choisir une instance
Par défaut, c’est la deuxième propriété qui est utilisée pour l’affichage (sa version “formatée” si elle existe) mais les options fournies peuvent définir une autre propriété avec l’at- tribut :name_property
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/clir/data_manager/Manager.rb', line 176 def choose(**) # # Définition des options # .key?(:multi) || .merge!(multi: false) [:question] ||= "#{MSG[:choose]} : " [:question] = [:question].jaune load_data unless full_loaded? @tty_name_procedure = nil # # Définition des menus # # Soit par précédences, soit par classement si options[:sort_key] # est défini. # cs = get_choices_with_precedences() # # Interaction # if [:multi] # # Menus sélectionnés par défaut # selecteds = nil selecteds = get_default_choices(cs, ) if [:default] # # L'utilisateur procède aux choix # choixs = Q.multi_select([:question], cs, {per_page: ([:per_page] || cs.count), filter:true, default: selecteds, echo:false}) if choixs.include?(:create) choixs.delete(:create) choixs << classe.new.create end # # Enregistrement de la précédence # choixs = choixs.map do |choix| next if choix.nil? if choix.instance_of?(GroupedItems) choix = choose_in_list_of_grouped_items(choix, ) choose_precedence_set("G#{choix.id}") else choose_precedence_set(choix.id) end choix end.compact # # Instances retournées # choixs else # # L'utilisateur procède au choix # choix = Q.select([:question], cs, {per_page: 20, filter:true, show_help:false}) choix = classe.new.create if choix == :create choix || return # cancel return :complete if choix == :complete choose_precedence_set(choix.id) # # Si c'est une liste d'items groupés, il faut encore choisir # dans cette liste l'item qui sera renvoyé. Sinon, on retourne # l'item choisi. # if choix.instance_of?(GroupedItems) choix = choose_in_list_of_grouped_items(choix, ) end choix end end |
#choose_in_list_of_grouped_items(group, options) ⇒ Any
Returns Any instance chosen in group
.
250 251 252 253 254 255 |
# File 'lib/clir/data_manager/Manager.rb', line 250 def choose_in_list_of_grouped_items(group, ) choices = group.items.map do |item| {name: item.best_name, value: item} end + [CHOIX_RENONCER] Q.select([:question], choices, {per_page:choices.count, show_help:false, echo:false}) end |
#choose_precedence_set(id) ⇒ Object
354 355 356 357 358 359 |
# File 'lib/clir/data_manager/Manager.rb', line 354 def choose_precedence_set(id) precedence_ids.delete(id) precedence_ids.unshift(id) mkdir(tmp_folder) File.write(precedence_list, precedence_ids.join(' ')) end |
#class_name ⇒ Object
Le nom simple de la classe propriétaire, sans module
725 726 727 |
# File 'lib/clir/data_manager/Manager.rb', line 725 def class_name @class_name ||= classe.name.to_s.split('::').last end |
#create(instance, options = nil) ⇒ Object
To create a instance
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 |
# File 'lib/clir/data_manager/Manager.rb', line 1006 def create(instance, = nil) data = instance.before_create if instance.respond_to?(:before_create) instance.data = data || {id: __new_id} instance.data.merge!(is_new: true) edit(instance, ) if not(instance.new?) # => bien créé key = classe.feminine? ? :item_created_fem : :item_created puts (MSG[key] % {element: class_name}).vert instance.after_create if instance.respond_to?(:after_create) end return instance # chainage end |
#display(instance, options = nil) ⇒ Object
1032 1033 1034 1035 1036 1037 1038 |
# File 'lib/clir/data_manager/Manager.rb', line 1032 def display(instance, = nil) @displayer ||= Displayer.new(self) = instance.before_display() if instance.respond_to?(:before_display) @displayer.show(instance, ) instance.after_display if instance.respond_to?(:after_display) return instance # chainage end |
#display_items(options = nil) ⇒ Object
Pour afficher des items les uns sur les autres, avec des informations réduites.
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/clir/data_manager/Manager.rb', line 269 def display_items( = nil) ||= {} full_loaded? || load_data # # Dans le cas d'absence d'items # @items.count > 0 || begin puts MSG[:no_items_to_display].orange return end # # Filtrage de la liste (s'il le faut) # if not(.key?(:filter)) && [:periode] .merge!(filter: {}) end [:filter].merge!(periode: [:periode]) if [:periode] disp_items = filter_items_of_list(@items, ) # # Classement des items si nécessaire # if .key?(:sort_key) && [:sort_key] sort_key = [:sort_key] if disp_items.first.respond_to?(sort_key) begin disp_items = disp_items.sort do |a, b| a.send(sort_key) <=> b.send(sort_key) end disp_items = disp_items.reverse if [:sort_dir].to_s == 'asc' rescue Exception => e puts "Classement impossible (avec la clé de classement #{sort_key.inspect}) : #{e.}".rouge sleep 4 end else # # Clé inconnue # puts "Pour classer par la clé #{sort_key.inspect} il faudrait que les items la reconnaissent.".rouge end end # # Procédure qui permet de récupérer la liste des données pour # l'affichage tabulaire des éléments # header = [] tableizable_props = [] properties.each do |property| if property.tablizable? header << (property.short_name||property.name) tableizable_props << property end end tbl = Clir::Table.new(**{ title: "AFFICHAGE DES #{class_name}S", header: header }) disp_items.each do |item| tbl << tableizable_props.map do |property| property.formated_value_in(item) || '---' end end clear unless debug? tbl.display end |
#each_property(&block) ⇒ Object
Loop on every property (as instances)
1094 1095 1096 1097 1098 1099 1100 |
# File 'lib/clir/data_manager/Manager.rb', line 1094 def each_property(&block) if block_given? properties.each do |property| yield property end end end |
#edit(instance, options = nil) ⇒ Object
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 |
# File 'lib/clir/data_manager/Manager.rb', line 1019 def edit(instance, = nil) @editor ||= Editor.new(self) is_new_item = instance.data[:is_new] instance.before_edit if instance.respond_to?(:before_edit) @editor.edit(instance, ) instance.after_edit if instance.respond_to?(:after_edit) unless is_new_item key = classe.feminine? ? :item_updated_fem : :item_updated puts (MSG[key] % [class_name, instance.id]).vert end return instance # chainage end |
#ensure_last_id_by_card(sid) ⇒ Integer
Méthode qui s’assure de retourner un identifiant qui n’existe vraiment pas.
Il peut arriver que l’utitilisateur ajoute des données à la main (par fiche), il faut donc s’assurer que cet identifiant est bien inusité
60 61 62 63 64 65 66 67 68 |
# File 'lib/clir/data_manager/Manager.rb', line 60 def ensure_last_id_by_card(sid) case save_format when :yaml sid += 1 while File.exist?(File.join(save_location,"#{sid}.yaml")) else raise "Je ne sais pas traiter le format #{save_format.inspect}…" end return sid end |
#filter_items_of_list(list, options = nil) ⇒ Array
Filtre la liste list
avec le filtre options[:filter]
s’il existe.
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 |
# File 'lib/clir/data_manager/Manager.rb', line 458 def filter_items_of_list(list, = nil) return list unless && [:filter] # # Duplication pour pouvoir le modifier # option_filter = [:filter].dup # # Préparer éventuellement certaines valeurs du filtre # option_filter.each do |k, v| case k when :periode # # Si une période est déterminée, il faut ajouter cette condition # au filtre. # # L'idée c'est de déterminer que le temps de l'item doit être # supérieur ou égal au temps de départ de la période et doit # être inférieur ou égal au temps de fin de la période. # Le tout est de savoir quel temps prendre en compte. On # cherche dans cet ordre # :date, :created_at, :time # Pour le savoir on prend le premier élément, qui existe # forcément. item1 = list.first time_prop = if item1.respond_to?(:date) :date elsif item1.respond_to?(:created_at) :created_at elsif item1.respond_to?(:time) :time elsif not(time_property) time_property else raise ERRORS[:no_time_property] % ["#{classe.class}"] end # On prend la période en la retirant du filtre periode = [:filter].delete(:periode) # Et on ajoute la condition sur le temps [:filter].merge!( time_prop => Proc.new { |inst| periode.time_in?(inst.send(time_prop) ) } ) end #/case k end # # Sélectionner les items valides # list.select do |item| item_match_filter?(item, [:filter]) end end |
#full_loaded? ⇒ Boolean
Pour savoir si toutes les données sont chargées
677 678 679 |
# File 'lib/clir/data_manager/Manager.rb', line 677 def full_loaded? @is_full_loaded === true end |
#get(item_id) ⇒ Any
Returns Any instance with ID item_id
.
803 804 805 806 807 808 809 810 811 812 |
# File 'lib/clir/data_manager/Manager.rb', line 803 def get(item_id) item_id = item_id.to_i @table ||= {} @table[item_id] || begin # La table, même si elle a déjà été chargée, peut peut-être # avoir besoin d'être rechargée load_data end @table[item_id] end |
#get_choices_with_precedences(options) ⇒ Array
La liste de précédence se fiche de savoir s’il s’agit d’un item ou d’un groupement d’items. Pour le moment, ça signifie que l’item enregistré dans la liste de précédences ne sera pas le bon.
pour choisir une instance de la classe.
Cette liste tient compte de la variable @@group_by de la classe, qui détermine les regroupements de données à effectuer.
La méthode retourne aussi une liste avec ITEMS CLASSÉS PAR PRÉCÉDENCES aux conditions suivantes :
SI la liste de précédence existe.
SI les options ne contiennent pas :sort_key, une clé de
classement des items.
Donc une liste :
- items groupés par @@group_by
- items classés par liste de précédence.
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
# File 'lib/clir/data_manager/Manager.rb', line 403 def get_choices_with_precedences() # # La liste au départ # list = @items # # Filtrer la liste si nécessaire # list = filter_items_of_list(list, ) # # Grouper les éléments si nécessaire # list = group_items_of_list(list, ) # # Quand on a la liste finale, on peut régler la précédence si # elle est définie OU classer la liste si une clé de classement # est définie (:sort_key et :sort_dir) # if [:sort_key] list.sort! do |a, b| a.send([:sort_key]) <=> b.send([:sort_key]) end list.reverse! if [:sort_dir] == 'desc' else if File.exist?(precedence_list) # puts "Classement par rapport à la liste : #{precedence_list.inspect}".jaune # sleep 4 list.sort! do |a, b| (precedence_ids.index(a.id)||10000) <=> (precedence_ids.index(b.id)||10000) end end end # # On retourne des menus pour TTY-Prompt # cs = list.map do |item| {name: tty_name_for(item, ), value: item} end cs.unshift(CHOIX_CREATE) if [:create] cs.push({name:MSG[:finir].bleu, value: :complete}) if [:finir]||[:complete] cs.push(CHOIX_RENONCER) return cs end |
#get_classe_from(class_min) ⇒ Object
Reçoit quelque chose comme ‘edic_test_class’ et retourne Edic::TestClass en mémorisant pour accélérer le processus
687 688 689 |
# File 'lib/clir/data_manager/Manager.rb', line 687 def get_classe_from(class_min) return self.class.get_class_from_class_mmin(class_min) end |
#get_default_choices(cs, options) ⇒ Object
Les sélectionnés sont définis par leur identifiant dans options
345 346 347 348 349 350 351 352 |
# File 'lib/clir/data_manager/Manager.rb', line 345 def get_default_choices(cs, ) selecteds = [:default] ids_sels = [] cs.each_with_index do |, idx| ids_sels << (idx + 1) if selecteds.include?([:value]) end return ids_sels end |
#group_items_of_list(list, options = nil) ⇒ Array
Cf. le manuel pour le détail de l’utilisation.
Groupe les éléments dans la liste list
suivant la variable de classe @@group_by ou options[:group_by]
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 |
# File 'lib/clir/data_manager/Manager.rb', line 518 def group_items_of_list(list, = nil) return list if [:group_by].nil? && items_grouped_by.nil? # # La clé de groupement # groupby = [:group_by] || items_grouped_by # # La clé de groupe fait-elle référence à une classe relative ? # is_relative_class = groupby.to_s.match?(/_ids?$/) # # Table des groupes initiés # groups = {} # # La liste finale qui contiendra les nouveaux éléments # final_list = [] # # On boucle sur la liste en groupant # list.each do |item| if (group_id = item.send(groupby)) # # Si ce groupe n'existe pas, on le crée # unless groups.key?(group_id) # # Le nom que prendra le groupe # property = table_properties[groupby] nom = if is_relative_class property.relative_class.get(group_id).name else property.name end group = GroupedItems.new(nom, group_id, []) groups.merge!(group_id => group) final_list << group end groups[group_id].items << item else # # Si l'item ne répond pas à la propriété de classement, on # le met tel quel # final_list << item end end # # On retourne la liste finale # return final_list end |
#item_match_filter?(item, filter) ⇒ Boolean
filter
581 582 583 584 585 586 587 588 589 590 591 |
# File 'lib/clir/data_manager/Manager.rb', line 581 def item_match_filter?(item, filter) filter.each do |key, expected| case expected when Proc return false if not(expected.call(item)) else return false if item.send(key) != expected end end return true end |
#items_grouped_by ⇒ Object
666 667 668 669 670 671 672 |
# File 'lib/clir/data_manager/Manager.rb', line 666 def items_grouped_by @items_grouped_by ||= begin if classe.class_variables.include?(:'@@group_by') classe.class_variable_get('@@group_by') end end end |
#last_id_path ⇒ Object
— Path Methods —
1177 1178 1179 1180 1181 |
# File 'lib/clir/data_manager/Manager.rb', line 1177 def last_id_path @last_id_path ||= begin File.join(mkdir(save_location),"LASTID") end end |
#load_data ⇒ Object
— Data Methods —
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 |
# File 'lib/clir/data_manager/Manager.rb', line 1134 def load_data @table = {} @items = [] @last_id = 0 case save_system when :card load_data_from_cards when :file load_data_from_uniq_file end.each do |ditem| inst = classe.new(ditem) @table.merge!(inst.id => inst) @items << inst @last_id = 0 + inst.id if inst.id > @last_id end @is_full_loaded = true end |
#load_data_from_cards ⇒ Object
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 |
# File 'lib/clir/data_manager/Manager.rb', line 1164 def load_data_from_cards Dir["#{save_location}/*.#{save_format}"].map do |pth| case save_format when :yaml YAML.safe_load(IO.read(pth), **YAML_OPTIONS) else raise "Format de fiche inconnue : #{save_format}" end end end |
#load_data_from_uniq_file ⇒ Object
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 |
# File 'lib/clir/data_manager/Manager.rb', line 1152 def load_data_from_uniq_file if File.exist?(save_location) case save_format when :yaml YAML.safe_load(IO.read(save_location), **YAML_OPTIONS) when :csv CSV.read(save_location) end else [] end end |
#owner_class_valid? ⇒ Boolean
Returns true si la classe propriétaire est valide.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/clir/data_manager/Manager.rb', line 116 def owner_class_valid? classe.class_variable_defined?("@@save_system") || raise(ERRORS[:require_save_system] % classe.name) classe.class_variable_defined?('@@save_location') || raise(ERRORS[:require_save_location] % classe.name) classe.class_variable_defined?('@@save_format') || raise(ERRORS[:require_save_format] % classe.name) [:card,:file,:conf].include?(save_system) || raise(ERRORS[:bad_save_system] % classe.name) [:csv, :yaml].include?(save_format) || raise(ERRORS[:bas_save_format] % classe.name) if save_system == :card && save_format == :csv raise(ERRORS[:no_csv_format_with_card]) end if File.exist?(save_location) if save_system == :card File.directory?(save_location) || raise(ERRORS[:require_save_location_folder] % classe.name) else File.directory?(save_location) && raise(ERRORS[:require_save_location_file] % classe.name) end end # # Si c'est un système d'enregistrement par fiche, on prépare # déjà le fichier du dernier identifiant. # if save_system == :card File.write(last_id_path,"0") unless File.exist?(last_id_path) end rescue Exception => e puts "\n#{e.}\n".rouge return false else return true end |
#precedence_ids ⇒ Object
361 362 363 364 365 366 367 |
# File 'lib/clir/data_manager/Manager.rb', line 361 def precedence_ids @precedence_ids ||= begin if File.exist?(precedence_list) File.read(precedence_list).split(' ').map(&:to_i) else [] end end end |
#precedence_list ⇒ Object
369 370 371 |
# File 'lib/clir/data_manager/Manager.rb', line 369 def precedence_list @precedence_list ||= File.join(tmp_folder, "#{classe.name.to_s.gsub(/::/,'_').downcase}.precedences") end |
#prepare_class_methods ⇒ Object
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 |
# File 'lib/clir/data_manager/Manager.rb', line 733 def prepare_class_methods my = self classe.define_singleton_method 'data_manager' do return my end classe.define_singleton_method 'save_location' do return my.save_location end classe.define_singleton_method 'items' do | = nil| my.load_data if not(my.full_loaded?) if .nil? my.items else get() end end classe.define_singleton_method 'table' do my.full_loaded? || my.load_data my.instance_variable_get("@table") end classe.define_singleton_method 'get' do |item_id| data_manager.get(item_id) end classe.define_singleton_method 'last_id' do return my.__last_id end classe.define_singleton_method 'class_name' do my.class_name end classe.define_singleton_method 'count' do get_all.count end classe.define_singleton_method 'get_all' do | = nil| my.load_data if not(my.full_loaded?) my.filter_items_of_list(my.items, || {}) end classe.define_singleton_method 'select' do |filter, = nil| ||= {} .merge!({filter: filter}) get_all() end classe.class_eval do class << self alias :filter :select end end # classe.define_singleton_method 'filter' do |options = nil| # alias # return get_all(options) # end classe.define_singleton_method 'display' do | = nil| my.display_items() end classe.define_singleton_method 'remove' do |instances, = nil| my.remove(instances, ) end if classe.methods.include?(:choose) # Rien à faire else classe.define_singleton_method 'choose' do | = nil| return my.choose() end end unless classe.respond_to?(:feminine?) classe.define_singleton_method 'feminine?' do return false end end end |
#prepare_instance_methods_of_class ⇒ Object
Add instance methods to managed class (:create, :edit, :display and :remove/:destroy)
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 |
# File 'lib/clir/data_manager/Manager.rb', line 818 def prepare_instance_methods_of_class my = self classe.define_method 'initialize' do |data = {}| @data = data end classe.define_method 'create' do | = {}| return my.create(self, ) end classe.define_method 'edit' do | = {}| return my.edit(self, ) end classe.define_method 'display' do | = {}| my.display(self, ) end classe.alias_method(:show, :display) classe.define_method 'remove' do | = {}| my.remove(self, ) end classe.alias_method(:destroy, :remove) classe.define_method 'data' do return @data end classe.define_method 'data=' do |value| @data = value end # @return [String] The best name for the object # @note # Managed class can define its own best_name method unless classe.instance_methods(false).include?(:best_name) classe.define_method 'best_name' do @best_name ||= begin bn = nil [:designation, :reference, :ref, :pretty_inspect, :titre, :full_name, :fullname ].each do |meth| bn = self.send(meth) and break if respond_to?(meth) end if bn.nil? if classe.instance_methods(false).include?(:inspect) self.inspect else "#{name} (##{id})" end else bn end end end end # # Quelques propriétés supplémentaires pour les instances # classe.define_method "new?" do return @data[:is_new] === true end prepare_save_methods prepare_properties_methods end |
#prepare_properties_methods ⇒ Object
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
# File 'lib/clir/data_manager/Manager.rb', line 932 def prepare_properties_methods # # Chaque propriété de DATA_PROPERTIES doit faire une méthode qui # permettra de récupérer et de définir la valeur # data_properties.each do |dproperty| prop = dproperty[:prop] classe.define_method "#{prop}" do return @data[prop] end classe.define_method "#{prop}=" do |value| @data.merge!( prop => value) end # # Propriétés spéciales qui se terminent par _id et sont des # liens avec une autre classe (typiquement : user_id pour faire # référence à un user {User}) # if prop.to_s.match?(/_ids?$/) traite_property_as_other_class_instance(dproperty) end end end |
#prepare_save_methods ⇒ Object
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 |
# File 'lib/clir/data_manager/Manager.rb', line 882 def prepare_save_methods my = self # # Méthode de sauvegarde, en fonction du système de sauvegarde # choisi. # case save_system when :card case save_format when :yaml classe.define_method "data_file" do @data_file ||= begin File.join(mkdir(my.save_location),"#{id}.yaml") end end classe.define_method "save" do if new? my.add(self) @data.delete(:is_new) end File.write(data_file, data.to_yaml) end end when :file case save_format when :yaml classe.define_method "save" do load_data unless my.full_loaded? if new? my.add(self) @data.delete(:is_new) end my.save_all end when :csv classe.define_method "save" do load_data unless my.full_loaded? if new? my.add(self) @data.delete(:is_new) end my.save_all end end when :conf raise "Je ne sais pas encore utiliser le système :conf de sauvegarde." end end |
#properties ⇒ Array<Property>
Also product @table_properties, a table with key = :prop and value is instance DataManager::Property
Returns All data properties as instance.
1107 1108 1109 1110 1111 1112 1113 1114 |
# File 'lib/clir/data_manager/Manager.rb', line 1107 def properties @properties ||= begin data_properties.map.with_index do |dproperty, idx| dproperty.merge!(index: idx) Property.new(self, dproperty) end end end |
#remove(instances, options = nil) ⇒ Object
Cette méthode est testée dans remove_test.rb
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 |
# File 'lib/clir/data_manager/Manager.rb', line 1043 def remove(instances, = nil) has_method_before = instances.first.respond_to?(:before_remove) has_method_after = instances.first.respond_to?(:after_remove) # # Tout charger si ça n'est pas encore fait full_loaded? || load_data # # Pour conserver les IDs supprimés et les supprimer plus # rapidement de @items # table_removed_ids = {} # # Boucle sur toutes les instances à détruire # instances.each do |instance| # Méthode avant ? instance.send(:before_remove) if has_method_before # # Si les instancences sont sauvées dans des cartes, il faut les # détruire # if save_system == :card File.delete(instance.data_file) if File.exist?(instance.data_file) end # # Pour pouvoir retirer l'instance de @items # table_removed_ids.merge!(instance.id => true) # # Retirer l'instance de @table # @table.delete(instance.id) # # Faut-il appeler une méthode après la destruction ? # instance.send(:after_remove) if has_method_after end #/fin boucle sur les instances à détruire # # On retire ces items de @items # @items.reject! { |item| table_removed_ids[item.id] } # # Si les données sont enregistrées dans un fichier, on les # sauve maintenant # save_all if save_system == :file return true end |
#save_all ⇒ Object
Méthode principale du manager, quand le :save_system est :file, qui enregistre toutes les données
643 644 645 646 647 648 649 650 651 652 653 654 655 |
# File 'lib/clir/data_manager/Manager.rb', line 643 def save_all case save_format when :yaml all_data = @items.map(&:data) File.write(save_location, all_data.to_yaml) when :csv CSV.open(save_location, 'wb') do |csv| @items.each do |item| csv << item.data end end end end |
#save_format ⇒ Object
663 664 665 |
# File 'lib/clir/data_manager/Manager.rb', line 663 def save_format classe.class_variable_get("@@save_format") end |
#save_location ⇒ Object
660 661 662 |
# File 'lib/clir/data_manager/Manager.rb', line 660 def save_location classe.class_variable_get("@@save_location") end |
#save_system ⇒ Object
657 658 659 |
# File 'lib/clir/data_manager/Manager.rb', line 657 def save_system classe.class_variable_get("@@save_system") end |
#table_properties ⇒ Hash
is DataManager::Property instance.
1118 1119 1120 1121 1122 1123 1124 |
# File 'lib/clir/data_manager/Manager.rb', line 1118 def table_properties @table_properties ||= begin tbl = {}; properties.each do |property| tbl.merge!(property.prop => property) end; tbl end end |
#tmp_folder ⇒ Object
373 374 375 |
# File 'lib/clir/data_manager/Manager.rb', line 373 def tmp_folder @tmp_folder ||= mkdir(File.join(APP_FOLDER,'tmp','precedences')) end |
#traite_property_as_other_class_instance(dproperty) ⇒ Object
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 |
# File 'lib/clir/data_manager/Manager.rb', line 957 def traite_property_as_other_class_instance(dproperty) prop = dproperty[:prop] last = prop.end_with?('_ids') ? -5 : -4 class_min = prop[0..last] other_class = get_classe_from(class_min) # other_class.respond_to?(:choose) || begin # raise "Impossible d'obtenir la classe relative #{class_min.inspect}. La classe calculée est #{other_class.name} qui ne répond pas à la méthode de classe :choose." # end # puts "other_classe avec #{class_min.inspect} : #{other_class}" # sleep 4 dproperty.merge!(relative_class: other_class) # # Les méthodes utiles pour la gestion de l'autre classe. # Note : une méthode différente suivant _id ou _ids # case true when prop.end_with?('_ids') classe.define_method "#{class_min}" do # p.e. def vente; instance_variable_get("@#{class_min}") || begin items = self.send(prop).map do |item_id| other_class.get(item_id) end instance_variable_set("@#{class_min}", items) end end when prop.end_with?('_id') # # @note # On ne va mettre la propriété @class_min de l'instance en # variable d'instance seulement si elle est définie. Dans le # cas contraire, une fois qu'elle est évaluée à nil, elle # resterait nil pour toujours… # classe.define_method "#{class_min}" do # p.e. def user; ... end if instance_variables.include?("@#{class_min}".to_sym) instance_variable_get("@#{class_min}") # forcément non nil else inst = other_class.get(self.send(prop)) instance_variable_set("@#{class_min}", inst) unless inst.nil? return inst end end classe.define_method "#{class_min}=" do |owner| # p.e. user= self.send("#{prop}=".to_sym, owner.id) end end end |
#tty_name_for(item, options) ⇒ Object
Returns le string à utiliser pour l’attribut :name de TTY prompt.
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 |
# File 'lib/clir/data_manager/Manager.rb', line 594 def tty_name_for(item, ) @tty_name_procedure ||= begin ||= {} if .key?(:name4tty) && [:name4tty] # # Procédure à utiliser définie dans les options # case v = [:name4tty] when Symbol then Proc.new { |inst| inst.send([:name4tty]) } when Proc then Proc.new { |inst| [:name4tty].call(inst) } end elsif item.respond_to?(:name4tty) # # :name4tty Définie comme méthode d'intance # case v = item.send(:name4tty) when Symbol then Proc.new { |inst| inst.send(item.send(:name4tty)) } when String then Proc.new { |inst| inst.send(:name4tty) } end elsif item.respond_to?(:best_name) Proc.new do |inst| begin if inst.is_a?(Clir::GroupedItems) inst.name else inst.best_name end rescue Exception => e puts "-> #{e.}".rouge puts "Problème avec l'instance #{inst.inspect} qui ne répond pas à :best_name…".rouge puts "POURTANT, #{item.inspect} répondait à :best_name…".rouge inst.send(data_properties[1][:prop]) end end else # # Aucune définition => deuxième propriété # prop = data_properties[1][:prop] Proc.new { |inst| inst.send(prop) } end end @tty_name_procedure.call(item) end |