From 9304f16e56c219fd63fa12b7d42a7cbf16b2914a Mon Sep 17 00:00:00 2001 From: cedricnjanga Date: Tue, 21 Nov 2017 15:32:22 +0100 Subject: Change the way we name classes We now always use modules for namespaces => same structure for models, decorators, policies... --- app/models/chouette/access_link.rb | 89 ++-- app/models/chouette/journey_frequency.rb | 4 +- app/models/chouette/journey_pattern.rb | 187 ++++---- app/models/chouette/objectid/netex.rb | 46 +- app/models/chouette/objectid/stif_codifligne.rb | 12 +- app/models/chouette/objectid/stif_netex.rb | 18 +- app/models/chouette/objectid/stif_reflex.rb | 13 +- app/models/chouette/objectid_formatter/netex.rb | 14 +- .../chouette/objectid_formatter/stif_codifligne.rb | 14 +- .../chouette/objectid_formatter/stif_netex.rb | 8 +- .../chouette/objectid_formatter/stif_reflex.rb | 14 +- app/models/chouette/stop_point.rb | 69 ++- app/models/chouette/vehicle_journey.rb | 468 ++++++++++----------- app/models/chouette/vehicle_journey_at_stop.rb | 107 ++--- ...stops_are_in_increasing_time_order_validator.rb | 76 ++-- .../vehicle_journey_at_stops_day_offset.rb | 58 +-- app/models/chouette/vehicle_journey_frequency.rb | 101 ++--- 17 files changed, 659 insertions(+), 639 deletions(-) (limited to 'app/models') diff --git a/app/models/chouette/access_link.rb b/app/models/chouette/access_link.rb index 5e44704fd..46fbcb631 100644 --- a/app/models/chouette/access_link.rb +++ b/app/models/chouette/access_link.rb @@ -4,62 +4,63 @@ module Chouette # FIXME http://jira.codehaus.org/browse/JRUBY-6358 self.primary_key = "id" - attr_accessor :access_link_type, :link_orientation_type, :link_key + attr_accessor :access_link_type, :link_orientation_type, :link_key - belongs_to :access_point, :class_name => 'Chouette::AccessPoint' - belongs_to :stop_area, :class_name => 'Chouette::StopArea' + belongs_to :access_point, :class_name => 'Chouette::AccessPoint' + belongs_to :stop_area, :class_name => 'Chouette::StopArea' - validates_presence_of :name - validates_presence_of :link_orientation + validates_presence_of :name + validates_presence_of :link_orientation - def self.nullable_attributes - [:link_distance, :default_duration, :frequent_traveller_duration, :occasional_traveller_duration, - :mobility_restricted_traveller_duration, :link_type] - end + def self.nullable_attributes + [:link_distance, :default_duration, :frequent_traveller_duration, :occasional_traveller_duration, + :mobility_restricted_traveller_duration, :link_type] + end - def access_link_type - link_type && Chouette::ConnectionLinkType.new(link_type.underscore) - end + def access_link_type + link_type && Chouette::ConnectionLinkType.new(link_type.underscore) + end - def access_link_type=(access_link_type) - self.link_type = (access_link_type ? access_link_type.camelcase : nil) - end + def access_link_type=(access_link_type) + self.link_type = (access_link_type ? access_link_type.camelcase : nil) + end - @@access_link_types = nil - def self.access_link_types - @@access_link_types ||= Chouette::ConnectionLinkType.all - end + @@access_link_types = nil + def self.access_link_types + @@access_link_types ||= Chouette::ConnectionLinkType.all + end - def link_orientation_type - link_orientation && Chouette::LinkOrientationType.new(link_orientation.underscore) - end + def link_orientation_type + link_orientation && Chouette::LinkOrientationType.new(link_orientation.underscore) + end - def link_orientation_type=(link_orientation_type) - self.link_orientation = (link_orientation_type ? link_orientation_type.camelcase : nil) - end + def link_orientation_type=(link_orientation_type) + self.link_orientation = (link_orientation_type ? link_orientation_type.camelcase : nil) + end - @@link_orientation_types = nil - def self.link_orientation_types - @@link_orientation_types ||= Chouette::LinkOrientationType.all - end + @@link_orientation_types = nil + def self.link_orientation_types + @@link_orientation_types ||= Chouette::LinkOrientationType.all + end - def geometry - GeoRuby::SimpleFeatures::LineString.from_points( [ access_point.geometry, stop_area.geometry], 4326) if access_point.geometry and stop_area.geometry - end + def geometry + GeoRuby::SimpleFeatures::LineString.from_points( [ access_point.geometry, stop_area.geometry], 4326) if access_point.geometry and stop_area.geometry + end - def link_key - Chouette::AccessLink.build_link_key(access_point,stop_area,link_orientation_type) - end - - def self.build_link_key(access_point,stop_area,link_orientation_type) - if link_orientation_type == "access_point_to_stop_area" - "A_#{access_point.id}-S_#{stop_area.id}" - else - "S_#{stop_area.id}-A_#{access_point.id}" + def link_key + Chouette::AccessLink.build_link_key(access_point,stop_area,link_orientation_type) + end + + def self.build_link_key(access_point,stop_area,link_orientation_type) + if link_orientation_type == "access_point_to_stop_area" + "A_#{access_point.id}-S_#{stop_area.id}" + else + "S_#{stop_area.id}-A_#{access_point.id}" + end end - end - def geometry_presenter - Chouette::Geometry::AccessLinkPresenter.new self + def geometry_presenter + Chouette::Geometry::AccessLinkPresenter.new self + end end end \ No newline at end of file diff --git a/app/models/chouette/journey_frequency.rb b/app/models/chouette/journey_frequency.rb index 8e7dd1819..1b4efe96e 100644 --- a/app/models/chouette/journey_frequency.rb +++ b/app/models/chouette/journey_frequency.rb @@ -18,8 +18,8 @@ module Chouette if record.first_departure_time == record.last_departure_time record.errors[:last_departure_time] << I18n.t('activerecord.errors.models.journey_frequency.end_must_be_different_from_first') end - unless last_departure_time.between? timeband_start_time, timeband_end_time - record.errors[:last_departure_time] << I18n.t('activerecord.errors.models.journey_frequency.end_must_be_before_timeband') + if record.scheduled_headway_interval.blank? || (record.scheduled_headway_interval.strftime( "%H%M%S%N" ) == Time.current.midnight.strftime( "%H%M%S%N" )) + record.errors[:scheduled_headway_interval] << I18n.t('activerecord.errors.models.journey_frequency.scheduled_headway_interval_greater_than_zero') end end end diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb index 31b7c56be..797b6adb1 100644 --- a/app/models/chouette/journey_pattern.rb +++ b/app/models/chouette/journey_pattern.rb @@ -26,124 +26,125 @@ module Chouette "IBOO-#{self.referential.id}-#{self.route.line.get_objectid.local_id}-#{self.id}" end - def checksum_attributes - values = self.slice(*['name', 'published_name', 'registration_number']).values - values << self.stop_points.map(&:stop_area).map(&:user_objectid) - values.flatten - end + def checksum_attributes + values = self.slice(*['name', 'published_name', 'registration_number']).values + values << self.stop_points.map(&:stop_area).map(&:user_objectid) + values.flatten + end - def self.state_update route, state - transaction do - state.each do |item| - item.delete('errors') - jp = find_by(objectid: item['object_id']) || state_create_instance(route, item) - next if item['deletable'] && jp.persisted? && jp.destroy - # Update attributes and stop_points associations - jp.update_attributes(state_permited_attributes(item)) unless item['new_record'] - jp.state_stop_points_update(item) if !jp.errors.any? && jp.persisted? - item['errors'] = jp.errors if jp.errors.any? + def self.state_update route, state + transaction do + state.each do |item| + item.delete('errors') + jp = find_by(objectid: item['object_id']) || state_create_instance(route, item) + next if item['deletable'] && jp.persisted? && jp.destroy + # Update attributes and stop_points associations + jp.update_attributes(state_permited_attributes(item)) unless item['new_record'] + jp.state_stop_points_update(item) if !jp.errors.any? && jp.persisted? + item['errors'] = jp.errors if jp.errors.any? + end + + if state.any? {|item| item['errors']} + state.map {|item| item.delete('object_id') if item['new_record']} + raise ::ActiveRecord::Rollback + end end - if state.any? {|item| item['errors']} - state.map {|item| item.delete('object_id') if item['new_record']} - raise ActiveRecord::Rollback - end + state.map {|item| item.delete('new_record')} + state.delete_if {|item| item['deletable']} end - state.map {|item| item.delete('new_record')} - state.delete_if {|item| item['deletable']} - end - - def self.state_permited_attributes item - { - name: item['name'], - published_name: item['published_name'], - registration_number: item['registration_number'] - } - end - - def self.state_create_instance route, item - # Flag new record, so we can unset object_id if transaction rollback - jp = route.journey_patterns.create(state_permited_attributes(item)) + def self.state_permited_attributes item + { + name: item['name'], + published_name: item['published_name'], + registration_number: item['registration_number'] + } + end - # FIXME - # DefaultAttributesSupport will trigger some weird validation on after save - # wich will call to valid?, wich will populate errors - # In this case, we mark jp to be valid if persisted? return true - jp.errors.clear if jp.persisted? + def self.state_create_instance route, item + # Flag new record, so we can unset object_id if transaction rollback + jp = route.journey_patterns.create(state_permited_attributes(item)) - item['object_id'] = jp.objectid - item['new_record'] = true - jp - end + # FIXME + # DefaultAttributesSupport will trigger some weird validation on after save + # wich will call to valid?, wich will populate errors + # In this case, we mark jp to be valid if persisted? return true + jp.errors.clear if jp.persisted? - def state_stop_points_update item - item['stop_points'].each do |sp| - exist = stop_area_ids.include?(sp['id']) - next if exist && sp['checked'] + item['object_id'] = jp.objectid + item['new_record'] = true + jp + end - stop_point = route.stop_points.find_by(stop_area_id: sp['id']) - if !exist && sp['checked'] - stop_points << stop_point - end - if exist && !sp['checked'] - stop_points.delete(stop_point) + def state_stop_points_update item + item['stop_points'].each do |sp| + exist = stop_area_ids.include?(sp['id']) + next if exist && sp['checked'] + + stop_point = route.stop_points.find_by(stop_area_id: sp['id']) + if !exist && sp['checked'] + stop_points << stop_point + end + if exist && !sp['checked'] + stop_points.delete(stop_point) + end end end - end - # TODO: this a workarround - # otherwise, we loose the first stop_point - # when creating a new journey_pattern - def special_update - bck_sp = self.stop_points.map {|s| s} - self.update_attributes :stop_points => [] - self.update_attributes :stop_points => bck_sp - end + # TODO: this a workarround + # otherwise, we loose the first stop_point + # when creating a new journey_pattern + def special_update + bck_sp = self.stop_points.map {|s| s} + self.update_attributes :stop_points => [] + self.update_attributes :stop_points => bck_sp + end - def departure_stop_point - return unless departure_stop_point_id - Chouette::StopPoint.find( departure_stop_point_id) - end + def departure_stop_point + return unless departure_stop_point_id + Chouette::StopPoint.find( departure_stop_point_id) + end - def arrival_stop_point - return unless arrival_stop_point_id - Chouette::StopPoint.find( arrival_stop_point_id) - end + def arrival_stop_point + return unless arrival_stop_point_id + Chouette::StopPoint.find( arrival_stop_point_id) + end - def shortcuts_update_for_add( stop_point) - stop_points << stop_point unless stop_points.include?( stop_point) + def shortcuts_update_for_add( stop_point) + stop_points << stop_point unless stop_points.include?( stop_point) - ordered_stop_points = stop_points - ordered_stop_points = ordered_stop_points.sort { |a,b| a.position <=> b.position} unless ordered_stop_points.empty? + ordered_stop_points = stop_points + ordered_stop_points = ordered_stop_points.sort { |a,b| a.position <=> b.position} unless ordered_stop_points.empty? - self.update_attributes( :departure_stop_point_id => (ordered_stop_points.first && ordered_stop_points.first.id), - :arrival_stop_point_id => (ordered_stop_points.last && ordered_stop_points.last.id)) - end + self.update_attributes( :departure_stop_point_id => (ordered_stop_points.first && ordered_stop_points.first.id), + :arrival_stop_point_id => (ordered_stop_points.last && ordered_stop_points.last.id)) + end - def shortcuts_update_for_remove( stop_point) - stop_points.delete( stop_point) if stop_points.include?( stop_point) + def shortcuts_update_for_remove( stop_point) + stop_points.delete( stop_point) if stop_points.include?( stop_point) - ordered_stop_points = stop_points - ordered_stop_points = ordered_stop_points.sort { |a,b| a.position <=> b.position} unless ordered_stop_points.empty? + ordered_stop_points = stop_points + ordered_stop_points = ordered_stop_points.sort { |a,b| a.position <=> b.position} unless ordered_stop_points.empty? - self.update_attributes( :departure_stop_point_id => (ordered_stop_points.first && ordered_stop_points.first.id), - :arrival_stop_point_id => (ordered_stop_points.last && ordered_stop_points.last.id)) - end + self.update_attributes( :departure_stop_point_id => (ordered_stop_points.first && ordered_stop_points.first.id), + :arrival_stop_point_id => (ordered_stop_points.last && ordered_stop_points.last.id)) + end - def vjas_add( stop_point) - return if new_record? + def vjas_add( stop_point) + return if new_record? - vehicle_journeys.each do |vj| - vjas = vj.vehicle_journey_at_stops.create :stop_point_id => stop_point.id + vehicle_journeys.each do |vj| + vjas = vj.vehicle_journey_at_stops.create :stop_point_id => stop_point.id + end end - end - def vjas_remove( stop_point) - return if new_record? + def vjas_remove( stop_point) + return if new_record? - vehicle_journey_at_stops.where( :stop_point_id => stop_point.id).each do |vjas| - vjas.destroy + vehicle_journey_at_stops.where( :stop_point_id => stop_point.id).each do |vjas| + vjas.destroy + end end end end diff --git a/app/models/chouette/objectid/netex.rb b/app/models/chouette/objectid/netex.rb index b83ef7b8d..7953c6b12 100644 --- a/app/models/chouette/objectid/netex.rb +++ b/app/models/chouette/objectid/netex.rb @@ -1,29 +1,33 @@ -class Chouette::Objectid::Netex - include ActiveModel::Model +module Chouette + module Objectid + class Netex + include ActiveModel::Model - attr_accessor :provider_id, :object_type, :local_id, :creation_id - validates_presence_of :provider_id, :object_type, :local_id, :creation_id - validate :must_respect_format + attr_accessor :provider_id, :object_type, :local_id, :creation_id + validates_presence_of :provider_id, :object_type, :local_id, :creation_id + validate :must_respect_format - def initialize(**attributes) - @provider_id ||= (attributes[:provider_id] ||= 'chouette') - @object_type = attributes[:object_type] - @local_id = attributes[:local_id] - @creation_id = (attributes[:creation_id] ||= 'LOC') - end + def initialize(**attributes) + @provider_id ||= (attributes[:provider_id] ||= 'chouette') + @object_type = attributes[:object_type] + @local_id = attributes[:local_id] + @creation_id = (attributes[:creation_id] ||= 'LOC') + end - @@format = /^([A-Za-z_-]+):([A-Za-z]+):([0-9A-Za-z_-]+):([A-Za-z]+)$/ - cattr_reader :format + @@format = /^([A-Za-z_-]+):([A-Za-z]+):([0-9A-Za-z_-]+):([A-Za-z]+)$/ + cattr_reader :format - def to_s - "#{self.provider_id}:#{self.object_type}:#{self.local_id}:#{self.creation_id}" - end + def to_s + "#{self.provider_id}:#{self.object_type}:#{self.local_id}:#{self.creation_id}" + end - def must_respect_format - self.to_s.match(format) - end + def must_respect_format + self.to_s.match(format) + end - def short_id - local_id + def short_id + local_id + end + end end end \ No newline at end of file diff --git a/app/models/chouette/objectid/stif_codifligne.rb b/app/models/chouette/objectid/stif_codifligne.rb index d1a1e7862..a1e40f0a1 100644 --- a/app/models/chouette/objectid/stif_codifligne.rb +++ b/app/models/chouette/objectid/stif_codifligne.rb @@ -1,10 +1,12 @@ -class Chouette::Objectid::StifCodifligne < Chouette::Objectid::Netex +module Chouette + module Objectid + class StifCodifligne < Chouette::Objectid::Netex - attr_accessor :sync_id - validates_presence_of :sync_id - validates :creation_id, presence: false + attr_accessor :sync_id + validates_presence_of :sync_id + validates :creation_id, presence: false - @@format = /^([A-Za-z_]+):([A-Za-z]+):([A-Za-z]+):([0-9A-Za-z_-]+)$/ + @@format = /^([A-Za-z_]+):([A-Za-z]+):([A-Za-z]+):([0-9A-Za-z_-]+)$/ def initialize(**attributes) @provider_id = attributes[:provider_id] diff --git a/app/models/chouette/objectid/stif_netex.rb b/app/models/chouette/objectid/stif_netex.rb index 26700bf4b..80208af56 100644 --- a/app/models/chouette/objectid/stif_netex.rb +++ b/app/models/chouette/objectid/stif_netex.rb @@ -1,11 +1,15 @@ -class Chouette::Objectid::StifNetex < Chouette::Objectid::Netex +module Chouette + module Objectid + class StifNetex < Chouette::Objectid::Netex - def initialize(**attributes) - @provider_id = (attributes[:provider_id] ||= 'stif') - super - end + def initialize(**attributes) + @provider_id = (attributes[:provider_id] ||= 'stif') + super + end - def short_id - local_id.try(:split, "-").try(:[], -1) + def short_id + local_id.try(:split, "-").try(:[], -1) + end + end end end \ No newline at end of file diff --git a/app/models/chouette/objectid/stif_reflex.rb b/app/models/chouette/objectid/stif_reflex.rb index 6ffaf7c0e..69a3f52fa 100644 --- a/app/models/chouette/objectid/stif_reflex.rb +++ b/app/models/chouette/objectid/stif_reflex.rb @@ -1,10 +1,12 @@ -class Chouette::Objectid::StifReflex < Chouette::Objectid::Netex +module Chouette + module Objectid + class StifReflex < Chouette::Objectid::Netex - attr_accessor :country_code, :zip_code - validates_presence_of :country_code, :zip_code - validates :creation_id, presence: false + attr_accessor :country_code, :zip_code + validates_presence_of :country_code, :zip_code + validates :creation_id, presence: false - @@format = /^([A-Za-z_]+):([0-9A-Za-z_-]+):([A-Za-z]+):([0-9A-Za-z_-]+):([A-Za-z]+)$/ + @@format = /^([A-Za-z_]+):([0-9A-Za-z_-]+):([A-Za-z]+):([0-9A-Za-z_-]+):([A-Za-z]+)$/ def initialize(**attributes) @provider_id = attributes[:provider_id] @@ -18,5 +20,4 @@ class Chouette::Objectid::StifReflex < Chouette::Objectid::Netex end end end - end \ No newline at end of file diff --git a/app/models/chouette/objectid_formatter/netex.rb b/app/models/chouette/objectid_formatter/netex.rb index 6b64b8f82..7279fdaa5 100644 --- a/app/models/chouette/objectid_formatter/netex.rb +++ b/app/models/chouette/objectid_formatter/netex.rb @@ -5,12 +5,14 @@ module Chouette model.update_attributes(objectid: Chouette::Objectid::Netex.new(local_id: SecureRandom.uuid, object_type: model.class.name.gsub(/Chouette::/,'')).to_s) unless model.read_attribute(:objectid) end - def after_commit(model) - # unused method in this context - end + def after_commit(model) + # unused method in this context + end - def get_objectid(definition) - parts = definition.try(:split, ":") - Chouette::Objectid::Netex.new(provider_id: parts[0], object_type: parts[1], local_id: parts[2], creation_id: parts[3]) rescue nil + def get_objectid(definition) + parts = definition.try(:split, ":") + Chouette::Objectid::Netex.new(provider_id: parts[0], object_type: parts[1], local_id: parts[2], creation_id: parts[3]) rescue nil + end + end end end \ No newline at end of file diff --git a/app/models/chouette/objectid_formatter/stif_codifligne.rb b/app/models/chouette/objectid_formatter/stif_codifligne.rb index f575a4001..0624fc8a8 100644 --- a/app/models/chouette/objectid_formatter/stif_codifligne.rb +++ b/app/models/chouette/objectid_formatter/stif_codifligne.rb @@ -5,12 +5,14 @@ module Chouette # unused method in this context end - def after_commit(model) - # unused method in this context - end + def after_commit(model) + # unused method in this context + end - def get_objectid(definition) - parts = definition.try(:split, ":") - Chouette::Objectid::StifCodifligne.new(provider_id: parts[0], sync_id: parts[1], object_type: parts[2], local_id: parts[3]) rescue nil + def get_objectid(definition) + parts = definition.try(:split, ":") + Chouette::Objectid::StifCodifligne.new(provider_id: parts[0], sync_id: parts[1], object_type: parts[2], local_id: parts[3]) rescue nil + end + end end end \ No newline at end of file diff --git a/app/models/chouette/objectid_formatter/stif_netex.rb b/app/models/chouette/objectid_formatter/stif_netex.rb index 904d8503b..0256754bf 100644 --- a/app/models/chouette/objectid_formatter/stif_netex.rb +++ b/app/models/chouette/objectid_formatter/stif_netex.rb @@ -9,8 +9,10 @@ module Chouette model.update_attributes(objectid: Chouette::Objectid::StifNetex.new(provider_id: "stif", object_type: model.class.name.gsub(/Chouette::/,''), local_id: model.local_id).to_s) end - def get_objectid(definition) - parts = definition.try(:split, ":") - Chouette::Objectid::StifNetex.new(provider_id: parts[0], object_type: parts[1], local_id: parts[2], creation_id: parts[3]) rescue nil + def get_objectid(definition) + parts = definition.try(:split, ":") + Chouette::Objectid::StifNetex.new(provider_id: parts[0], object_type: parts[1], local_id: parts[2], creation_id: parts[3]) rescue nil + end + end end end \ No newline at end of file diff --git a/app/models/chouette/objectid_formatter/stif_reflex.rb b/app/models/chouette/objectid_formatter/stif_reflex.rb index ba1022c2b..5637f2806 100644 --- a/app/models/chouette/objectid_formatter/stif_reflex.rb +++ b/app/models/chouette/objectid_formatter/stif_reflex.rb @@ -5,12 +5,14 @@ module Chouette # unused method in this context end - def after_commit(model) - # unused method in this context - end + def after_commit(model) + # unused method in this context + end - def get_objectid(definition) - parts = definition.try(:split, ":") - Chouette::Objectid::StifReflex.new(country_code: parts[0], zip_code: parts[1], object_type: parts[2], local_id: parts[3], provider_id: parts[4]) rescue nil + def get_objectid(definition) + parts = definition.try(:split, ":") + Chouette::Objectid::StifReflex.new(country_code: parts[0], zip_code: parts[1], object_type: parts[2], local_id: parts[3], provider_id: parts[4]) rescue nil + end + end end end \ No newline at end of file diff --git a/app/models/chouette/stop_point.rb b/app/models/chouette/stop_point.rb index b03eca6ae..86be39d70 100644 --- a/app/models/chouette/stop_point.rb +++ b/app/models/chouette/stop_point.rb @@ -1,23 +1,23 @@ module Chouette class StopPoint < Chouette::TridentActiveRecord - def self.policy_class - RoutePolicy - end + def self.policy_class + Chouette::RoutePolicy + end - include ForBoardingEnumerations - include ForAlightingEnumerations - include ObjectidSupport + include ForBoardingEnumerations + include ForAlightingEnumerations + include ObjectidSupport - # FIXME http://jira.codehaus.org/browse/JRUBY-6358 - self.primary_key = "id" + # FIXME http://jira.codehaus.org/browse/JRUBY-6358 + self.primary_key = "id" - belongs_to :stop_area - belongs_to :route, inverse_of: :stop_points - has_many :vehicle_journey_at_stops, :dependent => :destroy - has_many :vehicle_journeys, -> {uniq}, :through => :vehicle_journey_at_stops + belongs_to :stop_area + belongs_to :route, inverse_of: :stop_points + has_many :vehicle_journey_at_stops, :dependent => :destroy + has_many :vehicle_journeys, -> {uniq}, :through => :vehicle_journey_at_stops - acts_as_list :scope => :route, top_of_list: 0 + acts_as_list :scope => :route, top_of_list: 0 validates_presence_of :stop_area @@ -27,35 +27,34 @@ module Chouette errors.add(:stop_area_id, I18n.t("stop_areas.errors.empty")) end end - end - scope :default_order, -> { order("position") } + scope :default_order, -> { order("position") } - delegate :name, to: :stop_area + delegate :name, to: :stop_area - before_destroy :remove_dependent_journey_pattern_stop_points - def remove_dependent_journey_pattern_stop_points - route.journey_patterns.each do |jp| - if jp.stop_point_ids.include?( id) - jp.stop_point_ids = jp.stop_point_ids - [id] + before_destroy :remove_dependent_journey_pattern_stop_points + def remove_dependent_journey_pattern_stop_points + route.journey_patterns.each do |jp| + if jp.stop_point_ids.include?( id) + jp.stop_point_ids = jp.stop_point_ids - [id] + end end end - end - def duplicate(for_route:) - keys_for_create = attributes.keys - %w{id objectid created_at updated_at} - atts_for_create = attributes - .slice(*keys_for_create) - .merge('route_id' => for_route.id) - self.class.create!(atts_for_create) - end + def duplicate(for_route:) + keys_for_create = attributes.keys - %w{id objectid created_at updated_at} + atts_for_create = attributes + .slice(*keys_for_create) + .merge('route_id' => for_route.id) + self.class.create!(atts_for_create) + end - def local_id - "IBOO-#{self.referential.id}-#{self.route.line.get_objectid.local_id}-#{self.route.id}-#{self.id}" - end + def local_id + "IBOO-#{self.referential.id}-#{self.route.line.get_objectid.local_id}-#{self.route.id}-#{self.id}" + end - def self.area_candidates - Chouette::StopArea.where(:area_type => ['Quay', 'BoardingPosition']) + def self.area_candidates + Chouette::StopArea.where(:area_type => ['Quay', 'BoardingPosition']) + end end - end \ No newline at end of file diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb index 1508360ce..b68909795 100644 --- a/app/models/chouette/vehicle_journey.rb +++ b/app/models/chouette/vehicle_journey.rb @@ -7,301 +7,301 @@ module Chouette # FIXME http://jira.codehaus.org/browse/JRUBY-6358 self.primary_key = "id" - enum journey_category: { timed: 0, frequency: 1 } + enum journey_category: { timed: 0, frequency: 1 } - default_scope { where(journey_category: journey_categories[:timed]) } + default_scope { where(journey_category: journey_categories[:timed]) } - attr_reader :time_table_tokens + attr_reader :time_table_tokens - def self.nullable_attributes - [:transport_mode, :published_journey_name, :vehicle_type_identifier, :published_journey_identifier, :comment, :status_value] - end + def self.nullable_attributes + [:transport_mode, :published_journey_name, :vehicle_type_identifier, :published_journey_identifier, :comment, :status_value] + end - belongs_to :company - belongs_to :route - belongs_to :journey_pattern + belongs_to :company + belongs_to :route + belongs_to :journey_pattern - has_and_belongs_to_many :footnotes, :class_name => 'Chouette::Footnote' + has_and_belongs_to_many :footnotes, :class_name => 'Chouette::Footnote' - validates_presence_of :route - validates_presence_of :journey_pattern - # validates :vehicle_journey_at_stops, - # Validation temporarily removed for day offsets - # :vjas_departure_time_must_be_before_next_stop_arrival_time, + validates_presence_of :route + validates_presence_of :journey_pattern + # validates :vehicle_journey_at_stops, + # Validation temporarily removed for day offsets + # :vjas_departure_time_must_be_before_next_stop_arrival_time, - # vehicle_journey_at_stops_are_in_increasing_time_order: false - validates_presence_of :number + # vehicle_journey_at_stops_are_in_increasing_time_order: false + validates_presence_of :number - has_many :vehicle_journey_at_stops, -> { includes(:stop_point).order("stop_points.position") }, :dependent => :destroy - has_and_belongs_to_many :time_tables, :class_name => 'Chouette::TimeTable', :foreign_key => "vehicle_journey_id", :association_foreign_key => "time_table_id" - has_many :stop_points, -> { order("stop_points.position") }, :through => :vehicle_journey_at_stops + has_many :vehicle_journey_at_stops, -> { includes(:stop_point).order("stop_points.position") }, :dependent => :destroy + has_and_belongs_to_many :time_tables, :class_name => 'Chouette::TimeTable', :foreign_key => "vehicle_journey_id", :association_foreign_key => "time_table_id" + has_many :stop_points, -> { order("stop_points.position") }, :through => :vehicle_journey_at_stops - before_validation :set_default_values, - :calculate_vehicle_journey_at_stop_day_offset + before_validation :set_default_values, + :calculate_vehicle_journey_at_stop_day_offset - # TODO: Remove this validator - # We've eliminated this validation because it prevented vehicle journeys - # from being saved with at-stops having a day offset greater than 0, - # because these would have times that were "earlier" than the previous - # at-stop. TBD by Luc whether we're deleting this validation altogether or - # instead rejiggering it to work with day offsets. - def vjas_departure_time_must_be_before_next_stop_arrival_time - notice = 'departure time must be before next stop arrival time' - vehicle_journey_at_stops.each_with_index do |current_stop, index| - next_stop = vehicle_journey_at_stops[index + 1] + # TODO: Remove this validator + # We've eliminated this validation because it prevented vehicle journeys + # from being saved with at-stops having a day offset greater than 0, + # because these would have times that were "earlier" than the previous + # at-stop. TBD by Luc whether we're deleting this validation altogether or + # instead rejiggering it to work with day offsets. + def vjas_departure_time_must_be_before_next_stop_arrival_time + notice = 'departure time must be before next stop arrival time' + vehicle_journey_at_stops.each_with_index do |current_stop, index| + next_stop = vehicle_journey_at_stops[index + 1] - next unless next_stop && (next_stop[:arrival_time] < current_stop[:departure_time]) + next unless next_stop && (next_stop[:arrival_time] < current_stop[:departure_time]) - current_stop.errors.add(:departure_time, notice) - self.errors.add(:vehicle_journey_at_stops, notice) + current_stop.errors.add(:departure_time, notice) + self.errors.add(:vehicle_journey_at_stops, notice) + end end - end - def local_id - "IBOO-#{self.referential.id}-#{self.route.line.get_objectid.local_id}-#{self.id}" - end + def local_id + "IBOO-#{self.referential.id}-#{self.route.line.get_objectid.local_id}-#{self.id}" + end - def checksum_attributes - [].tap do |attrs| - attrs << self.published_journey_name - attrs << self.published_journey_identifier - attrs << self.try(:company).try(:objectid).try(:local_id) - attrs << self.footnotes.map(&:checksum).sort - attrs << self.vehicle_journey_at_stops.map(&:checksum).sort + def checksum_attributes + [].tap do |attrs| + attrs << self.published_journey_name + attrs << self.published_journey_identifier + attrs << self.try(:company).try(:objectid).try(:local_id) + attrs << self.footnotes.map(&:checksum).sort + attrs << self.vehicle_journey_at_stops.map(&:checksum).sort + end end - end - def set_default_values - if number.nil? - self.number = 0 + def set_default_values + if number.nil? + self.number = 0 + end end - end - def calculate_vehicle_journey_at_stop_day_offset - Chouette::VehicleJourneyAtStopsDayOffset.new( - vehicle_journey_at_stops - ).update - end + def calculate_vehicle_journey_at_stop_day_offset + Chouette::VehicleJourneyAtStopsDayOffset.new( + vehicle_journey_at_stops + ).update + end - scope :without_any_time_table, -> { joins('LEFT JOIN "time_tables_vehicle_journeys" ON "time_tables_vehicle_journeys"."vehicle_journey_id" = "vehicle_journeys"."id" LEFT JOIN "time_tables" ON "time_tables"."id" = "time_tables_vehicle_journeys"."time_table_id"').where(:time_tables => { :id => nil}) } - scope :without_any_passing_time, -> { joins('LEFT JOIN "vehicle_journey_at_stops" ON "vehicle_journey_at_stops"."vehicle_journey_id" = "vehicle_journeys"."id"').where(vehicle_journey_at_stops: { id: nil }) } + scope :without_any_time_table, -> { joins('LEFT JOIN "time_tables_vehicle_journeys" ON "time_tables_vehicle_journeys"."vehicle_journey_id" = "vehicle_journeys"."id" LEFT JOIN "time_tables" ON "time_tables"."id" = "time_tables_vehicle_journeys"."time_table_id"').where(:time_tables => { :id => nil}) } + scope :without_any_passing_time, -> { joins('LEFT JOIN "vehicle_journey_at_stops" ON "vehicle_journey_at_stops"."vehicle_journey_id" = "vehicle_journeys"."id"').where(vehicle_journey_at_stops: { id: nil }) } - accepts_nested_attributes_for :vehicle_journey_at_stops, :allow_destroy => true + accepts_nested_attributes_for :vehicle_journey_at_stops, :allow_destroy => true - def presenter - @presenter ||= ::VehicleJourneyPresenter.new( self) - end + def presenter + @presenter ||= ::VehicleJourneyPresenter.new( self) + end - def vehicle_journey_at_stops_matrix - at_stops = self.vehicle_journey_at_stops.to_a.dup - active_stop_point_ids = journey_pattern.stop_points.map(&:id) + def vehicle_journey_at_stops_matrix + at_stops = self.vehicle_journey_at_stops.to_a.dup + active_stop_point_ids = journey_pattern.stop_points.map(&:id) - (route.stop_points.map(&:id) - at_stops.map(&:stop_point_id)).each do |id| - vjas = Chouette::VehicleJourneyAtStop.new(stop_point_id: id) - vjas.dummy = !active_stop_point_ids.include?(id) - at_stops.insert(route.stop_points.map(&:id).index(id), vjas) + (route.stop_points.map(&:id) - at_stops.map(&:stop_point_id)).each do |id| + vjas = Chouette::VehicleJourneyAtStop.new(stop_point_id: id) + vjas.dummy = !active_stop_point_ids.include?(id) + at_stops.insert(route.stop_points.map(&:id).index(id), vjas) + end + at_stops end - at_stops - end - def create_or_find_vjas_from_state vjas - return vehicle_journey_at_stops.find(vjas['id']) if vjas['id'] - stop_point = Chouette::StopPoint.find_by(objectid: vjas['stop_point_objectid']) - stop = vehicle_journey_at_stops.create(stop_point: stop_point) - vjas['id'] = stop.id - vjas['new_record'] = true - stop - end + def create_or_find_vjas_from_state vjas + return vehicle_journey_at_stops.find(vjas['id']) if vjas['id'] + stop_point = Chouette::StopPoint.find_by(objectid: vjas['stop_point_objectid']) + stop = vehicle_journey_at_stops.create(stop_point: stop_point) + vjas['id'] = stop.id + vjas['new_record'] = true + stop + end - def update_vjas_from_state state - state.each do |vjas| - next if vjas["dummy"] - params = {}.tap do |el| - ['arrival_time', 'departure_time'].each do |field| - time = "#{vjas[field]['hour']}:#{vjas[field]['minute']}" - el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 UTC") + def update_vjas_from_state state + state.each do |vjas| + next if vjas["dummy"] + params = {}.tap do |el| + ['arrival_time', 'departure_time'].each do |field| + time = "#{vjas[field]['hour']}:#{vjas[field]['minute']}" + el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 UTC") + end end + stop = create_or_find_vjas_from_state(vjas) + stop.update_attributes(params) + vjas.delete('errors') + vjas['errors'] = stop.errors if stop.errors.any? end - stop = create_or_find_vjas_from_state(vjas) - stop.update_attributes(params) - vjas.delete('errors') - vjas['errors'] = stop.errors if stop.errors.any? end - end - def state_update_vjas? vehicle_journey_at_stops - departure_times = vehicle_journey_at_stops.map do |vjas| - "#{vjas['departure_time']['hour']}:#{vjas['departure_time']['minute']}" + def state_update_vjas? vehicle_journey_at_stops + departure_times = vehicle_journey_at_stops.map do |vjas| + "#{vjas['departure_time']['hour']}:#{vjas['departure_time']['minute']}" + end + times = departure_times.uniq + (times.count == 1 && times[0] == '00:00') ? false : true end - times = departure_times.uniq - (times.count == 1 && times[0] == '00:00') ? false : true - end - def update_has_and_belongs_to_many_from_state item - ['time_tables', 'footnotes'].each do |assos| - saved = self.send(assos).map(&:id) + def update_has_and_belongs_to_many_from_state item + ['time_tables', 'footnotes'].each do |assos| + saved = self.send(assos).map(&:id) - (saved - item[assos].map{|t| t['id']}).each do |id| - self.send(assos).delete(self.send(assos).find(id)) - end + (saved - item[assos].map{|t| t['id']}).each do |id| + self.send(assos).delete(self.send(assos).find(id)) + end - item[assos].each do |t| - klass = "Chouette::#{assos.classify}".constantize - unless saved.include?(t['id']) - self.send(assos) << klass.find(t['id']) + item[assos].each do |t| + klass = "Chouette::#{assos.classify}".constantize + unless saved.include?(t['id']) + self.send(assos) << klass.find(t['id']) + end end end end - end - def self.state_update route, state - transaction do - state.each do |item| - item.delete('errors') - vj = find_by(objectid: item['objectid']) || state_create_instance(route, item) - next if item['deletable'] && vj.persisted? && vj.destroy + def self.state_update route, state + transaction do + state.each do |item| + item.delete('errors') + vj = find_by(objectid: item['objectid']) || state_create_instance(route, item) + next if item['deletable'] && vj.persisted? && vj.destroy - if vj.state_update_vjas?(item['vehicle_journey_at_stops']) - vj.update_vjas_from_state(item['vehicle_journey_at_stops']) + if vj.state_update_vjas?(item['vehicle_journey_at_stops']) + vj.update_vjas_from_state(item['vehicle_journey_at_stops']) + end + + vj.update_attributes(state_permited_attributes(item)) + vj.update_has_and_belongs_to_many_from_state(item) + item['errors'] = vj.errors.full_messages.uniq if vj.errors.any? end - vj.update_attributes(state_permited_attributes(item)) - vj.update_has_and_belongs_to_many_from_state(item) - item['errors'] = vj.errors.full_messages.uniq if vj.errors.any? + # Delete ids of new object from state if we had to rollback + if state.any? {|item| item['errors']} + state.map do |item| + item.delete('objectid') if item['new_record'] + item['vehicle_journey_at_stops'].map {|vjas| vjas.delete('id') if vjas['new_record'] } + end + raise ::ActiveRecord::Rollback + end end - # Delete ids of new object from state if we had to rollback - if state.any? {|item| item['errors']} - state.map do |item| - item.delete('objectid') if item['new_record'] - item['vehicle_journey_at_stops'].map {|vjas| vjas.delete('id') if vjas['new_record'] } - end - raise ::ActiveRecord::Rollback + # Remove new_record flag && deleted item from state if transaction has been saved + state.map do |item| + item.delete('new_record') + item['vehicle_journey_at_stops'].map {|vjas| vjas.delete('new_record') } end + state.delete_if {|item| item['deletable']} end - # Remove new_record flag && deleted item from state if transaction has been saved - state.map do |item| - item.delete('new_record') - item['vehicle_journey_at_stops'].map {|vjas| vjas.delete('new_record') } + def self.state_create_instance route, item + # Flag new record, so we can unset object_id if transaction rollback + vj = route.vehicle_journeys.create(state_permited_attributes(item)) + item['objectid'] = vj.objectid + item['new_record'] = true + vj end - state.delete_if {|item| item['deletable']} - end - def self.state_create_instance route, item - # Flag new record, so we can unset object_id if transaction rollback - vj = route.vehicle_journeys.create(state_permited_attributes(item)) - item['objectid'] = vj.objectid - item['new_record'] = true - vj - end + def self.state_permited_attributes item + attrs = item.slice('published_journey_identifier', 'published_journey_name', 'journey_pattern_id', 'company_id').to_hash + ['company', 'journey_pattern'].map do |association| + attrs["#{association}_id"] = item[association]['id'] if item[association] + end + attrs + end - def self.state_permited_attributes item - attrs = item.slice('published_journey_identifier', 'published_journey_name', 'journey_pattern_id', 'company_id').to_hash - ['company', 'journey_pattern'].map do |association| - attrs["#{association}_id"] = item[association]['id'] if item[association] + def missing_stops_in_relation_to_a_journey_pattern(selected_journey_pattern) + selected_journey_pattern.stop_points - self.stop_points end - attrs - end + def extra_stops_in_relation_to_a_journey_pattern(selected_journey_pattern) + self.stop_points - selected_journey_pattern.stop_points + end + def extra_vjas_in_relation_to_a_journey_pattern(selected_journey_pattern) + extra_stops = self.extra_stops_in_relation_to_a_journey_pattern(selected_journey_pattern) + self.vehicle_journey_at_stops.select { |vjas| extra_stops.include?( vjas.stop_point)} + end + def time_table_tokens=(ids) + self.time_table_ids = ids.split(",") + end + def bounding_dates + dates = [] - def missing_stops_in_relation_to_a_journey_pattern(selected_journey_pattern) - selected_journey_pattern.stop_points - self.stop_points - end - def extra_stops_in_relation_to_a_journey_pattern(selected_journey_pattern) - self.stop_points - selected_journey_pattern.stop_points - end - def extra_vjas_in_relation_to_a_journey_pattern(selected_journey_pattern) - extra_stops = self.extra_stops_in_relation_to_a_journey_pattern(selected_journey_pattern) - self.vehicle_journey_at_stops.select { |vjas| extra_stops.include?( vjas.stop_point)} - end - def time_table_tokens=(ids) - self.time_table_ids = ids.split(",") - end - def bounding_dates - dates = [] + time_tables.each do |tm| + dates << tm.start_date if tm.start_date + dates << tm.end_date if tm.end_date + end - time_tables.each do |tm| - dates << tm.start_date if tm.start_date - dates << tm.end_date if tm.end_date + dates.empty? ? [] : [dates.min, dates.max] end - dates.empty? ? [] : [dates.min, dates.max] - end + def update_journey_pattern( selected_journey_pattern) + return unless selected_journey_pattern.route_id==self.route_id - def update_journey_pattern( selected_journey_pattern) - return unless selected_journey_pattern.route_id==self.route_id - - missing_stops_in_relation_to_a_journey_pattern(selected_journey_pattern).each do |sp| - self.vehicle_journey_at_stops.build( :stop_point => sp) - end - extra_vjas_in_relation_to_a_journey_pattern(selected_journey_pattern).each do |vjas| - vjas._destroy = true + missing_stops_in_relation_to_a_journey_pattern(selected_journey_pattern).each do |sp| + self.vehicle_journey_at_stops.build( :stop_point => sp) + end + extra_vjas_in_relation_to_a_journey_pattern(selected_journey_pattern).each do |vjas| + vjas._destroy = true + end end - end - def self.matrix(vehicle_journeys) - {}.tap do |hash| - vehicle_journeys.map{ |vj| - vj.vehicle_journey_at_stops.map{ |vjas |hash[ "#{vj.id}-#{vjas.stop_point_id}"] = vjas } - } + def self.matrix(vehicle_journeys) + {}.tap do |hash| + vehicle_journeys.map{ |vj| + vj.vehicle_journey_at_stops.map{ |vjas |hash[ "#{vj.id}-#{vjas.stop_point_id}"] = vjas } + } + end end - end - def self.with_stops - self - .joins(:journey_pattern) - .joins(' - LEFT JOIN "vehicle_journey_at_stops" - ON "vehicle_journey_at_stops"."vehicle_journey_id" = - "vehicle_journeys"."id" - AND "vehicle_journey_at_stops"."stop_point_id" = - "journey_patterns"."departure_stop_point_id" - ') - .order('"vehicle_journey_at_stops"."departure_time"') - end + def self.with_stops + self + .joins(:journey_pattern) + .joins(' + LEFT JOIN "vehicle_journey_at_stops" + ON "vehicle_journey_at_stops"."vehicle_journey_id" = + "vehicle_journeys"."id" + AND "vehicle_journey_at_stops"."stop_point_id" = + "journey_patterns"."departure_stop_point_id" + ') + .order('"vehicle_journey_at_stops"."departure_time"') + end - # Requires a SELECT DISTINCT and a join with - # "vehicle_journey_at_stops". - # - # Example: - # .select('DISTINCT "vehicle_journeys".*') - # .joins(' - # LEFT JOIN "vehicle_journey_at_stops" - # ON "vehicle_journey_at_stops"."vehicle_journey_id" = - # "vehicle_journeys"."id" - # ') - # .where_departure_time_between('08:00', '09:45') - def self.where_departure_time_between( - start_time, - end_time, - allow_empty: false - ) - self - .where( - %Q( - "vehicle_journey_at_stops"."departure_time" >= ? - AND "vehicle_journey_at_stops"."departure_time" <= ? - #{ - if allow_empty - 'OR "vehicle_journey_at_stops"."id" IS NULL' - end - } - ), - "2000-01-01 #{start_time}:00 UTC", - "2000-01-01 #{end_time}:00 UTC" - ) - end + # Requires a SELECT DISTINCT and a join with + # "vehicle_journey_at_stops". + # + # Example: + # .select('DISTINCT "vehicle_journeys".*') + # .joins(' + # LEFT JOIN "vehicle_journey_at_stops" + # ON "vehicle_journey_at_stops"."vehicle_journey_id" = + # "vehicle_journeys"."id" + # ') + # .where_departure_time_between('08:00', '09:45') + def self.where_departure_time_between( + start_time, + end_time, + allow_empty: false + ) + self + .where( + %Q( + "vehicle_journey_at_stops"."departure_time" >= ? + AND "vehicle_journey_at_stops"."departure_time" <= ? + #{ + if allow_empty + 'OR "vehicle_journey_at_stops"."id" IS NULL' + end + } + ), + "2000-01-01 #{start_time}:00 UTC", + "2000-01-01 #{end_time}:00 UTC" + ) + end - def self.without_time_tables - # Joins the VehicleJourney–TimeTable through table to select only those - # VehicleJourneys that don't have an associated TimeTable. - self - .joins(' - LEFT JOIN "time_tables_vehicle_journeys" - ON "time_tables_vehicle_journeys"."vehicle_journey_id" = - "vehicle_journeys"."id" - ') - .where('"time_tables_vehicle_journeys"."vehicle_journey_id" IS NULL') + def self.without_time_tables + # Joins the VehicleJourney–TimeTable through table to select only those + # VehicleJourneys that don't have an associated TimeTable. + self + .joins(' + LEFT JOIN "time_tables_vehicle_journeys" + ON "time_tables_vehicle_journeys"."vehicle_journey_id" = + "vehicle_journeys"."id" + ') + .where('"time_tables_vehicle_journeys"."vehicle_journey_id" IS NULL') + end end - end \ No newline at end of file diff --git a/app/models/chouette/vehicle_journey_at_stop.rb b/app/models/chouette/vehicle_journey_at_stop.rb index 8167dab47..6f0119e74 100644 --- a/app/models/chouette/vehicle_journey_at_stop.rb +++ b/app/models/chouette/vehicle_journey_at_stop.rb @@ -4,75 +4,76 @@ module Chouette include Chouette::ForAlightingEnumerations include ChecksumSupport - DAY_OFFSET_MAX = 1 + DAY_OFFSET_MAX = 1 - # FIXME http://jira.codehaus.org/browse/JRUBY-6358 - self.primary_key = "id" + # FIXME http://jira.codehaus.org/browse/JRUBY-6358 + self.primary_key = "id" - belongs_to :stop_point - belongs_to :vehicle_journey + belongs_to :stop_point + belongs_to :vehicle_journey - attr_accessor :_destroy, :dummy + attr_accessor :_destroy, :dummy - validate :arrival_must_be_before_departure - def arrival_must_be_before_departure - # security against nil values - return unless arrival_time && departure_time + validate :arrival_must_be_before_departure + def arrival_must_be_before_departure + # security against nil values + return unless arrival_time && departure_time - if TimeDuration.exceeds_gap?(4.hours, arrival_time, departure_time) - errors.add( - :arrival_time, - I18n.t("activerecord.errors.models.vehicle_journey_at_stop.arrival_must_be_before_departure") - ) + if TimeDuration.exceeds_gap?(4.hours, arrival_time, departure_time) + errors.add( + :arrival_time, + I18n.t("activerecord.errors.models.vehicle_journey_at_stop.arrival_must_be_before_departure") + ) + end end - end - validate :day_offset_must_be_within_range + validate :day_offset_must_be_within_range - after_initialize :set_virtual_attributes - def set_virtual_attributes - @_destroy = false - @dummy = false - end + after_initialize :set_virtual_attributes + def set_virtual_attributes + @_destroy = false + @dummy = false + end - def day_offset_must_be_within_range - if day_offset_outside_range?(arrival_day_offset) - errors.add( - :arrival_day_offset, - I18n.t( - 'vehicle_journey_at_stops.errors.day_offset_must_not_exceed_max', - short_id: vehicle_journey.get_objectid.short_id, - max: DAY_OFFSET_MAX + 1 + def day_offset_must_be_within_range + if day_offset_outside_range?(arrival_day_offset) + errors.add( + :arrival_day_offset, + I18n.t( + 'vehicle_journey_at_stops.errors.day_offset_must_not_exceed_max', + short_id: vehicle_journey.get_objectid.short_id, + max: DAY_OFFSET_MAX + 1 + ) ) - ) - end + end - if day_offset_outside_range?(departure_day_offset) - errors.add( - :departure_day_offset, - I18n.t( - 'vehicle_journey_at_stops.errors.day_offset_must_not_exceed_max', - short_id: vehicle_journey.get_objectid.short_id, - max: DAY_OFFSET_MAX + 1 + if day_offset_outside_range?(departure_day_offset) + errors.add( + :departure_day_offset, + I18n.t( + 'vehicle_journey_at_stops.errors.day_offset_must_not_exceed_max', + short_id: vehicle_journey.get_objectid.short_id, + max: DAY_OFFSET_MAX + 1 + ) ) - ) + end end - end - def day_offset_outside_range?(offset) - # At-stops that were created before the database-default of 0 will have - # nil offsets. Handle these gracefully by forcing them to a 0 offset. - offset ||= 0 + def day_offset_outside_range?(offset) + # At-stops that were created before the database-default of 0 will have + # nil offsets. Handle these gracefully by forcing them to a 0 offset. + offset ||= 0 - offset < 0 || offset > DAY_OFFSET_MAX - end + offset < 0 || offset > DAY_OFFSET_MAX + end - def checksum_attributes - [].tap do |attrs| - attrs << self.departure_time.try(:to_s, :time) - attrs << self.arrival_time.try(:to_s, :time) - attrs << self.departure_day_offset.to_s - attrs << self.arrival_day_offset.to_s + def checksum_attributes + [].tap do |attrs| + attrs << self.departure_time.try(:to_s, :time) + attrs << self.arrival_time.try(:to_s, :time) + attrs << self.departure_day_offset.to_s + attrs << self.arrival_day_offset.to_s + end end end end \ No newline at end of file diff --git a/app/models/chouette/vehicle_journey_at_stops_are_in_increasing_time_order_validator.rb b/app/models/chouette/vehicle_journey_at_stops_are_in_increasing_time_order_validator.rb index 0d8bc2fca..db48a6108 100644 --- a/app/models/chouette/vehicle_journey_at_stops_are_in_increasing_time_order_validator.rb +++ b/app/models/chouette/vehicle_journey_at_stops_are_in_increasing_time_order_validator.rb @@ -1,54 +1,50 @@ -<<<<<<< HEAD + module Chouette class VehicleJourneyAtStopsAreInIncreasingTimeOrderValidator < ActiveModel::EachValidator def validate_each(vehicle_journey, attribute, value) previous_at_stop = nil -======= -class Chouette::VehicleJourneyAtStopsAreInIncreasingTimeOrderValidator < ActiveModel::EachValidator - def validate_each(vehicle_journey, attribute, value) - previous_at_stop = nil ->>>>>>> Change the use of namespace and remove modules - vehicle_journey - .vehicle_journey_at_stops - .select { |vjas| vjas.departure_time && vjas.arrival_time } - .each do |vjas| - unless self.class.validate_at_stop_times_must_increase( - vjas, - previous_at_stop - ) - vehicle_journey.errors.add( - :vehicle_journey_at_stops, - 'time gap overflow' + vehicle_journey + .vehicle_journey_at_stops + .select { |vjas| vjas.departure_time && vjas.arrival_time } + .each do |vjas| + unless self.class.validate_at_stop_times_must_increase( + vjas, + previous_at_stop ) + vehicle_journey.errors.add( + :vehicle_journey_at_stops, + 'time gap overflow' + ) + end + + previous_at_stop = vjas end + end - previous_at_stop = vjas - end - end + def self.validate_at_stop_times_must_increase(at_stop, previous_at_stop) + valid = true + return valid unless previous_at_stop - def self.validate_at_stop_times_must_increase(at_stop, previous_at_stop) - valid = true - return valid unless previous_at_stop + if TimeDuration.exceeds_gap?( + 4.hours, + previous_at_stop.departure_time, + at_stop.departure_time + ) + valid = false + at_stop.errors.add(:departure_time, 'departure time gap overflow') + end - if TimeDuration.exceeds_gap?( - 4.hours, - previous_at_stop.departure_time, - at_stop.departure_time - ) - valid = false - at_stop.errors.add(:departure_time, 'departure time gap overflow') - end + if TimeDuration.exceeds_gap?( + 4.hours, + previous_at_stop.arrival_time, + at_stop.arrival_time + ) + valid = false + at_stop.errors.add(:arrival_time, 'arrival time gap overflow') + end - if TimeDuration.exceeds_gap?( - 4.hours, - previous_at_stop.arrival_time, - at_stop.arrival_time - ) - valid = false - at_stop.errors.add(:arrival_time, 'arrival time gap overflow') + valid end - - valid end end \ No newline at end of file diff --git a/app/models/chouette/vehicle_journey_at_stops_day_offset.rb b/app/models/chouette/vehicle_journey_at_stops_day_offset.rb index 60b8c2edf..b2cb90d11 100644 --- a/app/models/chouette/vehicle_journey_at_stops_day_offset.rb +++ b/app/models/chouette/vehicle_journey_at_stops_day_offset.rb @@ -1,40 +1,42 @@ -class Chouette::VehicleJourneyAtStopsDayOffset - def initialize(at_stops) - @at_stops = at_stops - end +module Chouette + class VehicleJourneyAtStopsDayOffset + def initialize(at_stops) + @at_stops = at_stops + end - def calculate! - arrival_offset = 0 - departure_offset = 0 + def calculate! + arrival_offset = 0 + departure_offset = 0 - @at_stops.inject(nil) do |prior_stop, stop| - next stop if prior_stop.nil? + @at_stops.inject(nil) do |prior_stop, stop| + next stop if prior_stop.nil? - if stop.arrival_time < prior_stop.departure_time || - stop.arrival_time < prior_stop.arrival_time - arrival_offset += 1 - end + if stop.arrival_time < prior_stop.departure_time || + stop.arrival_time < prior_stop.arrival_time + arrival_offset += 1 + end - if stop.departure_time < stop.arrival_time || - stop.departure_time < prior_stop.departure_time - departure_offset += 1 - end + if stop.departure_time < stop.arrival_time || + stop.departure_time < prior_stop.departure_time + departure_offset += 1 + end - stop.arrival_day_offset = arrival_offset - stop.departure_day_offset = departure_offset + stop.arrival_day_offset = arrival_offset + stop.departure_day_offset = departure_offset - stop + stop + end end - end - def save - @at_stops.each do |at_stop| - at_stop.save + def save + @at_stops.each do |at_stop| + at_stop.save + end end - end - def update - calculate! - save + def update + calculate! + save + end end end \ No newline at end of file diff --git a/app/models/chouette/vehicle_journey_frequency.rb b/app/models/chouette/vehicle_journey_frequency.rb index 28619912f..53e85121f 100644 --- a/app/models/chouette/vehicle_journey_frequency.rb +++ b/app/models/chouette/vehicle_journey_frequency.rb @@ -1,68 +1,69 @@ module Chouette class VehicleJourneyFrequency < Chouette::VehicleJourney - after_initialize :fill_journey_category + after_initialize :fill_journey_category - default_scope { where(journey_category: journey_categories[:frequency]) } + default_scope { where(journey_category: journey_categories[:frequency]) } - has_many :journey_frequencies, dependent: :destroy, foreign_key: 'vehicle_journey_id' - accepts_nested_attributes_for :journey_frequencies, allow_destroy: true + has_many :journey_frequencies, dependent: :destroy, foreign_key: 'vehicle_journey_id' + accepts_nested_attributes_for :journey_frequencies, allow_destroy: true - validate :require_at_least_one_frequency + validate :require_at_least_one_frequency - def self.matrix(vehicle_journeys) - hash = {} - vehicle_journeys.each do |vj| - vj.journey_frequencies.each do |jf| - next if jf.scheduled_headway_interval.hour == 0 && jf.scheduled_headway_interval.min == 0 - interval = jf.scheduled_headway_interval.hour.hours + jf.scheduled_headway_interval.min.minutes - first_departure_time = jf.first_departure_time - while first_departure_time <= jf.last_departure_time - hash[first_departure_time] = vj - first_departure_time += interval + def self.matrix(vehicle_journeys) + hash = {} + vehicle_journeys.each do |vj| + vj.journey_frequencies.each do |jf| + next if jf.scheduled_headway_interval.hour == 0 && jf.scheduled_headway_interval.min == 0 + interval = jf.scheduled_headway_interval.hour.hours + jf.scheduled_headway_interval.min.minutes + first_departure_time = jf.first_departure_time + while first_departure_time <= jf.last_departure_time + hash[first_departure_time] = vj + first_departure_time += interval + end end end + hash.sort.to_h end - hash.sort.to_h - end - def self.matrix_interval(matrix) - hash = prepare_matrix(matrix) - matrix.each do |departure_time, vj| - @base_departure_time = departure_time - vj.vehicle_journey_at_stops.each_cons(2) { |vjas, vjas_next| - vjas_dup = vjas.dup - vjas_dup.departure_time = @base_departure_time - hash[vjas.stop_point.stop_area.name][departure_time.to_i] = vjas_dup - @base_departure_time = vjas_dup.departure_time + (vjas_next.departure_time - vjas.departure_time) - @last_vjas_next = vjas_next.dup - } - # Add last stop_point - @last_vjas_next.departure_time = @base_departure_time - hash[@last_vjas_next.stop_point.stop_area.name][departure_time.to_i] = @last_vjas_next + def self.matrix_interval(matrix) + hash = prepare_matrix(matrix) + matrix.each do |departure_time, vj| + @base_departure_time = departure_time + vj.vehicle_journey_at_stops.each_cons(2) { |vjas, vjas_next| + vjas_dup = vjas.dup + vjas_dup.departure_time = @base_departure_time + hash[vjas.stop_point.stop_area.name][departure_time.to_i] = vjas_dup + @base_departure_time = vjas_dup.departure_time + (vjas_next.departure_time - vjas.departure_time) + @last_vjas_next = vjas_next.dup + } + # Add last stop_point + @last_vjas_next.departure_time = @base_departure_time + hash[@last_vjas_next.stop_point.stop_area.name][departure_time.to_i] = @last_vjas_next + end + hash end - hash - end - private + private - def self.prepare_matrix(matrix) - matrix.map{ |departure_time, vj| - Hash[ - vj.vehicle_journey_at_stops.map{ |sp| - [ - sp.stop_point.stop_area.name, Hash[matrix.map{ |departure_time2, vj2| [departure_time2.to_i, nil] }] - ] - } - ] - }.inject(&:merge) - end + def self.prepare_matrix(matrix) + matrix.map{ |departure_time, vj| + Hash[ + vj.vehicle_journey_at_stops.map{ |sp| + [ + sp.stop_point.stop_area.name, Hash[matrix.map{ |departure_time2, vj2| [departure_time2.to_i, nil] }] + ] + } + ] + }.inject(&:merge) + end - def fill_journey_category - self.journey_category = :frequency - end + def fill_journey_category + self.journey_category = :frequency + end - def require_at_least_one_frequency - errors.add(:base, I18n.t('vehicle_journey_frequency.require_at_least_one_frequency')) unless journey_frequencies.size > 0 + def require_at_least_one_frequency + errors.add(:base, I18n.t('vehicle_journey_frequency.require_at_least_one_frequency')) unless journey_frequencies.size > 0 + end end end \ No newline at end of file -- cgit v1.2.3