clir-data_manager 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +29 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +44 -0
- data/Manual/Manuel_fr.md +784 -0
- data/Manual/Manuel_fr.pdf +0 -0
- data/README.md +279 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/clir-data_manager.gemspec +34 -0
- data/lib/clir/data_manager/Displayer.rb +30 -0
- data/lib/clir/data_manager/Editor.rb +208 -0
- data/lib/clir/data_manager/Manager.rb +1184 -0
- data/lib/clir/data_manager/Periode.rb +366 -0
- data/lib/clir/data_manager/PrecedencedList.rb +98 -0
- data/lib/clir/data_manager/Property.rb +438 -0
- data/lib/clir/data_manager/Validator.rb +157 -0
- data/lib/clir/data_manager/constants.rb +14 -0
- data/lib/clir/data_manager/errors_and_messages.rb +123 -0
- data/lib/clir/data_manager/module_constants.rb +13 -0
- data/lib/clir/data_manager/version.rb +5 -0
- data/lib/clir/data_manager.rb +21 -0
- metadata +114 -0
@@ -0,0 +1,438 @@
|
|
1
|
+
module Clir
|
2
|
+
module DataManager
|
3
|
+
class Property
|
4
|
+
include ClirDataManagerConstants
|
5
|
+
|
6
|
+
attr_reader :manager
|
7
|
+
attr_reader :data
|
8
|
+
|
9
|
+
# @param manager {Clir::DataManager::Manager} The manager
|
10
|
+
# @param data {Hash} Property data table
|
11
|
+
def initialize(manager, data = nil)
|
12
|
+
@manager = manager
|
13
|
+
@data = data || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# --- Edition Methods ---
|
17
|
+
|
18
|
+
##
|
19
|
+
# Méthode principale de l'édition de la propriété pour l'instance
|
20
|
+
# +instance+ avec les options éventuelles +options+
|
21
|
+
#
|
22
|
+
# @return TRUE si la donnée a été modifiée, FALSE dans le cas
|
23
|
+
# contraire.
|
24
|
+
#
|
25
|
+
def edit(instance, options = nil)
|
26
|
+
#
|
27
|
+
# La valeur par défaut
|
28
|
+
# Soit la valeur actuelle de l'instance, soit la valeur définie
|
29
|
+
# par :default dans les propriétés, qui peut être soit une procé-
|
30
|
+
# dure soit une méthode de classe ou d'instance.
|
31
|
+
#
|
32
|
+
defvalue = instance.send(prop) || default(instance)
|
33
|
+
#
|
34
|
+
# On utilise une édition différente en fonction du type de la
|
35
|
+
# donnée
|
36
|
+
#
|
37
|
+
error = nil
|
38
|
+
question = question(instance).jaune
|
39
|
+
while true
|
40
|
+
puts error.rouge if error
|
41
|
+
new_value =
|
42
|
+
case type
|
43
|
+
when :id
|
44
|
+
# [N0001]
|
45
|
+
# Cas spécial d'une propriété <>_id. Si tout a bien été
|
46
|
+
# défini, DataManager a mis dans l'attribut relative_class
|
47
|
+
# la classe de l'élément.
|
48
|
+
if relative_class
|
49
|
+
item = relative_class.choose({create: true, filter: values_filter})
|
50
|
+
item&.id
|
51
|
+
else
|
52
|
+
raise ERRORS[:require_relative_class] % [prop.to_s, relative_class.to_s]
|
53
|
+
end
|
54
|
+
when :ids
|
55
|
+
# Cf. [N0001] ci-dessus
|
56
|
+
if relative_class
|
57
|
+
multi_choose(instance, options)
|
58
|
+
else
|
59
|
+
raise ERRORS[:require_relative_class] % [prop.to_s, relative_class.to_s]
|
60
|
+
end
|
61
|
+
when :date
|
62
|
+
defvalue ||= Time.now.strftime(MSG[:date_format])
|
63
|
+
Q.ask(question, {default: defvalue})&.strip
|
64
|
+
when :string, :email, :prix, :url, :people, :number, :float
|
65
|
+
nval = Q.ask(question, {help:"'---' = nul", default: defvalue})
|
66
|
+
nval = nil if nval == '---'
|
67
|
+
unless nval.nil?
|
68
|
+
nval = nval.to_s.force_encoding('UTF-8').strip
|
69
|
+
case type
|
70
|
+
when :number, :float
|
71
|
+
if nval.sub(/,/,'.').match?(/\./)
|
72
|
+
nval = nval.to_f
|
73
|
+
else
|
74
|
+
nval = nval.to_i
|
75
|
+
end
|
76
|
+
when :prix
|
77
|
+
nval = nval.to_f
|
78
|
+
when :url
|
79
|
+
nval = "https://#{nval}" unless nval.start_with?('http')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
nval
|
83
|
+
when :select
|
84
|
+
#
|
85
|
+
# Type :select
|
86
|
+
#
|
87
|
+
choices = select_values_with_precedences(instance)
|
88
|
+
if multi?
|
89
|
+
vals = Q.multi_select(question, choices, {default:default_select_value(instance, choices), per_page:choices.count})
|
90
|
+
vals.each { |val| values(instance).set_last(val) }
|
91
|
+
vals
|
92
|
+
else
|
93
|
+
value = Q.select(question, choices, {default:default_select_value(instance, choices), per_page:choices.count, show_help:false})
|
94
|
+
values(instance).set_last(value)
|
95
|
+
value
|
96
|
+
end
|
97
|
+
when :bool
|
98
|
+
Q.select(question, BOOLEAN_VALUES, {default: boolean_default_value(instance), per_page:BOOLEAN_VALUES.count, show_help:false})
|
99
|
+
else
|
100
|
+
puts "Je ne sais pas encore éditer une donnée de type #{type.inspect}.".orange
|
101
|
+
sleep 3
|
102
|
+
break
|
103
|
+
end
|
104
|
+
#
|
105
|
+
# Si la propriété définit une méthode de transformation de
|
106
|
+
# l'entrée, on l'utilise
|
107
|
+
if new_value && itransform
|
108
|
+
new_value = transform_new_value(instance, new_value)
|
109
|
+
end
|
110
|
+
#
|
111
|
+
# On vérifie la validité de la donnée, si une méthode de
|
112
|
+
# validation a été définie. Si la donnée est valide, on la
|
113
|
+
# consigne, sinon non demande à la modifier.
|
114
|
+
#
|
115
|
+
error = valid?(new_value, instance)
|
116
|
+
break if error.nil?
|
117
|
+
|
118
|
+
end #/while invalid
|
119
|
+
#
|
120
|
+
# La donnée a-t-elle changée ?
|
121
|
+
#
|
122
|
+
modified = new_value != current_value(instance)
|
123
|
+
#
|
124
|
+
# S'il y a eu modification, on affecte la nouvelle valeur
|
125
|
+
#
|
126
|
+
instance.send("#{prop}=".to_sym, new_value) if modified
|
127
|
+
#
|
128
|
+
# On indique si la donnée a été modifiée
|
129
|
+
#
|
130
|
+
return modified
|
131
|
+
end
|
132
|
+
|
133
|
+
# --- Méthodes de check ---
|
134
|
+
|
135
|
+
# @return Nil si OK ou le message d'erreur à afficher
|
136
|
+
def valid?(new_value, instance)
|
137
|
+
return if new_value && (new_value == current_value(instance))
|
138
|
+
return manager.validator.valid?(self, new_value, instance)
|
139
|
+
end
|
140
|
+
|
141
|
+
# --- Helpers Methods ---
|
142
|
+
|
143
|
+
def formated_value_in(instance)
|
144
|
+
curval = instance.send(prop)
|
145
|
+
if curval.nil?
|
146
|
+
#
|
147
|
+
# Value non définie
|
148
|
+
#
|
149
|
+
return '---'
|
150
|
+
elsif format_method # :mformat dans la définition de la propriété
|
151
|
+
#
|
152
|
+
# Si la propriété définit une valeur de formatage explicitement
|
153
|
+
#
|
154
|
+
if format_method.is_a?(Proc)
|
155
|
+
format_method.call(current_value(instance), instance)
|
156
|
+
else
|
157
|
+
instance.send(format_method)
|
158
|
+
end
|
159
|
+
elsif instance.respond_to?("f_#{prop}".to_sym)
|
160
|
+
#
|
161
|
+
# Si l'instance définit la méthode de formatage
|
162
|
+
#
|
163
|
+
instance.send("f_#{prop}".to_sym)
|
164
|
+
elsif prop == :name && instance.respond_to?(:best_name)
|
165
|
+
instance.best_name
|
166
|
+
elsif prop.match?(/_ids?$/) && [:id, :ids].include?(type)
|
167
|
+
#
|
168
|
+
# Propriété avec classe relative
|
169
|
+
#
|
170
|
+
if relative_class
|
171
|
+
dmanager = relative_class.data_manager
|
172
|
+
if type == :id
|
173
|
+
# inst = relative_class.get(current_value(instance))
|
174
|
+
inst = relative_class.get(curval)
|
175
|
+
return dmanager.tty_name_for(inst, nil)
|
176
|
+
elsif type == :ids
|
177
|
+
return curval.map do |id|
|
178
|
+
inst = relative_class.get(id)
|
179
|
+
dmanager.tty_name_for(inst, nil)
|
180
|
+
end.join(', ')
|
181
|
+
end
|
182
|
+
else
|
183
|
+
raise ERRORS[:require_relative_class]
|
184
|
+
end
|
185
|
+
elsif type == :select && data[:values]
|
186
|
+
#
|
187
|
+
# Propriété avec des values (on renvoie :full_name ou :name
|
188
|
+
# du choix correspondant)
|
189
|
+
#
|
190
|
+
values_for_instance = values(instance)
|
191
|
+
values_for_instance.each do |dchoix|
|
192
|
+
if dchoix[:value] == curval
|
193
|
+
return dchoix[:full_name]||dchoix[:name]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
raise ERRORS[:choice_unfound_in_choices_list] % [curval.inspect, self.name(instance), values_for_instance.inspect]
|
197
|
+
else
|
198
|
+
#
|
199
|
+
# En dernier recours, la valeur telle quelle
|
200
|
+
#
|
201
|
+
curval
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# --- Functional Methods ---
|
206
|
+
|
207
|
+
##
|
208
|
+
# Permet de choisir des valeurs multiples, pour le moment plusieurs
|
209
|
+
# identifiants d'une classe relative.
|
210
|
+
#
|
211
|
+
# La méthode doit être appelée après avoir vérifié que la
|
212
|
+
# relative_class existait bien.
|
213
|
+
#
|
214
|
+
def multi_choose(instance, options)
|
215
|
+
curvalue = current_value(instance) || []
|
216
|
+
#
|
217
|
+
# La valeur propre du filtre
|
218
|
+
filter_for_instance = nil
|
219
|
+
if values_filter
|
220
|
+
filter_for_instance = {}
|
221
|
+
values_filter.each do |key, value|
|
222
|
+
if value.is_a?(Symbol) # => propriété de l'instance
|
223
|
+
value = instance.send(value)
|
224
|
+
end
|
225
|
+
filter_for_instance.merge!(key => value)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
#
|
229
|
+
# On demande toutes les instances choisies
|
230
|
+
#
|
231
|
+
insts = relative_class.choose({multi:true, create: false, filter: filter_for_instance, default: curvalue})
|
232
|
+
curvalue = insts.map(&:id)
|
233
|
+
# puts "curvalue : #{curvalue.inspect}"
|
234
|
+
#
|
235
|
+
# Valeur finale à retourner
|
236
|
+
#
|
237
|
+
curvalue = nil if curvalue.empty?
|
238
|
+
return curvalue
|
239
|
+
end
|
240
|
+
|
241
|
+
##
|
242
|
+
# Si la propriété définit :itransform (méthode de transformation
|
243
|
+
# de la donnée entrée), cette méthode est appelée pour transformer
|
244
|
+
# la donnée.
|
245
|
+
def transform_new_value(instance, new_value)
|
246
|
+
case itransform
|
247
|
+
when Symbol
|
248
|
+
if instance.respond_to?(itransform)
|
249
|
+
instance.send(itransform, new_value)
|
250
|
+
elsif new_value.respond_to?(itransform)
|
251
|
+
new_value.send(itransform)
|
252
|
+
else
|
253
|
+
raise ERRORS[:value_doesnt_respond_to] % [new_value.inspect, "#{new_value.class}", itransform.inspect]
|
254
|
+
end
|
255
|
+
when Proc
|
256
|
+
itransform.call(instance, new_value)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def select_values_with_precedences(instance)
|
261
|
+
return values(instance).to_prec
|
262
|
+
end
|
263
|
+
|
264
|
+
# @return l'index de la valeur actuelle de l'instance pour la
|
265
|
+
# propriété courante, lorsque c'est un select (tty-prompt, en
|
266
|
+
# valeur par défaut, ne supporte que l'index, ou le :name du menu)
|
267
|
+
# Si la valeur n'est pas définie ou si elle est introuvable, on
|
268
|
+
# retourne nil
|
269
|
+
def default_select_value(instance, vals)
|
270
|
+
cvalue = current_value(instance) || default(instance) || return
|
271
|
+
vals.each_with_index do |dchoix, idx|
|
272
|
+
return idx + 1 if dchoix[:value] == cvalue
|
273
|
+
end
|
274
|
+
return nil
|
275
|
+
end
|
276
|
+
|
277
|
+
# @prop La valeur actuelle de cette propriété
|
278
|
+
def current_value(instance)
|
279
|
+
instance.send(prop)
|
280
|
+
end
|
281
|
+
|
282
|
+
# @prop La question à poser pour cette propriété
|
283
|
+
def question(instance)
|
284
|
+
if quest
|
285
|
+
quest % instance.data
|
286
|
+
else
|
287
|
+
"Nouvelle valeur pour #{name.inspect} : "
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# --- Predicate Methods ---
|
292
|
+
|
293
|
+
def required?(instance)
|
294
|
+
if_able?(instance) || return
|
295
|
+
:TRUE == @isrequired ||= true_or_false(specs & REQUIRED > 0)
|
296
|
+
end
|
297
|
+
|
298
|
+
def displayable?(instance)
|
299
|
+
if_able?(instance) || return
|
300
|
+
:TRUE == @isdisplayable ||= true_or_false(specs & DISPLAYABLE > 0)
|
301
|
+
end
|
302
|
+
|
303
|
+
def editable?(instance)
|
304
|
+
if_able?(instance) || return
|
305
|
+
:TRUE == @iseditable ||= true_or_false(specs & EDITABLE > 0)
|
306
|
+
end
|
307
|
+
|
308
|
+
def removable?(instance)
|
309
|
+
if_able?(instance) || return
|
310
|
+
:TRUE == @isremovable ||= true_or_false(specs & REMOVABLE > 0)
|
311
|
+
end
|
312
|
+
|
313
|
+
# @return [true, false] true si la propriété doit être affichée
|
314
|
+
# dans une table Clir::Table
|
315
|
+
# @note
|
316
|
+
# Contrairement aux autres méthodes predicate de même type (cf
|
317
|
+
# ci-dessus), on ne teste pas le if_able car cette valeur doit
|
318
|
+
# être utilisée dans la table même pour les items qui ne la défi-
|
319
|
+
# nissent pas (sinon il y aurait des "trous" dans la table)
|
320
|
+
#
|
321
|
+
def tablizable?
|
322
|
+
specs || raise(ERRORS[:specs_undefined] % prop)
|
323
|
+
:TRUE == @isremovable ||= true_or_false(specs & TABLEIZABLE > 0)
|
324
|
+
end
|
325
|
+
|
326
|
+
# @return [Boolean] true si property can have multi_select values.
|
327
|
+
def multi?
|
328
|
+
:TRUE == @ismultiselect ||= true_or_false(data[:multi] == true)
|
329
|
+
end
|
330
|
+
|
331
|
+
# @return TRUE si la propriété :if n'est pas définie ou si elle
|
332
|
+
# retourne la valeur true (donc elle retourne true quand la
|
333
|
+
# propriété existe pour l'instance donnée)
|
334
|
+
def if_able?(instance)
|
335
|
+
specs || raise(ERRORS[:specs_undefined] % prop)
|
336
|
+
return true if if_attr.nil?
|
337
|
+
case if_attr
|
338
|
+
when Symbol
|
339
|
+
instance.send(if_attr)
|
340
|
+
when Proc
|
341
|
+
if_attr.call(instance)
|
342
|
+
when TrueClass, FalseClass
|
343
|
+
if_attr
|
344
|
+
else
|
345
|
+
raise ERRORS[:unknown_if_attribut] % "#{if_attr.inspect}:#{if_attr.class}"
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
# --- Hard Coded Properties ---
|
350
|
+
|
351
|
+
def index; @index ||= data[:index] end
|
352
|
+
def specs; @specs ||= data[:specs] end
|
353
|
+
def prop; @prop ||= data[:prop] end
|
354
|
+
def type; @type ||= data[:type] end
|
355
|
+
def quest; @quest ||= data[:quest] end
|
356
|
+
def if_attr; @ifattr ||= data[:if] end
|
357
|
+
def valid_if; @valid_if ||= data[:valid_if] end
|
358
|
+
def short_name; @short_name ||= data[:short_name] end
|
359
|
+
def name(instance = nil)
|
360
|
+
@name ||= data[:name]
|
361
|
+
if @name.is_a?(Proc)
|
362
|
+
@name.call(instance)
|
363
|
+
else
|
364
|
+
@name
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
|
369
|
+
def values(instance = nil)
|
370
|
+
vs =
|
371
|
+
vs = case (vs = data[:values])
|
372
|
+
when Symbol
|
373
|
+
if manager.classe.respond_to?(vs)
|
374
|
+
begin
|
375
|
+
manager.classe.send(vs)
|
376
|
+
rescue ArgumentError
|
377
|
+
manager.classe.send(vs, instance)
|
378
|
+
end
|
379
|
+
elsif manager.respond_to?(vs)
|
380
|
+
nargs = manager.method(d).arity
|
381
|
+
puts "Nombre d'arguments attendus par (#{vs}) : #{nargs}".orange
|
382
|
+
puts 10
|
383
|
+
if nargs == 0
|
384
|
+
manager.send(vs)
|
385
|
+
else
|
386
|
+
manager.send(vs, instance)
|
387
|
+
end
|
388
|
+
# begin
|
389
|
+
# manager.send(vs)
|
390
|
+
# rescue ArgumentError
|
391
|
+
# manager.send(vs, instance)
|
392
|
+
# end
|
393
|
+
else
|
394
|
+
raise ERRORS[:unknown_values_method] % vs.inspect
|
395
|
+
end
|
396
|
+
when Proc
|
397
|
+
vs.call(instance)
|
398
|
+
else
|
399
|
+
vs
|
400
|
+
end
|
401
|
+
uniq_name = "#{manager.classe.class.to_s.gsub(/::/,'-')}-#{prop}".downcase
|
402
|
+
return PrecedencedList.new(vs, uniq_name)
|
403
|
+
end
|
404
|
+
|
405
|
+
def default(instance)
|
406
|
+
d = data[:default]
|
407
|
+
d = d.call(instance) if d.is_a?(Proc)
|
408
|
+
if d.is_a?(Symbol)
|
409
|
+
if instance.respond_to?(d)
|
410
|
+
instance.send(d)
|
411
|
+
elsif instance.class.respond_to?(d)
|
412
|
+
nargs = instance.class.method(d).arity
|
413
|
+
puts "Nombre d'arguments attendus : #{nargs}".orange
|
414
|
+
puts 10
|
415
|
+
begin
|
416
|
+
d = instance.class.send(d)
|
417
|
+
rescue ArgumentError
|
418
|
+
d = instance.class.send(d, instance)
|
419
|
+
end
|
420
|
+
else
|
421
|
+
# La garder telle quelle
|
422
|
+
end
|
423
|
+
end
|
424
|
+
d
|
425
|
+
end
|
426
|
+
def values_filter; @values_filter ||= data[:values_filter] end
|
427
|
+
def itransform; @itransform ||= data[:itransform] end
|
428
|
+
def relative_class; @relative_class ||= data[:relative_class] end
|
429
|
+
def format_method; @format_method ||= data[:mformat]||data[:mformate]||data[:format_method] end
|
430
|
+
|
431
|
+
BOOLEAN_VALUES = [
|
432
|
+
{name: MSG[:yes] , value: true },
|
433
|
+
{name: MSG[:no] , value: false },
|
434
|
+
{name: MSG[:cancel] , value: nil }
|
435
|
+
]
|
436
|
+
end #/class Property
|
437
|
+
end #/module DataManager
|
438
|
+
end #/module Clir
|
@@ -0,0 +1,157 @@
|
|
1
|
+
=begin
|
2
|
+
Clir::DataManager::Manager::Validator
|
3
|
+
-------------------------------------
|
4
|
+
To invalidate instance values
|
5
|
+
|
6
|
+
=end
|
7
|
+
module Clir
|
8
|
+
module DataManager
|
9
|
+
class Manager
|
10
|
+
class Validator
|
11
|
+
|
12
|
+
attr_reader :manager
|
13
|
+
|
14
|
+
def initialize(manager)
|
15
|
+
@manager = manager
|
16
|
+
end
|
17
|
+
|
18
|
+
# - main method -
|
19
|
+
#
|
20
|
+
# Quand l'éditeur (Manager::Editor) reçoit une nouvelle valeur pour
|
21
|
+
# la propriété +property+ ({Manager::Property}) il la checke ici
|
22
|
+
# pour savoir si elle est valide pour l'instance +instance+
|
23
|
+
#
|
24
|
+
# Noter que l'instance permet aussi de récupérer la classe de cette
|
25
|
+
# instance pour obtenir certaines valeurs. La classe doit par ex.
|
26
|
+
# répondre à la méthode ::get pour obtenir une autre instance.
|
27
|
+
#
|
28
|
+
def valid?(property, new_value, instance)
|
29
|
+
#
|
30
|
+
# Une propriété requise doit exister
|
31
|
+
#
|
32
|
+
if property.required?(instance) && (!new_value || new_value.to_s.empty?)
|
33
|
+
return ERRORS[:required_property] % property.name
|
34
|
+
end
|
35
|
+
|
36
|
+
if new_value
|
37
|
+
|
38
|
+
case property.type
|
39
|
+
|
40
|
+
when :email
|
41
|
+
#
|
42
|
+
# Un email
|
43
|
+
#
|
44
|
+
if not(mail_valid?(new_value))
|
45
|
+
return ERRORS[:invalid_mail] % new_value
|
46
|
+
end
|
47
|
+
when :date
|
48
|
+
#
|
49
|
+
# Une date
|
50
|
+
#
|
51
|
+
if not(date_valid?(new_value))
|
52
|
+
return ERRORS[:invalid_date] % new_value
|
53
|
+
end
|
54
|
+
when :url
|
55
|
+
#
|
56
|
+
# Une URL
|
57
|
+
#
|
58
|
+
if (err = url_invalid?(new_value))
|
59
|
+
return ERRORS[:invalid_url] % [new_value, err]
|
60
|
+
end
|
61
|
+
when :people
|
62
|
+
#
|
63
|
+
# Un ou des people
|
64
|
+
#
|
65
|
+
if (err = people_invalid?(new_value))
|
66
|
+
return ERRORS[:invalid_people] % [property.name, err]
|
67
|
+
end
|
68
|
+
end # suivant property.type
|
69
|
+
|
70
|
+
if property.valid_if
|
71
|
+
if (err = proceed_validation_propre(property, new_value, instance))
|
72
|
+
return ERRORS[:invalid_property] % [property.name, err]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end #/si la nouvelle valeur est défini
|
77
|
+
|
78
|
+
return nil # OK
|
79
|
+
end
|
80
|
+
|
81
|
+
# Quand les attributs de la propriété définissent :valid_if qui
|
82
|
+
# permet de procéder à une validation de la donnée +new_value+
|
83
|
+
#
|
84
|
+
# @return [NilClass|String] Return nil si aucune erreur n'est
|
85
|
+
# trouvée, sinon, retourne l'erreur rencontrée.
|
86
|
+
def proceed_validation_propre(property, new_value, instance)
|
87
|
+
meth = property.valid_if
|
88
|
+
case meth
|
89
|
+
when Symbol
|
90
|
+
if new_value.respond_to?(meth)
|
91
|
+
new_value.send(meth)
|
92
|
+
elsif instance.respond_to?(meth)
|
93
|
+
instance.send(meth, new_value)
|
94
|
+
elsif instance.class.respond_to?(meth)
|
95
|
+
instance.class.send(meth, new_value, instance)
|
96
|
+
end
|
97
|
+
when Proc
|
98
|
+
property.valid_if.call(new_value, instance)
|
99
|
+
else
|
100
|
+
raise ERRORS[:unknow_validate_method] % meth.inspect
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return true si la donnée +people+ est une donnée de personne
|
105
|
+
# valide. Une donnée de personne valide correspond à
|
106
|
+
def people_invalid?(people)
|
107
|
+
people.split(',').each do |patro|
|
108
|
+
dpatro = patro.split(' ')
|
109
|
+
dpatro.count < 6 || raise(ERRORS[:too_long_name] % patro)
|
110
|
+
patro.match?(/[0-9?!_,;.…\/\\"]/) && raise(ERRORS[:bad_chars_in_name] % patro)
|
111
|
+
end
|
112
|
+
return nil # ok
|
113
|
+
rescue Exception => e
|
114
|
+
return e.message
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return true si le mail +mail+ est valide
|
118
|
+
def mail_valid?(mail)
|
119
|
+
mail.match?(/^(.{6,40})@([a-z\-_\.0-9]+)\.([a-z]{2,6})$/i)
|
120
|
+
end
|
121
|
+
|
122
|
+
def date_valid?(date)
|
123
|
+
date.match?(MSG[:reg_date_format]) || return
|
124
|
+
begin
|
125
|
+
m, d, y = date.split('/').map {|n| n.to_i }
|
126
|
+
if LANG == 'fr'
|
127
|
+
Time.new(y, d, m)
|
128
|
+
else
|
129
|
+
Time.new(y, m, d)
|
130
|
+
end
|
131
|
+
rescue
|
132
|
+
return false
|
133
|
+
end
|
134
|
+
return true
|
135
|
+
end
|
136
|
+
|
137
|
+
# Noter que cette méthode fonctionne à l'inverse des autres : elle
|
138
|
+
# retourne un message d'erreur en cas d'invalidité et elle ne
|
139
|
+
# retourne rien si tout est OK
|
140
|
+
#
|
141
|
+
def url_invalid?(url)
|
142
|
+
require 'net/http'
|
143
|
+
uri = URI(url)
|
144
|
+
Net::HTTP.get(uri)
|
145
|
+
return nil # ok
|
146
|
+
rescue Exception => e
|
147
|
+
return e.message
|
148
|
+
# ensure
|
149
|
+
# puts "request: #{request.inspect}"
|
150
|
+
# sleep 10
|
151
|
+
# exit
|
152
|
+
end
|
153
|
+
|
154
|
+
end #/class Validator
|
155
|
+
end #/class Manager
|
156
|
+
end #/module DataManager
|
157
|
+
end #/module Clir
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
LANG = 'fr'
|
3
|
+
require_relative 'errors_and_messages'
|
4
|
+
|
5
|
+
module Clir
|
6
|
+
module DataManager
|
7
|
+
include ClirDataManagerConstants
|
8
|
+
|
9
|
+
|
10
|
+
CHOIX_RENONCER = {name: MSG[:cancel].orange, value:nil}
|
11
|
+
CHOIX_CREATE = {name: MSG[:create_new].bleu, value: :create}
|
12
|
+
|
13
|
+
end #/module DataManager
|
14
|
+
end #/module Clir
|