apidae 0.10.0 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,41 +14,49 @@ module Apidae
14
14
  store_accessor :pictures_data, :pictures
15
15
  store_accessor :attachments_data, :attachments
16
16
  store_accessor :type_data, :categories, :themes, :capacity, :classification, :labels, :chains, :area, :track,
17
- :products, :audience, :animals, :extra, :duration, :certifications, :business
17
+ :products, :audience, :animals, :animals_desc, :extra, :duration, :certifications, :business
18
18
  store_accessor :entity_data, :entity_id, :entity_name, :service_provider_id
19
- store_accessor :contact, :telephone, :email, :website
19
+ store_accessor :contact_data, :telephone, :email, :website, :google, :facebook, :twitter, :yelp, :trip_advisor, :contacts
20
20
  store_accessor :location_data, :address, :place, :latitude, :longitude, :access, :territories, :environments
21
- store_accessor :openings_data, :openings_desc, :openings_desc_mode, :openings, :time_periods
21
+ store_accessor :openings_data, :openings_desc, :openings_desc_mode, :openings, :time_periods, :openings_extra
22
22
  store_accessor :rates_data, :rates_desc, :rates_desc_mode, :rates, :payment_methods, :includes, :excludes
23
23
  store_accessor :service_data, :services, :equipments, :comfort, :activities, :challenged, :languages
24
24
  store_accessor :booking_data, :booking_desc, :booking_entities
25
25
  store_accessor :tags_data, :promo, :internal, :linked
26
26
  store_accessor :version_data, :versioned_fields
27
27
 
28
- LOCALIZED_FIELDS.each do |f|
29
- alias_method :"#{f}_hash", :"#{f}"
30
- alias_method :"#{f}_hash=", :"#{f}="
28
+ ALL_FIELDS.each do |f|
29
+ alias_method :"get_#{f}", :"#{f}"
30
+ alias_method :"set_#{f}", :"#{f}="
31
31
 
32
- define_method "#{f}=" do |val|
33
- ref_obj = (@obj_version == DEFAULT_VERSION || @obj_version.nil?) ? self : in_version(@obj_version)
34
- field_hash = ref_obj.send(:"#{f}_hash") || {}
35
- ref_obj.send(:"#{f}_hash=", field_hash.merge(@locale => val))
32
+ if LOCALIZED_FIELDS.include?(f)
33
+ define_method "#{f}=" do |val|
34
+ ref_obj = (@obj_version == DEFAULT_VERSION || @obj_version.nil?) ? self : in_version(@obj_version)
35
+ current_val = ref_obj.send(:"get_#{f}") || {}
36
+ ref_obj.send(:"set_#{f}", current_val.merge(@locale => val))
37
+ end
38
+ else
39
+ define_method "#{f}=" do |val|
40
+ ref_obj = (@obj_version == DEFAULT_VERSION || @obj_version.nil?) ? self : in_version(@obj_version)
41
+ ref_obj.send(:"set_#{f}", val)
42
+ end
36
43
  end
37
44
 
38
45
  define_method f do
39
- field_hash = self.send(:"#{f}_hash") || {}
46
+ default_value = LOCALIZED_FIELDS.include?(f) ? {} : nil
47
+ field_val = self.send(:"get_#{f}") || default_value
40
48
  unless @obj_version == DEFAULT_VERSION
41
49
  versioned_obj = in_version(@obj_version)
42
50
  if versioned_obj
43
- versioned_hash = versioned_obj.send(:"#{f}_hash") || {}
51
+ versioned_value = versioned_obj.send(:"get_#{f}") || default_value
44
52
  if versioned_obj.versioned_fields.include?(f.to_s)
45
- field_hash = versioned_hash
46
- else
47
- field_hash.deep_merge!(versioned_hash)
53
+ field_val = versioned_value
54
+ elsif field_val.respond_to?('deep_merge!')
55
+ field_val.deep_merge!(versioned_value)
48
56
  end
49
57
  end
50
58
  end
51
- field_hash[@locale] || field_hash[DEFAULT_LOCALE]
59
+ LOCALIZED_FIELDS.include?(f) ? (field_val[@locale] || field_val[DEFAULT_LOCALE]) : field_val
52
60
  end
53
61
  end
54
62
 
@@ -88,13 +96,6 @@ module Apidae
88
96
  TER => {node: :informationsTerritoire, subtype: :territoireType}
89
97
  }
90
98
 
