ar_loader 0.0.6 → 0.0.8

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.
Files changed (53) hide show
  1. data/LICENSE +9 -9
  2. data/README.markdown +268 -221
  3. data/Rakefile +76 -76
  4. data/lib/VERSION +1 -1
  5. data/lib/ar_loader.rb +87 -66
  6. data/lib/ar_loader/exceptions.rb +2 -0
  7. data/lib/{engine → ar_loader}/file_definitions.rb +353 -353
  8. data/lib/{engine → ar_loader}/mapping_file_definitions.rb +87 -87
  9. data/lib/ar_loader/method_detail.rb +257 -0
  10. data/lib/ar_loader/method_mapper.rb +213 -0
  11. data/lib/helpers/jruby/jexcel_file.rb +187 -0
  12. data/lib/{engine → helpers/jruby}/word.rb +79 -70
  13. data/lib/helpers/spree_helper.rb +85 -0
  14. data/lib/loaders/csv_loader.rb +87 -0
  15. data/lib/loaders/excel_loader.rb +132 -0
  16. data/lib/loaders/loader_base.rb +205 -73
  17. data/lib/loaders/spree/image_loader.rb +45 -41
  18. data/lib/loaders/spree/product_loader.rb +140 -91
  19. data/lib/to_b.rb +24 -24
  20. data/spec/csv_loader_spec.rb +27 -0
  21. data/spec/database.yml +19 -6
  22. data/spec/db/migrate/20110803201325_create_test_bed.rb +78 -0
  23. data/spec/excel_loader_spec.rb +113 -98
  24. data/spec/fixtures/BadAssociationName.xls +0 -0
  25. data/spec/fixtures/DemoNegativeTesting.xls +0 -0
  26. data/spec/fixtures/DemoTestModelAssoc.xls +0 -0
  27. data/spec/fixtures/ProjectsMultiCategories.xls +0 -0
  28. data/spec/fixtures/SimpleProjects.xls +0 -0
  29. data/spec/fixtures/SpreeProducts.xls +0 -0
  30. data/spec/fixtures/SpreeZoneExample.csv +5 -0
  31. data/spec/fixtures/SpreeZoneExample.xls +0 -0
  32. data/spec/loader_spec.rb +116 -0
  33. data/spec/logs/test.log +5000 -0
  34. data/spec/method_mapper_spec.rb +222 -0
  35. data/spec/models.rb +55 -0
  36. data/spec/spec_helper.rb +85 -18
  37. data/spec/spree_loader_spec.rb +223 -157
  38. data/tasks/config/seed_fu_product_template.erb +15 -15
  39. data/tasks/config/tidy_config.txt +12 -12
  40. data/tasks/db_tasks.rake +64 -64
  41. data/tasks/excel_loader.rake +63 -113
  42. data/tasks/file_tasks.rake +36 -37
  43. data/tasks/loader.rake +45 -0
  44. data/tasks/spree/image_load.rake +108 -107
  45. data/tasks/spree/product_loader.rake +49 -107
  46. data/tasks/word_to_seedfu.rake +166 -166
  47. metadata +66 -61
  48. data/lib/engine/jruby/jexcel_file.rb +0 -182
  49. data/lib/engine/jruby/method_mapper_excel.rb +0 -44
  50. data/lib/engine/method_detail.rb +0 -140
  51. data/lib/engine/method_mapper.rb +0 -157
  52. data/lib/engine/method_mapper_csv.rb +0 -28
  53. data/spec/db/migrate/20110803201325_create_testbed.rb +0 -25
