aboutsummaryrefslogtreecommitdiffstats
path: root/app/models/import_task.rb
blob: 7dfa2c64413bd0c51a60e4835b4762619cf30232 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require "zip"

class ImportTask
  extend Enumerize
  extend ActiveModel::Naming
  extend ActiveModel::Translation
  include ActiveModel::Validations
  include ActiveModel::Conversion

  # TODO : Move in configuration
  @@root = "#{Rails.root}/tmp/imports"
  cattr_accessor :root

  enumerize :data_format, in: %w( neptune netex gtfs )
  attr_accessor :referential_id, :user_id, :user_name, :data_format, :resources, :name, :no_save

  validates_presence_of :referential_id
  validates_presence_of :resources
  validates_presence_of :user_id
  validates_presence_of :user_name
  validates_presence_of :name

  validate :validate_file_size, :validate_file_content

  def initialize( params = {} )
    params.each {|k,v| send("#{k}=",v)}
  end

  def referential
    Referential.find(referential_id)
  end

  def organisation
    referential.organisation
  end

  def save
    if valid?
      # Save resources
      save_resources

      # Call Iev Server
      begin
        Ievkit.create_job(referential.slug, "importer", data_format, {
                            :file1 => params_io,
                            :file2 => transport_data_io
                          }

                         )

        # Delete resources
        delete_resources
      rescue Exception => exception
        # If iev server has an error must delete resources before
        delete_resources

        raise exception
      end
      true
    else
      false
    end
  end

  def params
    {}.tap do |h|
      h["parameters"] = {}
    end
  end

  def self.data_formats
    self.data_format.values
  end

  def params_io
    file = StringIO.new( params.to_json )
    Faraday::UploadIO.new(file, "application/json", "parameters.json")
  end

  def transport_data_io
    file = File.new(saved_resources_path, "r")
    if file_extname == ".zip"
      Faraday::UploadIO.new(file, "application/zip", original_filename )
    elsif file_extname == ".xml"
      Faraday::UploadIO.new(file, "application/xml", original_filename )
    end
  end

  def save_resources
    FileUtils.mkdir_p root
    FileUtils.cp resources.path, saved_resources_path
  end

  def delete_resources
    FileUtils.rm saved_resources_path if File.exists? saved_resources_path
  end

  def original_filename
    resources.original_filename
  end

  def file_extname
    File.extname(original_filename) if original_filename
  end

  def saved_resources_path
    @saved_resources_path ||= "#{root}/#{Time.now.to_i}#{file_extname}"
  end

  @@maximum_file_size = 80.megabytes
  cattr_accessor :maximum_file_size

  def validate_file_size
    return unless resources.present? and resources.path.present? and File.exists? resources.path

    if File.size(resources.path) > maximum_file_size
      message = I18n.t("activemodel.errors.models.import_task.attributes.resources.maximum_file_size", file_size:   ActionController::Base.helpers.number_to_human_size(File.size(resources.path)), maximum_file_size: ActionController::Base.helpers.number_to_human_size(maximum_file_size))
      errors.add(:resources, message)
    end
  end

  @@valid_mime_types = {
    neptune: %w{application/zip application/xml},
    netex: %w{application/zip},
    gtfs: %w{application/zip  text/plain}
  }
  cattr_accessor :valid_mime_types

  def validate_file_content
    return unless resources.present? and resources.path.present? and File.exists? resources.path

    mime_type = (File.open(resources.path) { |f| MimeMagic.by_magic f }).try :type
    expected_mime_types = valid_mime_types[data_format.to_sym]

    unless expected_mime_types.include? mime_type
      message = I18n.t("activemodel.errors.models.import_task.attributes.resources.invalid_mime_type", mime_type: mime_type)
      errors.add(:resources, message)
    end
  end

end