91
- PHONE = 201
92
- EMAIL = 204
93
- WEBSITE = 205
94
-
95
- MODE_AUTO = 'auto'
96
- MODE_MANUAL = 'manual'
97
-
98
99
  after_initialize do
99
100
  @locale = DEFAULT_LOCALE
100
101
  @obj_version = DEFAULT_VERSION
@@ -121,6 +122,18 @@ module Apidae
121
122
  self
122
123
  end
123
124
 
125
+ def dig(*keys)
126
+ root_key, *nested_keys = keys
127
+ root_val = self.send(root_key)
128
+ if root_val.blank?
129
+ nested_keys.blank? ? root_val : nil
130
+ elsif root_val.respond_to?(:dig)
131
+ root_val.dig(*nested_keys)
132
+ else
133
+ raise ArgumentError.new('Cannot call dig with these args')
134
+ end
135
+ end
136
+
124
137
  def self.default_scope
125
138
  where(root_obj_id: nil)
126
139
  end
@@ -141,7 +154,7 @@ module Apidae
141
154
  version_data[:type] = apidae_obj.apidae_type
142
155
  version_obj = apidae_obj.in_version(version) || Obj.new(apidae_id: apidae_obj.apidae_id,
143
156
  root_obj_id: apidae_obj.id, version: version)
144
- version_obj.versioned_fields = parse_versioned_fields(version_data)
157
+ version_obj.versioned_fields = ApidaeDataParser.parse_versioned_fields(version_data)
145
158
  populate_fields(version_obj, version_data, locales)
146
159
  version_obj.save!
147
160
  end
@@ -153,299 +166,31 @@ module Apidae
153
166
  def self.populate_fields(apidae_obj, object_data, locales)
154
167
  type_fields = TYPES_DATA[object_data[:type]]
155
168
  apidae_obj.last_update = DateTime.parse(object_data[:gestion][:dateModification]) unless object_data[:gestion].blank?
156
- apidae_obj.owner_data = parse_owner_data(object_data[:gestion][:membreProprietaire]) unless object_data[:gestion].blank?
169
+ apidae_obj.owner_data = ApidaeDataParser.parse_owner_data(object_data[:gestion][:membreProprietaire]) unless object_data[:gestion].blank?
157
170
  apidae_obj.apidae_type = object_data[:type]
