apidae 0.9.26 → 1.0.3

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.
@@ -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