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 +9 -1
- data/VERSION +1 -1
- data/acts_as_importable.gemspec +2 -2
- data/lib/import_export/controller_methods.rb +10 -9
- data/lib/import_export.rb +44 -32
- metadata +4 -4
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
|
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.
|
1
|
+
0.4.0
|
data/acts_as_importable.gemspec
CHANGED
@@ -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.
|
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-
|
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 =
|
32
|
-
context =
|
33
|
-
self.
|
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}
|
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(
|
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 =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
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
|
-
|
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:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 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-
|
18
|
+
date: 2011-01-15 00:00:00 +05:30
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|