158
- apidae_obj.apidae_subtype = node_id(object_data[type_fields[:node]], type_fields[:subtype])
159
- apidae_obj.title_data = parse_title(object_data, *locales)
160
- apidae_obj.description_data = parse_desc_data(object_data[:presentation], object_data[:donneesPrivees], *locales)
161
- apidae_obj.contact = contact(object_data[:informations])
162
- apidae_obj.location_data = parse_location_data(object_data[:localisation], object_data[type_fields[:node]],
171
+ apidae_obj.apidae_subtype = ApidaeDataParser.node_id(object_data[type_fields[:node]], type_fields[:subtype])
172
+ apidae_obj.title_data = ApidaeDataParser.parse_title(object_data, *locales)
173
+ apidae_obj.description_data = ApidaeDataParser.parse_desc_data(object_data[:presentation], object_data[:donneesPrivees], *locales)
174
+ apidae_obj.contact_data = ApidaeDataParser.parse_contact_data(object_data[:informations], object_data[:contacts])
175
+ apidae_obj.location_data = ApidaeDataParser.parse_location_data(object_data[:localisation], object_data[type_fields[:node]],
163
176
  object_data[:territoires])
164
- apidae_obj.town = town(object_data[:localisation])
165
- apidae_obj.openings_data = parse_openings(object_data[:ouverture], *locales)
166
- apidae_obj.rates_data = parse_rates(object_data[:descriptionTarif], *locales)
167
- apidae_obj.booking_data = parse_booking(object_data[:reservation], *locales)
168
- apidae_obj.type_data = parse_type_data(apidae_obj, object_data[type_fields[:node]], object_data[:prestations],
177
+ apidae_obj.town = ApidaeDataParser.parse_town(object_data[:localisation])
178
+ apidae_obj.openings_data = ApidaeDataParser.parse_openings(object_data[:ouverture], *locales)
179
+ apidae_obj.rates_data = ApidaeDataParser.parse_rates(object_data[:descriptionTarif], *locales)
180
+ apidae_obj.booking_data = ApidaeDataParser.parse_booking(object_data[:reservation], *locales)
181
+ apidae_obj.type_data = ApidaeDataParser.parse_type_data(apidae_obj, object_data[type_fields[:node]], object_data[:prestations],
169
182
  object_data[:tourismeAffaires], *locales)
170
- apidae_obj.pictures_data = parse_pictures_data(object_data[:illustrations], *locales)
171
- apidae_obj.attachments_data = parse_attachments_data(object_data[:multimedias], *locales)
172
- apidae_obj.entity_data = entity_fields(object_data[:informations], object_data[type_fields[:node]])
173
- apidae_obj.service_data = parse_service_data(object_data[:prestations], object_data[type_fields[:node]])
174
- apidae_obj.tags_data = parse_tags_data(object_data[:presentation], object_data[:criteresInternes], object_data[:liens])
183
+ apidae_obj.pictures_data = ApidaeDataParser.parse_pictures_data(object_data[:illustrations], *locales)
184
+ apidae_obj.attachments_data = ApidaeDataParser.parse_attachments_data(object_data[:multimedias], *locales)
185
+ apidae_obj.entity_data = ApidaeDataParser.parse_entity_fields(object_data[:informations], object_data[type_fields[:node]])
186
+ apidae_obj.service_data = ApidaeDataParser.parse_service_data(object_data[:prestations], object_data[type_fields[:node]])
187
+ apidae_obj.tags_data = ApidaeDataParser.parse_tags_data(object_data[:presentation], object_data[:criteresInternes], object_data[:liens])
175
188
  apidae_obj.meta_data = object_data[:metadonnees]
176
189
  end
177
190
 
178
- def self.non_empty(data_hash)
179
- data_hash.keep_if {|k, v| !v.blank?}
180
- end
181
-
182
- def self.parse_versioned_fields(data_hash)
183
- version_fields = data_hash[:champsAspect] || []
184
- matched_fields = []
185
- version_fields.each do |f|
186
- case f
187
- when 'nom'
188
- matched_fields << 'title'
189
- when 'presentation.descriptifCourt'
190
- matched_fields << 'short_desc'
191
- when 'presentation.descriptifDetaille'
192
- matched_fields << 'long_desc'
193
- when 'illustrations'
194
- matched_fields << 'pictures'
195
- when 'multimedias'
196
- matched_fields << 'attachments'
197
- when 'informations.moyensCommunication'
198
- matched_fields << 'contact'
199
- when 'descriptifsThematises'
200
- matched_fields << 'theme_desc'
201
- when 'ouverture.periodesOuvertures', 'ouverture.periodeEnClair'
202
- matched_fields << 'openings_desc'
203
- matched_fields << 'openings'
204
- when 'ouverture.periodeEnClairAutomatique'
205
- matched_fields << 'openings_desc_mode'
206
- when 'descriptionTarif.tarifsEnClair', 'descriptionTarif.periodes'
207
- matched_fields << 'rates_desc'
208
- matched_fields << 'rates'
209
- when 'descriptionTarif.tarifsEnClairAutomatique'
210
- matched_fields << 'rates_desc_mode'
211
- when 'prestations.equipements'
212
- matched_fields << 'equipments'
213
- when 'prestations.activites'
214
- matched_fields << 'activities'
215
- when 'prestations.services'
216
- matched_fields << 'services'
217
- when 'localisation.environnements'
218
- matched_fields << 'environments'
219
- when 'prestations.complementAccueil'
220
- matched_fields << 'extra'
221
- when 'localisation.geolocalisation.complement'
222
- matched_fields << 'access'
223
- else
224
- end
225
- end
226
- matched_fields.uniq
227
- end
228
-
229
- def self.parse_title(data_hash, *locales)
230
- {title: node_value(data_hash, :nom, *locales)}
231
- end
232
-
233
- def self.parse_owner_data(data_hash)
234
- unless data_hash.blank?
235
- {owner_name: data_hash[:nom], owner_id: data_hash[:id]}
236
- end
237
- end
238
-
239
- def self.parse_desc_data(data_hash, private_data, *locales)
240
- unless data_hash.blank?
241
- {
242
- short_desc: node_value(data_hash, :descriptifCourt, *locales),
243
- long_desc: node_value(data_hash, :descriptifDetaille, *locales),
244
- theme_desc: data_hash[:descriptifsThematises].blank? ? {} : Hash[data_hash[:descriptifsThematises].map {|th| [node_id(th, :theme), node_value(th, :description, *locales)]}],
245
- private_desc: private_data.blank? ? {} : Hash[private_data.map {|d| [d[:nomTechnique], node_value(d, :descriptif, *locales)]}]
246
- }
247
- end
248
- end
249
-
250
- def self.parse_pictures_data(pictures_array, *locales)
251
- pics_data = {}
252
- unless pictures_array.blank?
253
- l = locales.blank? ? [DEFAULT_LOCALE] : locales
254
- l.each do |locale|
255
- pics_data[locale] = []
256
- pictures_array.select { |p| p.is_a?(Hash) && !p[:traductionFichiers].blank? }.each do |pic|
257
- pics_data[locale] << {
258
- id: pic[:identifiant],
259
- name: localized_value(pic, :nom, locale),
260
- url: pic[:traductionFichiers][0][:url].gsub('http:', 'https:'),
261
- description: localized_value(pic, :legende, locale),
262
- credits: localized_value(pic, :copyright, locale),
263
- expiration_date: pic[:dateLimiteDePublication]
264
- }
265
- end
266
- end
267
- end
268
- {pictures: pics_data}
269
- end
270
-
271
- def self.parse_attachments_data(attachments_array, *locales)
272
- atts_data = {}
273
- unless attachments_array.blank?
274
- l = locales.blank? ? [DEFAULT_LOCALE] : locales
275
- l.each do |locale|
276
- atts_data[locale] = []
277
- attachments_array.select { |att| att.is_a?(Hash) && !att[:traductionFichiers].blank? }.each do |att|
278
- atts_data[locale] << {
279
- id: att[:identifiant],
280
- name: localized_value(att, :nom, locale),
281
- url: att[:traductionFichiers][0][:url].gsub('http:', 'https:'),
282
- type: att[:type],
283
- description: localized_value(att, :legende, locale)
284
- }
285
- end
286
- end
287
- end
288
- {attachments: atts_data}
289
- end
290
-
291
- def self.contact(information_hash)
292
- contact_details = {}
293
- unless information_hash.blank?
294
- contact_entries = information_hash[:moyensCommunication] || []
295
- contact_entries.each do |c|
296
- case c[:type][:id]
297
- when PHONE
298
- contact_details[:telephone] ||= []
299
- contact_details[:telephone] << c[:coordonnees][:fr]
300
- when EMAIL
301
- contact_details[:email] ||= []
302
- contact_details[:email] << c[:coordonnees][:fr]
303
- when WEBSITE
304
- contact_details[:website] ||= []
305
- contact_details[:website] << c[:coordonnees][:fr]
306
- else
307
- end
308
- end
309
- end
310
- contact_details
311
- end
312
-
313
- def self.parse_location_data(location_hash, type_data_hash, territories)
314
- loc_data = {}
315
- unless location_hash.blank?
316
- address_hash = location_hash[:adresse]
317
- computed_address = []
318
- unless address_hash.blank?
319
- computed_address << address_hash[:adresse1] unless address_hash[:adresse1].blank?
320
- computed_address << address_hash[:adresse2] unless address_hash[:adresse2].blank?
321
- computed_address << address_hash[:adresse3] unless address_hash[:adresse3].blank?
322
- end
323
- loc_data.merge!({address: computed_address})
324
- loc_data.merge!({place: type_data_hash[:nomLieu]}) if type_data_hash
325
- geoloc_details = location_hash[:geolocalisation]
326
- if geoloc_details && geoloc_details[:valide] && geoloc_details[:geoJson]
327
- loc_data[:latitude] = geoloc_details[:geoJson][:coordinates][1]
328
- loc_data[:longitude] = geoloc_details[:geoJson][:coordinates][0]
329
- end
330
- loc_data[:access] = node_value(geoloc_details, :complement) if geoloc_details
331
- loc_data[:environments] = location_hash[:environnements].map {|e| e[:id]} if location_hash[:environnements]
332
- end
333
- loc_data[:territories] = territories.map {|t| t[:id]} unless territories.blank?
334
- loc_data
335
- end
336
-
337
- def self.town(location_hash)
338
- if location_hash
339
- address_hash = location_hash[:adresse]
340
- (!address_hash.blank? && address_hash[:commune]) ? Town.find_by_apidae_id(address_hash[:commune][:id]) : nil
341
- else
342
- nil
343
- end
344
- end
345
-
346
- # Note : use internal format for openings storage (ideally Apihours one, to merge data from both sources)
347
- def self.parse_openings(openings_hash, *locales)
348
- if openings_hash && openings_hash[:periodeEnClair]
349
- {
350
- openings_desc: node_value(openings_hash, :periodeEnClair, *locales),
351
- openings_desc_mode: openings_hash[:periodeEnClairGenerationMode] == 'AUTOMATIQUE' ? MODE_AUTO : MODE_MANUAL,
352
- openings: openings_hash[:periodesOuvertures],
353
- time_periods: lists_ids(openings_hash[:indicationsPeriode])
354
- }
355
- end
356
- end
357
-
358
- def self.parse_rates(rates_hash, *locales)
359
- if rates_hash
360
- desc = rates_hash[:gratuit] ? {DEFAULT_LOCALE => 'gratuit'} : node_value(rates_hash, :tarifsEnClair, *locales)
361
- values = rates_hash[:periodes].blank? ? [] : rates_hash[:periodes].map {|p| build_rate(p)}
362
- methods = rates_hash[:modesPaiement].blank? ? [] : rates_hash[:modesPaiement].map {|p| p[:id]}
363
- {
364
- rates_desc: desc, rates: values, payment_methods: methods,
365
- rates_desc_mode: rates_hash[:tarifsEnClairGenerationMode] == 'AUTOMATIQUE' ? MODE_AUTO : MODE_MANUAL,
366
- includes: node_value(rates_hash, :leTarifComprend, *locales),
367
- excludes: node_value(rates_hash, :leTarifNeComprendPas, *locales)
368
- }
369
- end
370
- end
371
-
372
- def self.parse_type_data(apidae_obj, type_hash, presta_hash, business_hash, *locales)
373
- data_hash = type_hash || {}
374
- prestations_hash = presta_hash || {}
375
- apidae_obj.apidae_subtype = lists_ids(data_hash[:typesManifestation]).first if apidae_obj.apidae_type == FEM
376
- apidae_obj.apidae_subtype = node_id(data_hash, :rubrique) if apidae_obj.apidae_type == EQU
377
- apidae_obj.apidae_subtype = lists_ids(data_hash[:typesHebergement]).first if apidae_obj.apidae_type == SPA
378
- {
379
- categories: lists_ids(data_hash[:categories], data_hash[:typesDetailles], data_hash[:activiteCategories]),
380
- themes: lists_ids(data_hash[:themes]),
381
- capacity: (data_hash[:capacite] || {})
382
- .merge(presta_hash ? {group_min: presta_hash[:tailleGroupeMin], group_max: presta_hash[:tailleGroupeMax],
383
- age_min: presta_hash[:ageMin], age_max: presta_hash[:ageMax]} : {}),
384
- classification: nodes_ids(data_hash[:classement], data_hash[:classementPrefectoral], data_hash[:classification]) +
385
- lists_ids(data_hash[:classementsGuides]) + lists_ids(data_hash[:classements]),
386
- labels: lists_ids(data_hash[:labels], data_hash[:labelsChartesQualite], prestations_hash[:labelsTourismeHandicap]) +
387
- (node_id(data_hash, :typeLabel) ? [node_id(data_hash, :typeLabel)] : []),
388
- chains: lists_ids(data_hash[:chaines]) + nodes_ids(data_hash[:chaineEtLabel]),
389
- area: apidae_obj.apidae_type == DOS ? data_hash.except(:classification) : node_value(data_hash, :lieuDePratique),
390
- track: apidae_obj.apidae_type == EQU ? data_hash[:itineraire] : nil,
391
- products: lists_ids(data_hash[:typesProduit], data_hash[:aopAocIgps], data_hash[:specialites]),
392
- audience: lists_ids(prestations_hash[:typesClientele]),
393
- animals: prestations_hash[:animauxAcceptes] == 'ACCEPTES',
394
- extra: apidae_obj.apidae_type == SPA ? node_value(data_hash, :formuleHebergement, *locales) : node_value(prestations_hash, :complementAccueil, *locales),
395
- duration: apidae_obj.apidae_type == SPA ? {days: data_hash[:nombreJours], nights: data_hash[:nombreNuits]} : data_hash[:dureeSeance],
396
- certifications: data_hash[:agrements].blank? ? [] : data_hash[:agrements].map {|a| {id: a[:type][:id], identifier: a[:numero]}},
397
- business: business_hash
398
- }
399
- end
400
-
401
- def self.parse_service_data(data_hash, type_data_hash)
402
- if data_hash
403
- {
404
- services: lists_ids(data_hash[:services]),
405
- equipments: lists_ids(data_hash[:equipements]),
406
- comfort: lists_ids(data_hash[:conforts]),
407
- activities: lists_ids(data_hash[:activites], type_data_hash ? type_data_hash[:activites] : [],
408
- type_data_hash ? type_data_hash[:activitesSportives] : [],
409
- type_data_hash ? type_data_hash[:activitesCulturelles] : []),
410
- challenged: lists_ids(data_hash[:tourismesAdaptes]),
411
- languages: lists_ids(data_hash[:languesParlees])
412
- }
413
- end
414
- end
415
-
416
- def self.parse_tags_data(pres_data_hash, crit_data_hash, linked_data_hash)
417
- tags = {}
418
- if pres_data_hash
419
- tags[:promo] = lists_ids(pres_data_hash[:typologiesPromoSitra])
420
- end
421
- unless crit_data_hash.blank?
422
- tags[:internal] = crit_data_hash.map {|c| c[:id]}
423
- end
424
- unless linked_data_hash.blank? || linked_data_hash[:liensObjetsTouristiquesTypes].blank?
425
- tags[:linked] = linked_data_hash[:liensObjetsTouristiquesTypes]
426
- .map {|l| {apidae_id: l[:objetTouristique][:id], apidae_type: l[:objetTouristique][:type], category: l[:type]}}
427
- end
428
- tags
429
- end
430
-
431
- def self.parse_booking(reservation_hash, *locales)
432
- if reservation_hash
433
- {
434
- booking_desc: node_value(reservation_hash, :complement, *locales),
435
- booking_entities: reservation_hash[:organismes]
436
- }
437
- end
438
- end
439
-
440
- def self.entity_fields(information_hash, type_data_hash)
441
- if information_hash && information_hash[:structureGestion]
442
- {entity_id: information_hash[:structureGestion][:id], service_provider_id: node_id(type_data_hash, :prestataireActivites)}
443
- end
444
- end
445
-
446
191
  def contact_text
447
192
  entries = []
448
- JSON.parse(contact).each_pair do |k, v|
193
+ JSON.parse(contact_data).each_pair do |k, v|
449
194
  entries << "#{k}: #{v}"
450
195
  end
451
196
  entries.join("\n")
@@ -454,48 +199,5 @@ module Apidae
454
199
  def main_picture
455
200
  pictures.blank? ? "/#{Rails.application.config.apidae_pictures_path}/default/logo.png" : pictures[0]["url"].gsub('http:', 'https:')
456
201
  end
457
-
458
- def self.build_rate(rate_period)
459
- {
460
- id: rate_period[:identifiant], start_date: rate_period[:dateDebut], end_date: rate_period[:dateFin],
461
- values: rate_period[:tarifs].blank? ? [] : rate_period[:tarifs].map {|t| {min: t[:minimum], max: t[:maximum], type: t[:type][:id], details: node_value(t, :precisionTarif)}}
462
- }
463
- end
464
-
465
- private
466
-
467
- def self.node_value(node, key, *locales)
468
- l = locales.blank? ? [DEFAULT_LOCALE] : locales
469
- locales_map = Hash[l.map {|loc| [localized_key(loc), loc]}]
470
- if node && node[key]
471
- node[key].slice(*locales_map.keys).transform_keys {|k| locales_map[k]}
472
- else
473
- {}
474
- end
475
- end
476
-
477
- def self.localized_value(node, key, loc)
478
- if node && node[key]
479
- node[key][localized_key(loc)]
480
- else
481
- ''
482
- end
483
- end
484
-
485
- def self.node_id(node, key)
486
- node[key][:id] if node && node[key]
487
- end
488
-
489
- def self.lists_ids(*lists)
490
- lists.blank? ? [] : lists.map {|l| l.blank? ? [] : l.map {|elt| elt[:id]}}.flatten.uniq
491
- end
492
-
493
- def self.nodes_ids(*nodes)
494
- nodes.blank? ? [] : nodes.select {|n| !n.blank?}.map {|n| n[:id]}
495
- end
496
-
497
- def self.localized_key(loc = DEFAULT_LOCALE)
498
- "libelle#{loc.camelize.gsub('-', '')}".to_sym
499
- end
500
202
  end
501
203
  end