Class: ActiveImporter::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/active_importer/base.rb

Constant Summary collapse

EVENTS =

Callbacks

[
  :row_success,
  :row_error,
  :row_processing,
  :row_skipped,
  :row_processed,
  :import_started,
  :import_finished,
  :import_failed,
  :import_aborted,
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, options = {}) ⇒ Base

Returns a new instance of Base.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/active_importer/base.rb', line 168

def initialize(file, options = {})
  @row_errors = []
  @params = options.delete(:params)
  @transactional = options.fetch(:transactional, self.class.transactional?)

  raise "Importer is declared transactional at the class level" if !@transactional && self.class.transactional?

  @book = Roo::Spreadsheet.open(file, options)
  load_sheet
  load_header

  @data_row_indices = ((@header_index+1)..@book.last_row)
  @row_count = @data_row_indices.count
rescue => e
  @book = @header = nil
  @row_count = 0
  @row_index = 1
  fire_event :import_failed, e
  raise
end

Instance Attribute Details

#headerObject (readonly)

Implementation



163
164
165
# File 'lib/active_importer/base.rb', line 163

def header
  @header
end

#modelObject (readonly)

Implementation



163
164
165
# File 'lib/active_importer/base.rb', line 163

def model
  @model
end

#paramsObject (readonly)

Returns the value of attribute params.



166
167
168
# File 'lib/active_importer/base.rb', line 166

def params
  @params
end

#rowObject (readonly)

Implementation



163
164
165
# File 'lib/active_importer/base.rb', line 163

def row
  @row
end

#row_countObject (readonly)

Returns the value of attribute row_count.



164
165
166
# File 'lib/active_importer/base.rb', line 164

def row_count
  @row_count
end

#row_errorsObject (readonly)

Returns the value of attribute row_errors.



165
166
167
# File 'lib/active_importer/base.rb', line 165

def row_errors
  @row_errors
end

#row_indexObject (readonly)

Returns the value of attribute row_index.



164
165
166
# File 'lib/active_importer/base.rb', line 164

def row_index
  @row_index
end

Class Method Details

.column(title, field = nil, options = nil, &block) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/active_importer/base.rb', line 56

def self.column(title, field = nil, options = nil, &block)
  title = title.strip
  if columns[title]
    raise "Duplicate importer column '#{title}'"
  end

  if field.is_a?(Hash)
    raise "Invalid column '#{title}': expected a single set of options" unless options.nil?
    options = field
    field = nil
  else
    options ||= {}
  end

  if field.nil? && block_given?
    raise "Invalid column '#{title}': must have a corresponding attribute, or it shouldn't have a block"
  end

  columns[title] = {
    field_name: field,
    transform: block,
    optional: !!options[:optional],
  }
end

.columnsObject



24
25
26
# File 'lib/active_importer/base.rb', line 24

def self.columns
  @columns ||= {}
end

.event_handlersObject



130
131
132
# File 'lib/active_importer/base.rb', line 130

def self.event_handlers
  @event_handlers ||= EVENTS.inject({}) { |hash, event| hash.merge({event => []}) }
end

.fetch_model(&block) ⇒ Object



40
41
42
# File 'lib/active_importer/base.rb', line 40

def self.fetch_model(&block)
  @fetch_model_block = block
end

.fetch_model_blockObject



44
45
46
# File 'lib/active_importer/base.rb', line 44

def self.fetch_model_block
  @fetch_model_block
end

.fire_event(instance, event, param = nil) ⇒ Object



146
147
148
149
150
# File 'lib/active_importer/base.rb', line 146

def self.fire_event(instance, event, param = nil)
  event_handlers[event].each do |block|
    instance.instance_exec(param, &block)
  end
end

.import(file, options = {}) ⇒ Object



81
82
83
# File 'lib/active_importer/base.rb', line 81

def self.import(file, options = {})
  new(file, options).import
end

.imports(klass) ⇒ Object



20
21
22
# File 'lib/active_importer/base.rb', line 20

def self.imports(klass)
  @model_class = klass
end

.model_classObject



28
29
30
# File 'lib/active_importer/base.rb', line 28

def self.model_class
  @model_class
end

.on(event, &block) ⇒ Object



134
135
136
137
# File 'lib/active_importer/base.rb', line 134

def self.on(event, &block)
  raise "Unknown ActiveImporter event '#{event}'" unless EVENTS.include?(event)
  event_handlers[event] << block
end

.sheet(index) ⇒ Object



36
37
38
# File 'lib/active_importer/base.rb', line 36

def self.sheet(index)
  @sheet_index = index
end

.skip_rows_blockObject



52
53
54
# File 'lib/active_importer/base.rb', line 52

def self.skip_rows_block
  @skip_rows_block
end

.skip_rows_if(&block) ⇒ Object



48
49
50
# File 'lib/active_importer/base.rb', line 48

def self.skip_rows_if(&block)
  @skip_rows_block = block
end

.transactional(flag = true) ⇒ Object

Transactions



89
90
91
92
93
94
# File 'lib/active_importer/base.rb', line 89

def self.transactional(flag = true)
  if flag
    raise "Model class does not support transactions" unless @model_class.respond_to?(:transaction)
  end
  @transactional = !!flag
end

.transactional?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/active_importer/base.rb', line 96

def self.transactional?
  @transactional || false
end

Instance Method Details

#abort!(message) ⇒ Object



12
13
14
# File 'lib/active_importer/base.rb', line 12

def abort!(message)
  @abort_message = message
end

#aborted?Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/active_importer/base.rb', line 16

def aborted?
  !!@abort_message
end

#fetch_modelObject



193
194
195
196
197
198
199
# File 'lib/active_importer/base.rb', line 193

def fetch_model
  if fetch_model_block
    self.instance_exec(&fetch_model_block)
  else
    model_class.new
  end
end

#fetch_model_blockObject



189
190
191
# File 'lib/active_importer/base.rb', line 189

def fetch_model_block
  self.class.send(:fetch_model_block)
end

#importObject



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/active_importer/base.rb', line 201

def import
  transaction do
    return if @book.nil?
    fire_event :import_started
    @data_row_indices.each do |index|
      @row_index = index
      @row = row_to_hash @book.row(index)
      if skip_row?
        fire_event :row_skipped
        next
      end
      import_row
      if aborted?
        fire_event :import_aborted, @abort_message
        break
      end
    end
  end
rescue => e
  fire_event :import_aborted, e.message
  raise
ensure
  fire_event :import_finished
end

#model_classObject



32
33
34
# File 'lib/active_importer/base.rb', line 32

def model_class
  self.class.model_class
end

#row_error_countObject



236
237
238
# File 'lib/active_importer/base.rb', line 236

def row_error_count
  row_errors.count
end

#row_processed_countObject



226
227
228
229
230
# File 'lib/active_importer/base.rb', line 226

def row_processed_count
  row_index - @header_index
rescue
  0
end

#row_success_countObject



232
233
234
# File 'lib/active_importer/base.rb', line 232

def row_success_count
  row_processed_count - row_errors.count
end

#transactional?Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/active_importer/base.rb', line 100

def transactional?
  @transactional || self.class.transactional?
end