aboutsummaryrefslogtreecommitdiffstats
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/chouette/vehicle_journey.rb9
-rw-r--r--app/models/concerns/application_days_support.rb47
-rw-r--r--app/models/simple_exporter.rb116
-rw-r--r--app/models/simple_interface.rb14
4 files changed, 125 insertions, 61 deletions
diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb
index 9b94f7f0e..49a2b387e 100644
--- a/app/models/chouette/vehicle_journey.rb
+++ b/app/models/chouette/vehicle_journey.rb
@@ -89,7 +89,6 @@ module Chouette
end
}
-
scope :in_purchase_window, ->(range){
purchase_windows = Chouette::PurchaseWindow.overlap_dates(range)
sql = purchase_windows.joins(:vehicle_journeys).select('vehicle_journeys.id').uniq.to_sql
@@ -156,6 +155,14 @@ module Chouette
end
end
+ def sales_start
+ purchase_windows.map{|p| p.date_ranges.first}.min
+ end
+
+ def sales_end
+ purchase_windows.map{|p| p.date_ranges.last}.max
+ end
+
def calculate_vehicle_journey_at_stop_day_offset
Chouette::VehicleJourneyAtStopsDayOffset.new(
vehicle_journey_at_stops
diff --git a/app/models/concerns/application_days_support.rb b/app/models/concerns/application_days_support.rb
index 348436aa4..2d00b5847 100644
--- a/app/models/concerns/application_days_support.rb
+++ b/app/models/concerns/application_days_support.rb
@@ -15,41 +15,34 @@ module ApplicationDaysSupport
end
def day_by_mask(flag)
- int_day_types & flag == flag
+ self.class.day_by_mask int_day_types, flag
end
- def self.day_by_mask(int_day_types,flag)
- int_day_types & flag == flag
+ def valid_day? wday
+ valid_days.include?(wday)
end
- def valid_days
- # Build an array with day of calendar week (1-7, Monday is 1).
- [].tap do |valid_days|
- valid_days << 1 if monday
- valid_days << 2 if tuesday
- valid_days << 3 if wednesday
- valid_days << 4 if thursday
- valid_days << 5 if friday
- valid_days << 6 if saturday
- valid_days << 7 if sunday
+ included do
+ def self.valid_days(int_day_types)
+ # Build an array with day of calendar week (1-7, Monday is 1).
+ [].tap do |valid_days|
+ valid_days << 1 if day_by_mask(int_day_types,MONDAY)
+ valid_days << 2 if day_by_mask(int_day_types,TUESDAY)
+ valid_days << 3 if day_by_mask(int_day_types,WEDNESDAY)
+ valid_days << 4 if day_by_mask(int_day_types,THURSDAY)
+ valid_days << 5 if day_by_mask(int_day_types,FRIDAY)
+ valid_days << 6 if day_by_mask(int_day_types,SATURDAY)
+ valid_days << 7 if day_by_mask(int_day_types,SUNDAY)
+ end
end
- end
- def valid_day? wday
- valid_days.include?(wday)
+ def self.day_by_mask(int_day_types,flag)
+ int_day_types & flag == flag
+ end
end
- def self.valid_days(int_day_types)
- # Build an array with day of calendar week (1-7, Monday is 1).
- [].tap do |valid_days|
- valid_days << 1 if day_by_mask(int_day_types,MONDAY)
- valid_days << 2 if day_by_mask(int_day_types,TUESDAY)
- valid_days << 3 if day_by_mask(int_day_types,WEDNESDAY)
- valid_days << 4 if day_by_mask(int_day_types,THURSDAY)
- valid_days << 5 if day_by_mask(int_day_types,FRIDAY)
- valid_days << 6 if day_by_mask(int_day_types,SATURDAY)
- valid_days << 7 if day_by_mask(int_day_types,SUNDAY)
- end
+ def valid_days
+ self.class.valid_days int_day_types
end
def monday
diff --git a/app/models/simple_exporter.rb b/app/models/simple_exporter.rb
index f9b1c0a80..9c12a4e02 100644
--- a/app/models/simple_exporter.rb
+++ b/app/models/simple_exporter.rb
@@ -10,10 +10,13 @@ class SimpleExporter < SimpleInterface
@padding = 1
@current_line = -1
@number_of_lines = collection.size
+
@padding = [1, Math.log(@number_of_lines, 10).ceil()].max
@csv = nil
fail_with_error "Unable to write in file: #{self.filepath}" do
+ dir = Pathname.new(self.filepath).dirname
+ FileUtils.mkdir_p dir
@csv = CSV.open(self.filepath, 'w', self.configuration.csv_options)
end
@@ -54,56 +57,100 @@ class SimpleExporter < SimpleInterface
log "Starting export ...", color: :green
log "Export will be written in #{filepath}", color: :green
@csv << self.configuration.columns.map(&:name)
- ids = collection.pluck :id
- ids.in_groups_of(configuration.batch_size).each do |batch_ids|
- collection.where(id: batch_ids).each do |item|
- @current_row = item.attributes
- @current_row = @current_row.slice(*configuration.logged_attributes) if configuration.logged_attributes.present?
- row = []
- @new_status = nil
- self.configuration.columns.each do |col|
- val = col[:value]
- if val.nil? || val.is_a?(Proc)
- if item.respond_to? col.attribute
- if val.is_a?(Proc)
- val = instance_exec(item.send(col.attribute), &val)
- else
- val = item.send(col.attribute)
- end
- else
- push_in_journal({event: :attribute_not_found, message: "Attribute not found: #{col.attribute}", kind: :warning})
- self.status ||= :success_with_warnings
- end
+ if collection.is_a?(ActiveRecord::Relation) && collection.model.column_names.include?("id")
+ ids = collection.pluck :id
+ ids.in_groups_of(configuration.batch_size).each do |batch_ids|
+ collection.where(id: batch_ids).each do |item|
+ handle_item item
+ end
+ end
+ else
+ collection.each{|item| handle_item item }
+ end
+ print_state
+ end
+
+ def map_item_to_rows item
+ return [item] unless configuration.item_to_rows_mapping
+ configuration.item_to_rows_mapping.call(item).map {|row| CustomRow.new row }
+ end
+
+ def handle_item item
+ number_of_lines = @number_of_lines
+ map_item_to_rows(item).each_with_index do |item, i|
+ @number_of_lines = number_of_lines + i
+ @current_row = item.attributes
+ @current_row = @current_row.slice(*configuration.logged_attributes) if configuration.logged_attributes.present?
+ row = []
+ @new_status = nil
+ self.configuration.columns.each do |col|
+ scoped_item = col.scope.inject(item){|tmp, scope| tmp.send(scope)}
+ val = col[:value]
+ if val.nil? || val.is_a?(Proc)
+ if val.is_a?(Proc)
+ val = instance_exec(scoped_item, &val)
+ else
+ attributes = [col.attribute].flatten
+ val = attributes.inject(scoped_item){|tmp, attr| tmp.send(attr)}
end
+ end
+ if val.nil?
+ push_in_journal({event: :attribute_not_found, message: "Value missing for: #{[col.scope, col.attribute].flatten.join('.')}", kind: :warning})
+ self.status ||= :success_with_warnings
+ end
- if val.nil? && col.required?
- @new_status = colorize("x", :red)
- raise "MISSING VALUE FOR COLUMN #{col.name}"
+ if val.nil? && col.required?
+ @new_status = colorize("x", :red)
+ raise "MISSING VALUE FOR COLUMN #{col.name}"
+ end
+ @new_status ||= colorize("✓", :green)
+ val = encode_string(val) if val.is_a?(String)
+ row << val
+ end
+ push_in_journal({event: :success, kind: :log})
+ @statuses += @new_status
+ print_state if @current_line % 20 == 0
+ @current_line += 1
+ @csv << row
+ end
+ end
+
+ class CustomRow < OpenStruct
+ def initialize data
+ super data
+ @data = data
+ end
+
+ def attributes
+ flatten_hash @data
+ end
+
+ protected
+ def flatten_hash h
+ h.each_with_object({}) do |(k, v), h|
+ if v.is_a? Hash
+ flatten_hash(v).map do |h_k, h_v|
+ h["#{k}.#{h_k}".to_sym] = h_v
end
- @new_status ||= colorize("✓", :green)
- val = encode_string(val) if val.is_a?(String)
- row << val
+ else
+ h[k] = v
end
- push_in_journal({event: :success, kind: :log})
- @statuses += @new_status
- print_state if @current_line % 20 == 0
- @current_line += 1
- @csv << row
end
end
- print_state
end
class Configuration < SimpleInterface::Configuration
attr_accessor :collection
attr_accessor :batch_size
attr_accessor :logged_attributes
+ attr_accessor :item_to_rows_mapping
def initialize import_name, opts={}
super import_name, opts
@collection = opts[:collection]
@batch_size = opts[:batch_size] || 1000
@logged_attributes = opts[:logged_attributes]
+ @item_to_rows_mapping = opts[:item_to_rows_mapping]
end
def options
@@ -111,9 +158,14 @@ class SimpleExporter < SimpleInterface
collection: collection,
batch_size: batch_size,
logged_attributes: logged_attributes,
+ item_to_rows_mapping: item_to_rows_mapping,
})
end
+ def map_item_to_rows &block
+ @item_to_rows_mapping = block
+ end
+
def add_column name, opts={}
raise "Column already defined: #{name}" if @columns.any?{|c| c.name == name.to_s}
super name, opts
diff --git a/app/models/simple_interface.rb b/app/models/simple_interface.rb
index 3d5027bf1..5f022719a 100644
--- a/app/models/simple_interface.rb
+++ b/app/models/simple_interface.rb
@@ -167,6 +167,13 @@ class SimpleInterface < ActiveRecord::Base
@scope = opts[:scope]
end
+ def on_relation relation_name
+ @scope ||= []
+ @scope.push relation_name
+ yield
+ @scope.pop
+ end
+
def duplicate
self.class.new @import_name, self.options
end
@@ -211,7 +218,8 @@ class SimpleInterface < ActiveRecord::Base
end
def add_column name, opts={}
- @columns.push Column.new({name: name.to_s}.update(opts))
+ @scope ||= []
+ @columns.push Column.new({name: name.to_s, scope: @scope.dup}.update(opts))
end
def add_value attribute, value
@@ -262,6 +270,10 @@ class SimpleInterface < ActiveRecord::Base
!!@options[:required]
end
+ def scope
+ @options[:scope] || []
+ end
+
def [](key)
@options[key]
end