apidae 0.9.26 → 1.0.3

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