acts_as_importable 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -16,7 +16,15 @@ If model name is not specified, it will use the controller name to find the mode
16
16
 
17
17
  acts_as_importable :product, :scoped => :current_store
18
18
 
19
- This will import all material records within the current_store object returned by the controller#current_store method. Product should have a belongs_to association to Store for this feature to work.
19
+ This will import all products within the current_store object returned by the controller#current_store method. Product should have a belongs_to association to Store for this feature to work.
20
+
21
+ ==== Updating existing objects:
22
+
23
+ acts_as_importable :product, :find_existing_by => :name
24
+
25
+ This will update existing products whose name matches with the value of name column in the csv row. However, if :find_by_existing is not specified, no attempt will be made to lookup existing products. e.g. the following will always create new products
26
+
27
+ acts_as_importable :product
20
28
 
21
29
  === Add the following to your Model:
22
30
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{acts_as_importable}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jagdeep Singh"]
12
- s.date = %q{2011-01-13}
12
+ s.date = %q{2011-01-15}
13
13
  s.description = %q{Use this gem to add import/export to .csv functionality to your activerecord models}
14
14
  s.email = %q{jagdeepkh@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -28,16 +28,14 @@ module ImportExport
28
28
 
29
29
  def import
30
30
  @new_objects = []
31
- filename = "#{UPLOADS_PATH}/#{self.controller_name}.csv"
32
- context = {}
33
- self.class.context.each_pair do |key, value|
34
- context[key] = self.send(value)
35
- end
31
+ filename = upload_file_name
32
+ context = self.class.context.clone
33
+ context[:scoped] = self.send(context[:scoped]) if context[:scoped]
36
34
 
37
35
  if File.exists? filename
38
36
  begin
39
37
  @new_objects = self.class.model_class.import(filename, context)
40
- flash[:notice] = "Import Successful - #{@new_objects.length} New #{self.class.model_class.name.underscore.humanize.pluralize}"
38
+ flash[:notice] = "Import Successful - Imported #{@new_objects.length} #{self.class.model_class.name.underscore.humanize.pluralize}"
41
39
  rescue Exception => e
42
40
  logger.error "Error: Unable to process file. #{e}"
43
41
  flash[:error] = "Error: Unable to process file. #{e}"
@@ -54,8 +52,7 @@ module ImportExport
54
52
  require 'ftools'
55
53
  if params[:csv_file] && File.extname(params[:csv_file].original_filename) == '.csv'
56
54
  File.makedirs "#{UPLOADS_PATH}"
57
- File.open("#{UPLOADS_PATH}/#{self.controller_name}.csv", "wb") { |f| f.write(params[:csv_file].read)}
58
- flash[:notice] = "Successful import of #{self.controller_name} data file"
55
+ File.open(upload_file_name, "wb") { |f| f.write(params[:csv_file].read)}
59
56
  else
60
57
  flash[:error] = "Error! Invalid file, please select a csv file."
61
58
  end
@@ -64,8 +61,12 @@ module ImportExport
64
61
 
65
62
  private
66
63
 
64
+ def upload_file_name
65
+ @upload_file_name ||= "#{UPLOADS_PATH}/#{self.controller_name}_#{request.session_options[:id]}.csv"
66
+ end
67
+
67
68
  def export_file_name
68
- "#{Time.now.to_formatted_s(:number)}_#{self.controller_name}_export.csv"
69
+ @export_file_name ||= "#{Time.now.to_formatted_s(:number)}_#{self.controller_name}_export.csv"
69
70
  end
70
71
 
71
72
  end # end of module InstanceMethods
data/lib/import_export.rb CHANGED
@@ -13,9 +13,8 @@ module ModelMethods
13
13
  self.export_fields = options[:export_fields]
14
14
  send :include, InstanceMethods
15
15
  end
16
-
17
- def import(filename, context)
18
16
 
17
+ def import(filename, context)
19
18
  collection = []
20
19
  headers, *data = self.read_csv(filename)
21
20
  scope_object = context[:scoped]
@@ -26,40 +25,18 @@ module ModelMethods
26
25
 
27
26
  begin
28
27
  class_or_association = scope_object ? scope_object.send(self.table_name) : self
29
- key_field = self.import_fields.first
30
- key_value = data_row[0]
31
- finder_method = "find_by_#{key_field}"
32
- existing_element = class_or_association.send(finder_method, key_value)
33
- element = existing_element || class_or_association.new
28
+ if key_field = context[:find_existing_by]
29
+ key_value = data_row[index_of(key_field)]
30
+ element = class_or_association.send("find_by_#{key_field}", key_value) || class_or_association.new
31
+ else
32
+ element = class_or_association.new
33
+ end
34
34
 
35
35
  Rails.logger.info "#{element.new_record? ? "Creating new" : "Updating existing"} record from #{data_row.inspect}"
36
36
 
37
37
  self.import_fields.each_with_index do |field_name, field_index|
38
38
  if field_name.include?('.')
39
- method_name = 'assign_' + field_name.split('.')[0]
40
- if element.respond_to?(method_name)
41
- element.send method_name, data_row
42
- elsif element.respond_to?("#{field_name.split('.')[0]}_id")
43
- create_record = field_name.include?('!')
44
- split_field = field_name.gsub(/!/,'').split('.').compact
45
- initial_class = split_field[0].classify.constantize
46
- if initial_class and initial_class.respond_to?("find_by_#{split_field[1]}")
47
- begin
48
- e = initial_class.send("find_by_#{split_field[1]}", data_row[field_index])
49
- rescue
50
- e = nil
51
- end
52
- # try to create a new record if not found in database and if '!' is present
53
- if e.nil? and create_record and !data_row[field_index].blank?
54
- e = initial_class.create!("#{split_field[1]}" => data_row[field_index])
55
- end
56
- if e.kind_of?(ActiveRecord::Base)
57
- element["#{split_field[0]}_id"] = e.id
58
- end
59
- else
60
- e = nil
61
- end
62
- end
39
+ assign_association(element, field_name, field_index, scope_object, data_row)
63
40
  else
64
41
  element.send "#{field_name}=", data_row[field_index]
65
42
  end
@@ -130,10 +107,45 @@ module ModelMethods
130
107
  raise ArgumentError, "File does not exist."
131
108
  end
132
109
  end
110
+
111
+ def index_of(fieldname)
112
+ @import_field_indices ||= {}
113
+ @import_field_indices[fieldname] ||= self.import_fields.index{ |f| f.to_s == fieldname.to_s }
114
+ end
115
+
116
+ protected
117
+
118
+ def assign_association(element, field_name, field_index, scope_object, data_row)
119
+ create_record = field_name.include?('!')
120
+ association_name, association_attribute = field_name.gsub(/!/,'').split('.')
121
+ assign_association_method = "assign_#{association_name}"
122
+ association_fk = "#{association_name}_id"
123
+
124
+ if element.respond_to?(assign_association_method)
125
+ element.send assign_association_method, data_row
126
+ elsif element.respond_to?(association_fk)
127
+ association_class = association_name.classify.constantize
128
+
129
+ if scope_object && scope_object.respond_to?(association_class.table_name)
130
+ association_class = scope_object.send(association_class.table_name)
131
+ end
132
+
133
+ finder_method = "find_by_#{association_attribute}"
134
+ if association_class and association_class.respond_to?(finder_method)
135
+ e = association_class.send(finder_method, data_row[field_index])
136
+ if e.nil? and create_record and !data_row[field_index].blank?
137
+ e = association_class.create!(association_attribute => data_row[field_index])
138
+ end
139
+ element[association_fk] = e.id if e
140
+ end
141
+ end
142
+ end
133
143
  end
134
144
 
135
145
  module InstanceMethods
136
- # any method placed here will apply to instaces, like @hickwall
146
+ def index_of(fieldname)
147
+ self.class.index_of(fieldname)
148
+ end
137
149
  end
138
150
 
139
151
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_importable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jagdeep Singh
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-13 00:00:00 +05:30
18
+ date: 2011-01-15 00:00:00 +05:30
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency