diff options
| author | Luc Donnet | 2017-03-22 13:33:07 +0100 |
|---|---|---|
| committer | Luc Donnet | 2017-03-22 13:33:07 +0100 |
| commit | 78e0ef962354b9cd3e6dfb51a2ccf8ed6fe5afaf (patch) | |
| tree | d194a26f6ea698a32b7f45b58abc59b10e0ae83c /lib | |
| parent | 56e6b5146aca41563b8e64ce95a7cd183fe80b13 (diff) | |
| parent | cfc35aca0f1383069e1f2cc5ed1026d085a1fc1d (diff) | |
| download | chouette-core-78e0ef962354b9cd3e6dfb51a2ccf8ed6fe5afaf.tar.bz2 | |
Merge branch 'staging' of github.com:AF83/stif-boiv into staging
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/activeattr_ext.rb | 39 | ||||
| -rw-r--r-- | lib/range_ext.rb | 7 | ||||
| -rw-r--r-- | lib/stif/codif_line_synchronization.rb | 55 | ||||
| -rw-r--r-- | lib/stif/my_workbench_scopes.rb | 23 | ||||
| -rw-r--r-- | lib/stif/reflex_synchronization.rb | 112 | ||||
| -rw-r--r-- | lib/tasks/ci.rake | 7 |
6 files changed, 192 insertions, 51 deletions
diff --git a/lib/activeattr_ext.rb b/lib/activeattr_ext.rb new file mode 100644 index 000000000..b4c112b72 --- /dev/null +++ b/lib/activeattr_ext.rb @@ -0,0 +1,39 @@ +module ActiveAttr::MultiParameterAttributes + + def assign_attributes(new_attributes, options = {}) + super( + expand_multiparameter_attributes(new_attributes), + options + ) + end + + def expand_multiparameter_attributes(attributes) + attributes ||= {} + + single_parameter_attributes = {} + multi_parameter_attributes = {} + + attributes.each do |key, value| + matches = key.match(/^(?<key>[^\(]+)\((?<index>\d+)i\)$/) + + unless matches + single_parameter_attributes[key] = value + next + end + + args = (multi_parameter_attributes[matches['key']] ||= []) + args[matches['index'].to_i - 1] = (value.present? ? value.to_i : nil) + end + + single_parameter_attributes.merge( + multi_parameter_attributes.inject({}) do |hash, (key, args)| + if args.all?(&:present?) + hash.merge(key => _attribute_type(key).new(*args)) + else + hash + end + end + ) + end + +end diff --git a/lib/range_ext.rb b/lib/range_ext.rb new file mode 100644 index 000000000..5afb44dee --- /dev/null +++ b/lib/range_ext.rb @@ -0,0 +1,7 @@ +class Range + def intersection(other) + return nil if (self.max < other.begin or other.max < self.begin) + [self.begin, other.begin].max..[self.max, other.max].min + end + alias_method :&, :intersection +end diff --git a/lib/stif/codif_line_synchronization.rb b/lib/stif/codif_line_synchronization.rb index 1be5474c2..1f52fc558 100644 --- a/lib/stif/codif_line_synchronization.rb +++ b/lib/stif/codif_line_synchronization.rb @@ -1,7 +1,28 @@ module Stif module CodifLineSynchronization class << self + attr_accessor :imported_count, :updated_count, :deleted_count + + def reset_counts + self.imported_count = 0 + self.updated_count = 0 + self.deleted_count = 0 + end + + def processed_counts + { + imported: self.imported_count, + updated: self.updated_count, + deleted: self.deleted_count + } + end + + def increment_counts prop_name, value + self.send("#{prop_name}=", self.send(prop_name) + value) + end + def synchronize + self.reset_counts start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) # Fetch Codifline data client = Codifligne::API.new @@ -47,10 +68,8 @@ module Stif # Delete deprecated Operators deleted_op = delete_deprecated(operators, Chouette::Company) log_deleted "Operators", deleted_op unless deleted_op == 0 - { - imported: operators.count + lines.count + networks.count, - deleted: deleted_op + deleted_li + deleted_ne - } + + self.processed_counts end def create_or_update_company(api_operator) @@ -70,14 +89,15 @@ module Stif deactivated: (api_line.status == "inactive" ? true : false), import_xml: api_line.xml } - - # Find Company - # TODO Check behavior when operator_codes count is 0 or > 1 - if api_line.operator_codes.any? - company_id = "STIF:CODIFLIGNE:Operator:" + api_line.operator_codes.first - params[:company] = Chouette::Company.find_by(objectid: company_id) + params[:transport_mode] = api_line.transport_mode.to_s + params[:transport_submode] = api_line.transport_submode.to_s + api_line.secondary_operator_ref.each do |id| + params[:secondary_companies] ||= [] + params[:secondary_companies] << Chouette::Company.find_by(objectid: id) + end + unless api_line.operator_ref.nil? + params[:company] = Chouette::Company.find_by(objectid: api_line.operator_ref) end - save_or_update(params, Chouette::Line) end @@ -121,13 +141,14 @@ module Stif def delete_deprecated(objects, klass) ids = objects.map{ |o| o.stif_id }.to_a deprecated = klass.where.not(objectid: ids) - deprecated.destroy_all.length + increment_counts :deleted_count, deprecated.destroy_all.length end def delete_deprecated_lines(lines) ids = lines.map{ |l| l.stif_id }.to_a deprecated = Chouette::Line.where.not(objectid: ids).where(deactivated: false) deprecated.update_all deactivated: true + increment_counts :deleted_count, deprecated.update_all(deactivated: true) end def save_or_update(params, klass) @@ -135,10 +156,16 @@ module Stif object = klass.where(objectid: params[:objectid]).first if object object.assign_attributes(params) - object.save if object.changed? + if object.changed? + object.save + increment_counts :updated_count, 1 + end else object = klass.new(params) - object.save if object.valid? + if object.valid? + object.save + increment_counts :imported_count, 1 + end end object end diff --git a/lib/stif/my_workbench_scopes.rb b/lib/stif/my_workbench_scopes.rb new file mode 100644 index 000000000..89c4e659c --- /dev/null +++ b/lib/stif/my_workbench_scopes.rb @@ -0,0 +1,23 @@ +module Stif + class MyWorkbenchScopes + attr_accessor :workbench + + def initialize(workbench) + @workbench = workbench + end + + def line_scope(initial_scope) + ids = self.parse_functional_scope + ids ? initial_scope.where(objectid: ids) : initial_scope + end + + def parse_functional_scope + return false unless @workbench.organisation.sso_attributes + begin + JSON.parse @workbench.organisation.sso_attributes['functional_scope'] + rescue Exception => e + Rails.logger.error "MyWorkbenchScopes : #{e}" + end + end + end +end diff --git a/lib/stif/reflex_synchronization.rb b/lib/stif/reflex_synchronization.rb index 822a295c0..68f7fc621 100644 --- a/lib/stif/reflex_synchronization.rb +++ b/lib/stif/reflex_synchronization.rb @@ -1,6 +1,31 @@ module Stif module ReflexSynchronization class << self + attr_accessor :imported_count, :updated_count, :deleted_count, :processed + + def reset_counts + self.imported_count = 0 + self.updated_count = 0 + self.deleted_count = 0 + self.processed = [] + end + + def processed_counts + { + imported: self.imported_count, + updated: self.updated_count, + deleted: self.deleted_count + } + end + + def log_processing_time message, time + Rails.logger.info "Reflex:sync - #{message} done in #{time} seconds" + end + + def increment_counts prop_name, value + self.send("#{prop_name}=", self.send(prop_name) + value) + end + def defaut_referential StopAreaReferential.find_by(name: "Reflex") end @@ -10,57 +35,58 @@ module Stif end def synchronize - tstart = Time.now - client = Reflex::API.new - processed = [] - initial_count = Chouette::StopArea.where(deleted_at: nil).count - + self.reset_counts ['getOR', 'getOP'].each do |method| start = Time.now - results = client.process method - Rails.logger.info "Reflex:sync - Process #{method} done in #{Time.now - start} seconds" - results.each do |type, entries| - Rails.logger.info "Reflex:sync - #{entries.count} #{type} retrieved" - end - - # Create or update stop_area for every quay, stop_place + results = Reflex::API.new().process(method) + log_processing_time("Process #{method}", Time.now - start) stop_areas = results[:Quay] | results[:StopPlace] - start = Time.now - stop_areas.each do |entry| - next unless is_valid_type_of_place_ref?(method, entry) - processed << entry['id'] - self.create_or_update_stop_area entry + time = Benchmark.measure do + stop_areas.each do |entry| + next unless is_valid_type_of_place_ref?(method, entry) + entry['TypeOfPlaceRef'] = self.stop_area_area_type entry, method + self.create_or_update_stop_area entry + self.processed << entry['id'] + end end - Rails.logger.info "Reflex:sync - Create or update StopArea done in #{Time.now - start} seconds" + log_processing_time("Create or update StopArea", time.real) - # Walk through every entry and set parent stop_area - start = Time.now - stop_areas.each do |entry| - self.stop_area_set_parent entry + time = Benchmark.measure do + stop_areas.map{|entry| self.stop_area_set_parent(entry)} end - Rails.logger.info "Reflex:sync - StopArea set parent done in #{Time.now - start} seconds" + log_processing_time("StopArea set parent", time.real) end - { - imported: Chouette::StopArea.where(deleted_at: nil).count - initial_count, - deleted: self.set_deleted_stop_area(processed.uniq).size - } + + # Set deleted_at for item not returned by api since last sync + time = Benchmark.measure { self.set_deleted_stop_area } + log_processing_time("StopArea #{self.deleted_count} deleted", time.real) + self.processed_counts end def is_valid_type_of_place_ref? method, entry return true if entry["TypeOfPlaceRef"].nil? return true if method == 'getOR' && ['ZDL', 'LDA', 'ZDE'].include?(entry["TypeOfPlaceRef"]) - return true if method == 'getOP' && ['ZDE'].include?(entry["TypeOfPlaceRef"]) + return true if method == 'getOP' && ['ZDE', 'ZDL'].include?(entry["TypeOfPlaceRef"]) + end + + def stop_area_area_type entry, method + if entry['type'] == 'Quay' + type = 'zder' if entry['OBJECT_STATUS'] == 'REFERENCE_OBJECT' + type = 'zdep' if entry['OBJECT_STATUS'] == 'LOCAL_OBJECT' + else + type = entry['TypeOfPlaceRef'] + type = "#{type.to_s}#{method.last}" unless type == 'LDA' + end + type.downcase end - def set_deleted_stop_area processed - start = Time.now - deleted = Chouette::StopArea.where(deleted_at: nil).pluck(:objectid).uniq - processed + def set_deleted_stop_area + deleted = Chouette::StopArea.where(deleted_at: nil).pluck(:objectid).uniq - self.processed.uniq deleted.each_slice(50) do |object_ids| Chouette::StopArea.where(objectid: object_ids).update_all(deleted_at: Time.now) end - Rails.logger.info "Reflex:sync - StopArea #{deleted.size} stop_area deleted since last sync in #{Time.now - start} seconds" - deleted + increment_counts :deleted_count, deleted.size end def stop_area_set_parent entry @@ -105,7 +131,11 @@ module Stif :zip_code => 'PostalRegion', :city_name => 'Town' }.each do |k, v| access[k] = entry[v] end - access.save! if access.changed? + if entry['gml:pos'] + access['longitude'] = entry['gml:pos'][:lng] + access['latitude'] = entry['gml:pos'][:lat] + end + access.save if access.valid? && access.changed? end def create_or_update_stop_area entry @@ -114,15 +144,23 @@ module Stif stop.stop_area_referential = self.defaut_referential { :name => 'Name', - :area_type => 'type', + :area_type => 'TypeOfPlaceRef', :object_version => 'version', :zip_code => 'PostalRegion', - :city_name => 'Town' + :city_name => 'Town', + :stif_type => 'OBJECT_STATUS' }.each do |k, v| stop[k] = entry[v] end + if entry['gml:pos'] + stop['longitude'] = entry['gml:pos'][:lng] + stop['latitude'] = entry['gml:pos'][:lat] + end + if stop.changed? - stop.creation_time = entry[:created] + stop.created_at = entry[:created] stop.import_xml = entry[:xml] + prop = stop.new_record? ? :imported_count : :updated_count + increment_counts prop, 1 stop.save! end # Create AccessPoint from StopPlaceEntrance diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake index 7fca878b6..52bab7aa4 100644 --- a/lib/tasks/ci.rake +++ b/lib/tasks/ci.rake @@ -3,6 +3,7 @@ namespace :ci do task :setup do cp "config/database/jenkins.yml", "config/database.yml" sh "RAILS_ENV=test rake db:migrate" + sh "npm install" end def git_branch @@ -21,6 +22,11 @@ namespace :ci do git_branch.in?(deploy_envs) ? git_branch : "dev" end + desc "Check security aspects" + task :check_security do + sh "bundle exec bundle-audit check --update" + end + desc "Deploy after CI" task :deploy do sh "cap #{deploy_env} deploy:migrations deploy:seed" @@ -34,3 +40,4 @@ end desc "Run continuous integration tasks (spec, ...)" task :ci => ["ci:setup", "spec", "cucumber", "ci:deploy", "ci:clean"] +# task :ci => ["ci:setup", "spec", "cucumber", "ci:check_security", "ci:deploy", "ci:clean"] |