@@ -1,108 +1,109 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Feb 2011
4
- # License:: MIT. Free, Open Source.
5
- #
6
- # Usage from rake : rake image_load input=path_to_images
7
- #
8
- # => rake image_load input=vendor\extensions\autotelik\fixtures\
9
- # => rake image_load input="C:\images\photos large' dummy=true
10
- # => rake image_load input="C:\images\taxon_icons" skip_if_no_assoc=true klass=Taxon
11
-
12
- namespace :autotelik do
13
-
14
- namespace :spree do
15
-
16
- desc "Populate the DB with images.\nDefault location db/image_seeds, or specify :input=<path> or dir under db/image_seeds with :folder"
17
- # :dummy => dummy run without actual saving to DB
18
- task :image_load, :input, :folder, :dummy, :sku, :skip_if_no_assoc, :skip_if_loaded, :model, :needs => :environment do |t, args|
19
-
20
- require 'image_loader'
21
-
22
- raise "USAGE: Please specify one of :input or :folder" if(args[:input] && args[:folder])
23
- puts "SKU not specified " if(args[:input] && args[:folder])
24
-
25
- if args[:input]
26
- @image_cache = args[:input]
27
- else
28
- @image_cache = File.join(Rails.root, "db", "image_seeds")
29
- @image_cache = File.join(@image_cache, args[:folder]) if(args[:folder])
30
- end
31
-
32
- attachment_klazz = Product
33
-
34
- begin
35
- attachment_klazz = Kernel.const_get(args[:model]) if(args[:model])
36
- rescue NameError
37
- attachment_klazz = Product
38
- end
39
-
40
- image_loader = ImageLoader.new
41
-
42
- if(File.exists? @image_cache )
43
- puts "Loading images from #{@image_cache}"
44
-
45
- missing_records = []
46
- Dir.glob("#{@image_cache}/*.{jpg,png,gif}") do |image_name|
47
-
48
- puts "Processing #{image_name} : #{File.exists?(image_name)}"
49
- base_name = File.basename(image_name, '.*')
50
-
51
- record = nil
52
- if(attachment_klazz == Product && args[:sku])
53
- sku = base_name.slice!(/\w+/)
54
- sku.strip!
55
- base_name.strip!
56
-
57
- puts "Looking fo SKU #{sku}"
58
- record = Variant.find_by_sku(sku)
59
- if record
60
- record = record.product # SKU stored on Variant but we want it's master Product
61
- else
62
- puts "Looking for NAME [#{base_name}]"
63
- record = attachment_klazz.find_by_name(base_name)
64
- end
65
- else
66
- puts "Looking for #{attachment_klazz.name} with NAME [#{base_name}]"
67
- record = attachment_klazz.find_by_name(base_name)
68
- end
69
-
70
- if(record)
71
- puts "Found record for attachment : #{record.inspect}"
72
- exists = record.images.detect {|i| puts "COMPARE #{i.attachment_file_name} => #{image_name}"; i.attachment_file_name == image_name }
73
- puts "Found existing attachments [#{exists}]" unless(exists.nil?)
74
- if(args[:skip_if_loaded] && !exists.nil?)
75
- puts "Skipping - Image #{image_name} already loaded for #{attachment_klazz}"
76
- next
77
- end
78
- else
79
- missing_records << image_name
80
- end
81
-
82
- # Now do actual upload to DB unless we are doing a dummy run,
83
- # or the Image must have an associated record
84
- unless(args[:dummy] == 'true' || (args[:skip_if_no_assoc] && record.nil?))
85
- image_loader.reset()
86
- puts "Process Image"
87
- image_loader.process( image_name, record )
88
- end
89
-
90
- end
91
-
92
- unless missing_records.empty?
93
- FileUtils.mkdir_p('MissingRecords') unless File.directory?('MissingRecords')
94
-
95
- puts '\nMISSING Records Report>>'
96
- missing_records.each do |i|
97
- puts "Copy #{i} to MissingRecords folder"
98
- FileUtils.cp( i, 'MissingRecords') unless(args[:dummy] == 'true')
99
- end
100
- end
101
-
102
- else
103
- puts "ERROR: Supplied Path #{@image_cache} not accesible"
104
- exit(-1)
105
- end
106
- end
107
- end
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Feb 2011
4
+ # License:: MIT
5
+ #
6
+ # Usage::
7
+ #
8
+ # => rake ar_loader:spree:images input=vendor/extensions/site/fixtures/images
9
+ # => rake ar_loader:spree:images input=C:\images\photos large dummy=true
10
+ #
11
+ # => rake ar_loader:spree:images input=C:\images\taxon_icons skip_if_no_assoc=true klass=Taxon
12
+ #
13
+ namespace :ar_loader do
14
+
15
+ namespace :spree do
16
+
17
+ desc "Populate the DB with images.\nDefault location db/image_seeds, or specify :input=<path> or dir under db/image_seeds with :folder"
18
+ # :dummy => dummy run without actual saving to DB
19
+ task :images, :input, :folder, :dummy, :sku, :skip_if_no_assoc, :skip_if_loaded, :model, :needs => :environment do |t, args|
20
+
21
+ require 'image_loader'
22
+
23
+ raise "USAGE: Please specify one of :input or :folder" if(args[:input] && args[:folder])
24
+ puts "SKU not specified " if(args[:input] && args[:folder])
25
+
26
+ if args[:input]
27
+ @image_cache = args[:input]
28
+ else
29
+ @image_cache = File.join(Rails.root, "db", "image_seeds")
30
+ @image_cache = File.join(@image_cache, args[:folder]) if(args[:folder])
31
+ end
32
+
33
+ attachment_klazz = Product
34
+
35
+ begin
36
+ attachment_klazz = Kernel.const_get(args[:model]) if(args[:model])
37
+ rescue NameError
38
+ attachment_klazz = Product
39
+ end
40
+
41
+ image_loader = ImageLoader.new
42
+
43
+ if(File.exists? @image_cache )
44
+ puts "Loading images from #{@image_cache}"
45
+
46
+ missing_records = []
47
+ Dir.glob("#{@image_cache}/*.{jpg,png,gif}") do |image_name|
48
+
49
+ puts "Processing #{image_name} : #{File.exists?(image_name)}"
50
+ base_name = File.basename(image_name, '.*')
51
+
52
+ record = nil
53
+ if(attachment_klazz == Product && args[:sku])
54
+ sku = base_name.slice!(/\w+/)
55
+ sku.strip!
56
+ base_name.strip!
57
+
58
+ puts "Looking fo SKU #{sku}"
59
+ record = Variant.find_by_sku(sku)
60
+ if record
61
+ record = record.product # SKU stored on Variant but we want it's master Product
62
+ else
63
+ puts "Looking for NAME [#{base_name}]"
64
+ record = attachment_klazz.find_by_name(base_name)
65
+ end
66
+ else
67
+ puts "Looking for #{attachment_klazz.name} with NAME [#{base_name}]"
68
+ record = attachment_klazz.find_by_name(base_name)
69
+ end
70
+
71
+ if(record)
72
+ puts "Found record for attachment : #{record.inspect}"
73
+ exists = record.images.detect {|i| puts "COMPARE #{i.attachment_file_name} => #{image_name}"; i.attachment_file_name == image_name }
74
+ puts "Found existing attachments [#{exists}]" unless(exists.nil?)
75
+ if(args[:skip_if_loaded] && !exists.nil?)
76
+ puts "Skipping - Image #{image_name} already loaded for #{attachment_klazz}"
77
+ next
78
+ end
79
+ else
80
+ missing_records << image_name
81
+ end
82
+
83
+ # Now do actual upload to DB unless we are doing a dummy run,
84
+ # or the Image must have an associated record
85
+ unless(args[:dummy] == 'true' || (args[:skip_if_no_assoc] && record.nil?))
86
+ image_loader.reset()
87
+ puts "Process Image"
88
+ image_loader.process( image_name, record )
89
+ end
90
+
91
+ end
92
+
93
+ unless missing_records.empty?
94
+ FileUtils.mkdir_p('MissingRecords') unless File.directory?('MissingRecords')
95
+
96
+ puts '\nMISSING Records Report>>'
97
+ missing_records.each do |i|
98
+ puts "Copy #{i} to MissingRecords folder"
99
+ FileUtils.cp( i, 'MissingRecords') unless(args[:dummy] == 'true')
100
+ end
101
+ end
102
+
103
+ else
104
+ puts "ERROR: Supplied Path #{@image_cache} not accesible"
105
+ exit(-1)
106
+ end
107
+ end
108
+ end
108
109
  end
