acts_as_importable 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|