Module: ActAsImportable::Base::ClassMethods

Defined in:
lib/act_as_importable/base.rb

Instance Method Summary collapse

Instance Method Details

#add_scope_for_field(scope, field, value) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/act_as_importable/base.rb', line 79

def add_scope_for_field(scope, field, value)
  return scope unless value
  if (association = self.reflect_on_association(field.to_sym))
    field = association.foreign_key
    value = value.id
  end
  scope.where("#{self.table_name}.#{field} = ?", value)
end

#convert_key_paths_to_values!(row) ⇒ Object

TODO: update this to support finding the association value with multiple columns



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

def convert_key_paths_to_values!(row)
  key_path_attributes = row.select { |k,v| k.to_s.include? '.' }
  key_path_attributes.each do |key, value|
    association_name, uid_field = key.to_s.split('.')
    row[association_name.to_sym] = find_association_value_with_attribute(association_name, uid_field => value)
    row.delete(key.to_sym)
  end
end

#filter_columns(row, options = {}) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/act_as_importable/base.rb', line 46

def filter_columns(row, options = {})
  except = Array(options[:except]).map { |i| i.to_s }
  only = Array(options[:only]).map { |i| i.to_s }
  row = row.reject { |key, value| except.include? key.to_s } if except.present?
  row = row.select { |key, value| only.include? key.to_s } if only.present?
  row
end

#find_association_value_with_attribute(name, attribute) ⇒ Object



64
65
66
67
# File 'lib/act_as_importable/base.rb', line 64

def find_association_value_with_attribute(name, attribute)
  association = self.reflect_on_association(name.to_sym)
  association.klass.where(attribute).first
end

#find_by_uids(attributes) ⇒ Object



73
74
75
76
77
# File 'lib/act_as_importable/base.rb', line 73

def find_by_uids(attributes)
  attributes.inject(self.scoped.readonly(false)) { |scope, key_value|
    add_scope_for_field(scope, key_value[0].to_s, key_value[1])
  }.first
end

#find_or_create_by_uids(attributes, &block) ⇒ Object



69
70
71
# File 'lib/act_as_importable/base.rb', line 69

def find_or_create_by_uids(attributes, &block)
  find_by_uids(attributes) || create(attributes, &block)
end

#import_csv_file(file, options = {}) ⇒ Object



10
11
12
# File 'lib/act_as_importable/base.rb', line 10

def import_csv_file(file, options = {})
  import_csv_text(read_file(file, options), options)
end

#import_csv_text(text, options = {}) ⇒ Object



14
15
16
17
18
19
# File 'lib/act_as_importable/base.rb', line 14

def import_csv_text(text, options = {})
  csv = ::CSV.parse(text, :headers => true)
  csv.map do |row|
    import_record(row.to_hash, options)
  end
end

#import_data(data, options = {}) ⇒ Object



21
22
23
24
25
# File 'lib/act_as_importable/base.rb', line 21

def import_data(data, options = {})
  data.map do |row|
    import_record(row, options)
  end
end

#import_record(row, options = {}) ⇒ Object

Creates or updates a model record Existing records are found by the column(s) specified by the :uid option (default ‘id’). If the values for the uid columns are not provided the row will be ignored. If uid is set to nil it will import the row data as a new record.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/act_as_importable/base.rb', line 31

def import_record(row, options = {})
  options.reverse_merge!(@default_import_options)
  row = row.with_indifferent_access
  row.reverse_merge!(options[:default_values]) if options[:default_values]
  convert_key_paths_to_values!(row)
  row = filter_columns(row, options)
  record = find_or_create_by_uids(uid_values(row, options))
  remove_uid_values_from_row(row, options)
  record.update_attributes(row)
  unless record.save
    Rails.logger.error(record.errors.full_messages)
  end
  record
end

#read_file(file, options = {}) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/act_as_importable/base.rb', line 98

def read_file(file, options = {})
  if options[:encoding]
    File.read(file, :encoding => options[:encoding])
  else
    File.read(file)
  end
end

#remove_uid_values_from_row(row, options = {}) ⇒ Object



58
59
60
61
62
# File 'lib/act_as_importable/base.rb', line 58

def remove_uid_values_from_row(row, options = {})
  Array(options[:uid]).each do |field|
    row.delete(field)
  end
end

#uid_values(row, options) ⇒ Object



54
55
56
# File 'lib/act_as_importable/base.rb', line 54

def uid_values(row, options)
  Hash[Array(options[:uid]).map { |k| [k, row[k.to_sym]] }]
end