@@ -1,108 +1,50 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Feb 2011
4
- # License:: MIT. Free, Open Source.
5
- #
6
- # REQUIRES: JRuby access to Java
7
- #
8
- # Usage from rake : jruby -S rake excel_loader input=<file.xls>
9
- #
10
- # e.g. => jruby -S rake autotelik:product_load input=vendor\extensions\autotelik\fixtures\ExampleInfoWeb.xls
11
- # => jruby -S rake autotelik:product_load input=C:\MyProducts.xls verbose=true
12
- #
13
- namespace :autotelik do
14
-
15
- desc "Populate Spree db with Product/Varient data from .xls (Excel) file"
16
- task :product_load, :input, :verbose, :sku_prefix, :needs => :environment do |t, args|
17
-
18
- raise "USAGE: jruby -S rake product_load input=excel_file.xls" unless args[:input]
19
- raise "ERROR: Could not find file #{args[:input]}" unless File.exists?(args[:input])
20
-
21
- require 'product_loader'
22
- require 'method_mapper_excel'
23
-
24
- @method_mapper = MethodMapperExcel.new(args[:input], Product)
25
-
26
- @excel = @method_mapper.excel
27
-
28
- if(args[:verbose])
29
- puts "Loading from Excel file: #{args[:input]}"
30
- puts "Processing #{@excel.num_rows} rows"
31
- end
32
-
33
- # REQUIRED 'set' methods on Product i.e will not validate/save without these
34
- required_methods = ['sku', 'name', 'price']
35
-
36
- @method_mapper.check_mandatory( required_methods )
37
-
38
- # COLUMNS WITH DEFAULTS - TODO create YAML configuration file to drive defaults etc
39
-
40
- MethodDetail.set_default_value('available_on', Time.now.to_s(:db) )
41
- MethodDetail.set_default_value('cost_price', 0.0 )
42
-
43
- MethodDetail.set_prefix('sku', args[:sku_prefix] ) if args[:sku_prefix]
44
-
45
- # Process spreadsheet and create Products
46
- method_names = @method_mapper.method_names
47
-
48
- sku_index = method_names.index('sku')
49
-
50
- Product.transaction do
51
- @products = []
52
-
53
- (1..@excel.num_rows).collect do |row|
54
-
55
- product_data_row = @excel.sheet.getRow(row)
56
- break if product_data_row.nil?
57
-
58
- # Excel num_rows seems to return all 'visible' rows so,
59
- # we have to manually detect when actual data ends and all the empty rows start
60
- contains_data = required_methods.find { |mthd| ! product_data_row.getCell(method_names.index(mthd)).to_s.empty? }
61
- break unless contains_data
62
-
63
- @assoc_classes = {}
64
-
65
- loader = ProductLoader.new()
66
-
67
- # TODO - Smart sorting of column processing order ....
68
- # Does not currently ensure mandatory columns (for valid?) processed first but Product needs saving
69
- # before associations can be processed so user should ensure SKU, name, price columns are among first columns
70
-
71
- @method_mapper.methods.each_with_index do |method_map, col|
72
- product_data_row.getCell(col).setCellType(JExcelFile::HSSFCell::CELL_TYPE_STRING) if(col == sku_index)
73
- loader.process(method_map, @excel.value(product_data_row, col))
74
- begin
75
- prod = loader.load_object
76
- if( prod.valid? && prod.new_record? )
77
- prod.save
78
- end
79
- rescue => e
80
- puts "ERROR: Product save #{e.inspect}"
81
- raise "Error processing Product"
82
- end
83
- end
84
-
85
- product = loader.load_object
86
-
87
- product.available_on ||= Time.now.to_s(:db)
88
-
89
- # TODO - handle when it's not valid ?
90
- # Process rest and dump out an exception list of Products
91
- #unless(product.valid?)
92
- #end
93
-
94
- puts "SAVING ROW #{row} : #{product.inspect}" if args[:verbose]
95
-
96
- unless(product.save)
97
- puts product.errors.inspect
98
- puts product.errors.full_messages.inspect
99
- raise "Error Saving Product: #{product.sku} :#{product.name}"
100
- else
101
- @products << product
102
- end
103
- end
104
- end # TRANSACTION
105
-
106
- end
107
-
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Feb 2011
4
+ # License:: MIT. Free, Open Source.
5
+ #
6
+ # REQUIRES: JRuby access to Java
7
+ #
8
+ # Usage::
9
+ #
10
+ # e.g. => jruby -S rake ar_loader:spree:products input=vendor/extensions/autotelik/fixtures/SiteSpreadsheetInfo.xls
11
+ # => jruby -S rake ar_loader:spree:products input=C:\MyProducts.xls verbose=true
12
+ #
13
+ require 'ar_loader'
14
+ require 'product_loader'
15
+ require 'csv_loader'
16
+
17
+ namespace :ar_loader do
18
+
19
+ namespace :spree do
20
+
21
+ desc "Populate Spree db with Product/Variant data from .xls (Excel) file"
22
+ task :products, [:input, :verbose, :sku_prefix] => :environment do |t, args|
23
+
24
+ input = ENV['input']
25
+
26
+ raise "USAGE: jruby -S rake ar_loader:spree:products input=excel_file.xls" unless input
27
+ raise "ERROR: Could not find file #{args[:input]}" unless File.exists?(input)
28
+
29
+ require 'product_loader'
30
+
31
+ # COLUMNS WITH DEFAULTS - TODO create YAML configuration file to drive defaults etc
32
+
33
+ ARLoader::MethodDetail.set_default_value('available_on', Time.now.to_s(:db) )
34
+ ARLoader::MethodDetail.set_default_value('cost_price', 0.0 )
35
+
36
+ ARLoader::MethodDetail.set_prefix('sku', args[:sku_prefix] ) if args[:sku_prefix]
37
+
38
+ if(File.extname(input) == '.xls' and Guards::jruby?)
39
+ loader = ARLoader::ProductLoader.new
40
+ else
41
+ loader = ARLoader::CSVLoader.new
42
+ end
43
+
44
+ puts "Loading from file: #{input}"
45
+
46
+ loader.load(input, :mandatory => ['sku', 'name', 'price'] )
47
+ end
48
+ end
49
+
108
50
  end
@@ -1,167 +1,167 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Aug 2010
4
- #
5
- # License:: Free, OpenSource... MIT ?
6
- #
7
- # About:: Rake tasks to read Word documents, containing product descriptions,
8
- # convert to HTML, tidy the HTML and then create seed_fu ready fixtures,
9
- # from a template, with product description supplied by the HTML
10
- #
11
- # Note cleanest HTML is produced by this combination : saving with WdFormatHTML
12
- # not WdFormatFilteredHTML and using the '--word-2000', 'y' option to tidy
13
- # (don't use the '--bare' option)
14
- #
15
- # Not currently available for JRuby due to Win32Ole requirement
16
- #
17
- # Requires local exes available in PATH for :
18
- # Microsoft Word
19
- # HTML Tidy - http://tidy.sourceforge.net (Free)
20
- #
21
- require 'erb'
22
-
23
- namespace :autotelik do
24
-
25
- desc "Convert MS Word to HTML and seed_fu fixtures. help=true for detailed usage."
26
-
27
- task :word2html, :help, :needs => [:environment] do |t, args|
28
- x =<<-EOS
29
-
30
- USAGE::
31
- Convert MS Word docs to HTML and seed_fu fixtures, by default searches for docs
32
- in RAILS_ROOT/doc/copy
33
-
34
- You can change the directory where Word document files are located
35
- with the COPY_PATH environment variable.
36
-
37
- Examples:
38
- # default, to convert all Word files for the current environment
39
- rake autotelik:word2seedfu
40
-
41
- # to load seed files matching orders or customers
42
- rake db:seed SEED=orders,customers
43
-
44
- # to load files from RAILS_ROOT/features/fixtures
45
- rake db:seed FIXTURE_PATH=features/fixtures
46
- EOS
47
-
48
- if(args[:help])
49
- puts x
50
- exit(0)
51
- end
52
-
53
- site_extension_lib = File.join(SiteExtension.root, 'lib')
54
-
55
- require File.join(site_extension_lib, 'word')
56
-
57
- copy_path = ENV["COPY_PATH"] ? ENV["COPY_PATH"] : File.join(RAILS_ROOT, "doc", "copy")
58
- fixtures_path = ENV["FIXTURES_PATH"] ? ENV["FIXTURES_PATH"] : File.join(RAILS_ROOT, "db", "fixtures")
59
-
60
- copy_files = Dir[File.join(copy_path, '*.doc')]
61
-
62
- copy_files.each do |file|
63
-
64
- name = File.basename(file, '.doc')
65
-
66
- puts "\n== Generate raw HTML from #{name}.doc =="
67
-
68
- @word = Word.new(true)
69
-
70
- @word.open( file )
71
-
72
- html_file = File.join(copy_path, "#{name}.ms.html")
73
-
74
- @word.save_as_html( html_file )
75
-
76
- tidy_file = File.join(copy_path, "#{name}.html")
77
-
78
- tidy_config = File.join(site_extension_lib, 'tasks', 'tidy_config.txt')
79
-
80
- puts "tidy cmd line:", "tidy -config #{tidy_config} -clean --show-body-only y --word-2000 y --indent-spaces 2 -output #{tidy_file} #{html_file}"
81
-
82
- result = system("tidy", '-config', "#{tidy_config}", '-clean', '--show-body-only', 'y', '--word-2000', 'y', '--indent-spaces', '2', '-output', "#{tidy_file}", "#{html_file}")
83
-
84
- # TODO maybe report on result, $?
85
-
86
- File.open( tidy_file ) do |f|
87
- puts f.read
88
- end
89
-
90
- @word.quit
91
- end
92
- end
93
-
94
- desc "Convert MS Word to HTML and seed_fu fixtures. help=true for detailed usage."
95
- task :word2seedfu => :environment do
96
- site_extension_lib = File.join(SiteExtension.root, 'lib')
97
-
98
- require File.join(site_extension_lib, 'word')
99
-
100
- sku_id = ENV["INITIAL_SKU_ID"] ? ENV["INITIAL_SKU_ID"] : 0
101
- sku_prefix = ENV["SKU_PREFIX"] ? ENV["SKU_PREFIX"] : File.basename( RAILS_ROOT )
102
-
103
- seedfu_template = File.join(site_extension_lib, 'tasks', 'seed_fu_product_template.erb')
104
-
105
- begin
106
- File.open( seedfu_template ) do |f|
107
- @template = ERB.new(f.read)
108
- end
109
- rescue => e
110
- puts "ERROR: #{e.inspect}"
111
- puts "Cannot open or read template #{seedfu_template}"
112
- raise e
113
- end
114
-
115
- copy_path = ENV["COPY_PATH"] ? ENV["COPY_PATH"] : File.join(RAILS_ROOT, "doc", "copy")
116
- fixtures_path = ENV["FIXTURES_PATH"] ? ENV["FIXTURES_PATH"] : File.join(RAILS_ROOT, "db", "fixtures")
117
-
118
- copy_files = Dir[File.join(copy_path, '*.doc')]
119
-
120
- copy_files.each do |file|
121
-
122
- name = File.basename(file, '.doc')
123
-
124
- puts "\n== Generate raw HTML from #{name}.doc =="
125
-
126
- @word = Word.new(true)
127
-
128
- @word.open( file )
129
-
130
- html_file = File.join(copy_path, "#{name}.ms.html")
131
-
132
- @word.save_as_html( html_file )
133
-
134
- tidy_file = File.join(copy_path, "#{name}.html")
135
-
136
- tidy_config = File.join(site_extension_lib, 'tasks', 'tidy_config.txt')
137
-
138
- puts "tidy cmd line:", "tidy -config #{tidy_config} -clean --show-body-only y --word-2000 y --indent-spaces 2 -output #{tidy_file} #{html_file}"
139
-
140
- result = system("tidy", '-config', "#{tidy_config}", '-clean', '--show-body-only', 'y', '--word-2000', 'y', '--indent-spaces', '2', '-output', "#{tidy_file}", "#{html_file}")
141
-
142
- # TODO maybe report on result, $?
143
-
144
- File.open( tidy_file ) do |f|
145
- @description = f.read
146
- end
147
-
148
- sku_id_str = "%03d" % sku_id
149
-
150
- seed_file = "#{sku_id_str}_#{name.gsub(' ', '_')}.rb"
151
- puts "\n== Generate seed fu file #{seed_file} =="
152
-
153
- @sku = "#{sku_prefix}_#{sku_id_str}"
154
- @name = 'TODO'
155
-
156
- File.open( File.join(fixtures_path, seed_file), 'w' ) do |f|
157
- f.write @template.result(binding)
158
- puts "\nFile created: #{File.join(fixtures_path, seed_file)}"
159
- end
160
-
161
- sku_id += 1
162
-
163
- @word.quit
164
- end
165
-
166
- end
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Aug 2010
4
+ #
5
+ # License:: Free, OpenSource... MIT ?
6
+ #
7
+ # About:: Rake tasks to read Word documents, containing product descriptions,
8
+ # convert to HTML, tidy the HTML and then create seed_fu ready fixtures,
9
+ # from a template, with product description supplied by the HTML
10
+ #
11
+ # Note cleanest HTML is produced by this combination : saving with WdFormatHTML
12
+ # not WdFormatFilteredHTML and using the '--word-2000', 'y' option to tidy
13
+ # (don't use the '--bare' option)
14
+ #
15
+ # Not currently available for JRuby due to Win32Ole requirement
16
+ #
17
+ # Requires local exes available in PATH for :
18
+ # Microsoft Word
19
+ # HTML Tidy - http://tidy.sourceforge.net (Free)
20
+ #
21
+ require 'erb'
22
+
23
+ namespace :ar_loader do
24
+
25
+ desc "Convert MS Word to HTML and seed_fu fixtures. help=true for detailed usage."
26
+
27
+ task :word2html, :help, :needs => [:environment] do |t, args|
28
+ x =<<-EOS
29
+
30
+ USAGE::
31
+ Convert MS Word docs to HTML and seed_fu fixtures, by default searches for docs
32
+ in RAILS_ROOT/doc/copy
33
+
34
+ You can change the directory where Word document files are located
35
+ with the COPY_PATH environment variable.
36
+
37
+ Examples:
38
+ # default, to convert all Word files for the current environment
39
+ rake ar_loader:word2seedfu
40
+
41
+ # to load seed files matching orders or customers
42
+ rake db:seed SEED=orders,customers
43
+
44
+ # to load files from RAILS_ROOT/features/fixtures
45
+ rake db:seed FIXTURE_PATH=features/fixtures
46
+ EOS
47
+
48
+ if(args[:help])
49
+ puts x
50
+ exit(0)
51
+ end
52
+
53
+ site_extension_lib = File.join(SiteExtension.root, 'lib')
54
+
55
+ require File.join(site_extension_lib, 'word')
56
+
57
+ copy_path = ENV["COPY_PATH"] ? ENV["COPY_PATH"] : File.join(RAILS_ROOT, "doc", "copy")
58
+ fixtures_path = ENV["FIXTURES_PATH"] ? ENV["FIXTURES_PATH"] : File.join(RAILS_ROOT, "db", "fixtures")
59
+
60
+ copy_files = Dir[File.join(copy_path, '*.doc')]
61
+
62
+ copy_files.each do |file|
63
+
64
+ name = File.basename(file, '.doc')
65
+
66
+ puts "\n== Generate raw HTML from #{name}.doc =="
67
+
68
+ @word = Word.new(true)
69
+
70
+ @word.open( file )
71
+
72
+ html_file = File.join(copy_path, "#{name}.ms.html")
73
+
74
+ @word.save_as_html( html_file )
75
+
76
+ tidy_file = File.join(copy_path, "#{name}.html")
77
+
78
+ tidy_config = File.join(site_extension_lib, 'tasks', 'tidy_config.txt')
79
+
80
+ puts "tidy cmd line:", "tidy -config #{tidy_config} -clean --show-body-only y --word-2000 y --indent-spaces 2 -output #{tidy_file} #{html_file}"
81
+
82
+ result = system("tidy", '-config', "#{tidy_config}", '-clean', '--show-body-only', 'y', '--word-2000', 'y', '--indent-spaces', '2', '-output', "#{tidy_file}", "#{html_file}")
83
+
84
+ # TODO maybe report on result, $?
85
+
86
+ File.open( tidy_file ) do |f|
87
+ puts f.read
88
+ end
89
+
90
+ @word.quit
91
+ end
92
+ end
93
+
94
+ desc "Convert MS Word to HTML and seed_fu fixtures. help=true for detailed usage."
95
+ task :word2seedfu => :environment do
96
+ site_extension_lib = File.join(SiteExtension.root, 'lib')
97
+
98
+ require File.join(site_extension_lib, 'word')
99
+
100
+ sku_id = ENV["INITIAL_SKU_ID"] ? ENV["INITIAL_SKU_ID"] : 0
101
+ sku_prefix = ENV["SKU_PREFIX"] ? ENV["SKU_PREFIX"] : File.basename( RAILS_ROOT )
102
+
103
+ seedfu_template = File.join(site_extension_lib, 'tasks', 'seed_fu_product_template.erb')
104
+
105
+ begin
106
+ File.open( seedfu_template ) do |f|
107
+ @template = ERB.new(f.read)
108
+ end
109
+ rescue => e
110
+ puts "ERROR: #{e.inspect}"
111
+ puts "Cannot open or read template #{seedfu_template}"
112
+ raise e
113
+ end
114
+
115
+ copy_path = ENV["COPY_PATH"] ? ENV["COPY_PATH"] : File.join(RAILS_ROOT, "doc", "copy")
116
+ fixtures_path = ENV["FIXTURES_PATH"] ? ENV["FIXTURES_PATH"] : File.join(RAILS_ROOT, "db", "fixtures")
117
+
118
+ copy_files = Dir[File.join(copy_path, '*.doc')]
119
+
120
+ copy_files.each do |file|
121
+
122
+ name = File.basename(file, '.doc')
123
+
124
+ puts "\n== Generate raw HTML from #{name}.doc =="
125
+
126
+ @word = Word.new(true)
127
+
128
+ @word.open( file )
129
+
130
+ html_file = File.join(copy_path, "#{name}.ms.html")
131
+
132
+ @word.save_as_html( html_file )
133
+
134
+ tidy_file = File.join(copy_path, "#{name}.html")
135
+
136
+ tidy_config = File.join(site_extension_lib, 'tasks', 'tidy_config.txt')
137
+
138
+ puts "tidy cmd line:", "tidy -config #{tidy_config} -clean --show-body-only y --word-2000 y --indent-spaces 2 -output #{tidy_file} #{html_file}"
139
+
140
+ result = system("tidy", '-config', "#{tidy_config}", '-clean', '--show-body-only', 'y', '--word-2000', 'y', '--indent-spaces', '2', '-output', "#{tidy_file}", "#{html_file}")
141
+
142
+ # TODO maybe report on result, $?
143
+
144
+ File.open( tidy_file ) do |f|
145
+ @description = f.read
146
+ end
147
+
148
+ sku_id_str = "%03d" % sku_id
149
+
150
+ seed_file = "#{sku_id_str}_#{name.gsub(' ', '_')}.rb"
151
+ puts "\n== Generate seed fu file #{seed_file} =="
152
+
153
+ @sku = "#{sku_prefix}_#{sku_id_str}"
154
+ @name = 'TODO'
155
+
156
+ File.open( File.join(fixtures_path, seed_file), 'w' ) do |f|
157
+ f.write @template.result(binding)
158
+ puts "\nFile created: #{File.join(fixtures_path, seed_file)}"
159
+ end
160
+
161
+ sku_id += 1
162
+
163
+ @word.quit
164
+ end
165
+
166
+ end
167
167
  end