aboutsummaryrefslogtreecommitdiffstats
path: root/app/models/import.rb
blob: 34736eb90e40765148cafa2dc312adf63c0de13a (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
class Import < ActiveRecord::Base
  belongs_to :referential

  validates_presence_of :referential_id
  validates_presence_of :resources

  validates_inclusion_of :status, :in => %w{ pending completed failed }

  attr_accessor :resources
  attr_accessor :loader

  has_many :log_messages, :class_name => "ImportLogMessage", :order => :position, :dependent => :delete_all

  serialize :options

  def self.option(name)
    name = name.to_s

    define_method(name) do
      self.options and self.options[name]
    end

    define_method("#{name}=") do |prefix|
      (self.options ||= {})[name] = prefix
    end
  end

  def self.format_name(format)
    name_by_format = { "NeptuneImport" => "Neptune",
                       "CsvImport" => "CSV",
                       "GtfsImport" => "GTFS",
                       "NetexImport" => "NeTEx"}
    name_by_format[format]
  end

  def self.types
    # if Rails.env.development? and subclasses.blank?
    #   Dir[File.expand_path("../*_import.rb", __FILE__)].each do |f| 
    #     require f
    #   end
    # end

    unless Rails.env.development?
      subclasses.map(&:to_s)
    else
      # FIXME
      %w{NeptuneImport CsvImport GtfsImport NetexImport}
    end
  end

  def loader
    @loader ||= ::Chouette::Loader.new(referential.slug)
  end

  def with_original_filename
    Dir.mktmpdir do |tmp_dir|
      tmp_link = File.join(tmp_dir, resources.original_filename)
      FileUtils.ln_s resources.path, tmp_link
      yield tmp_link
    end
  end

  before_validation :define_default_attributes, :on => :create
  def define_default_attributes
    self.status ||= "pending"
  end

  before_validation :extract_file_type, :on => :create
  def extract_file_type
    if ! resources.nil? 
      self.file_type = resources.original_filename.rpartition(".").last      
    end
  end

  after_create :delayed_import
  def delayed_import
    save_resources
    delay.import
  end

  @@root = "#{Rails.root}/tmp/imports"
  cattr_accessor :root

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

  after_destroy :destroy_resources
  def destroy_resources
    FileUtils.rm saved_resources if File.exists? saved_resources
  end

  def saved_resources
    "#{root}/#{id}.#{file_type}"
  end

  def name
    "#{self.class.model_name.human} #{id}"
  end

  def import_options
    { :import_id => self.id , :file_format => self.file_type }
  end

  def import
    begin
      log_messages.create :key => :started
      if resources
        with_original_filename do |file|
          # chouette-command checks the file extension (and requires .zip) :(
          loader.import file
        end
      else
        loader.import saved_resources, import_options
      end
      update_attribute :status, "completed"
    rescue => e
      Rails.logger.error "Import #{id} failed : #{e}, #{e.backtrace}"
      update_attribute :status, "failed"
    end
    log_messages.create :key => status
  end

  def self.new(attributes = {}, options = {}, &block)
    if self == Import
      Object.const_get(attributes.delete(:type) || "NeptuneImport").new(attributes, options)
    else
      super
    end
  end

end