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
@@ -0,0 +1,222 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Aug 2011
4
+ # License:: MIT
5
+ #
6
+ # Details:: Specs for Excel aspect of Active Record Loader
7
+ #
8
+ require File.dirname(__FILE__) + '/spec_helper'
9
+
10
+ describe 'Method Mapping' do
11
+
12
+ before(:all) do
13
+ db_connect( 'test_file' ) # , test_memory, test_mysql
14
+ migrate_up
15
+ @klazz = Project
16
+ @assoc_klazz = Milestone
17
+ end
18
+
19
+ before(:each) do
20
+ MethodMapper.clear
21
+ MethodMapper.find_operators( @klazz )
22
+ MethodMapper.find_operators( @assoc_klazz )
23
+ end
24
+
25
+ it "should populate method map for a given AR model" do
26
+
27
+ MethodMapper.has_many.should_not be_empty
28
+ MethodMapper.has_many[Project].should include('milestones')
29
+
30
+ MethodMapper.assignments.should_not be_empty
31
+ MethodMapper.assignments[Project].should include('id')
32
+ MethodMapper.assignments[Project].should include('value_as_string')
33
+ MethodMapper.assignments[Project].should include('value_as_text')
34
+
35
+ MethodMapper.belongs_to.should_not be_empty
36
+ MethodMapper.belongs_to[Project].should be_empty
37
+
38
+
39
+ MethodMapper.column_types.should be_is_a(Hash)
40
+ MethodMapper.column_types.should_not be_empty
41
+ MethodMapper.column_types[Project].size.should == Project.columns.size
42
+
43
+
44
+ end
45
+
46
+ it "should populate assigment members without the equivalent association names" do
47
+
48
+ # we should remove has-many & belongs_to from basic assignment set as they require a DB lookup
49
+ # or a Model.create call, not a simple assignment
50
+
51
+ MethodMapper.assignments_for(@klazz).should_not include( MethodMapper.belongs_to_for(@klazz) )
52
+ MethodMapper.assignments_for(@klazz).should_not include( MethodMapper.has_many_for(@klazz) )
53
+ end
54
+
55
+
56
+ it "should populate assignment operators for method details for different forms of a column name" do
57
+
58
+ [:value_as_string, 'value_as_string', "VALUE as_STRING", "value as string"].each do |format|
59
+
60
+ method_details = MethodMapper.find_method_detail( @klazz, format )
61
+
62
+ method_details.class.should == MethodDetail
63
+
64
+ method_details.name.should eq( format.to_s )
65
+
66
+ method_details.operator.should == 'value_as_string'
67
+ method_details.operator_for(:assignment).should == 'value_as_string'
68
+
69
+ method_details.operator?('value_as_string').should be_true
70
+ method_details.operator?('blah_as_string').should be_false
71
+
72
+ method_details.operator_for(:belongs_to).should be_nil
73
+ method_details.operator_for(:has_many).should be_nil
74
+ end
75
+ end
76
+
77
+
78
+ # Note : Not all assignments will currently have a column type, for example
79
+ # those that are derived from a delegate_belongs_to
80
+
81
+ it "should populate column types for assignment operators in method details" do
82
+
83
+ [:value_as_string, 'value_as_string', "VALUE as_STRING", "value as string"].each do |format|
84
+
85
+ method_details = MethodMapper.find_method_detail( @klazz, format )
86
+
87
+ method_details.class.should == MethodDetail
88
+
89
+ method_details.col_type.should_not be_nil
90
+ method_details.col_type.name.should == 'value_as_string'
91
+ method_details.col_type.default.should == nil
92
+ method_details.col_type.sql_type.should include 'varchar(255)' # db specific, sqlite
93
+ method_details.col_type.type.should == :string
94
+ end
95
+ end
96
+
97
+ it "should populate required Class for assignment operators based on column type" do
98
+
99
+ [:value_as_string, 'value_as_string', "VALUE as_STRING", "value as string"].each do |format|
100
+
101
+ method_details = MethodMapper.find_method_detail( Project, format )
102
+
103
+ method_details.operator_class_name.should == 'String'
104
+ method_details.operator_class.should be_is_a(Class)
105
+ method_details.operator_class.should == String
106
+ end
107
+
108
+ end
109
+
110
+ it "should populate belongs_to operator for method details for different forms of a column name" do
111
+
112
+ # milestone.project = project.id
113
+ [:project, 'project', "PROJECT", "prOJECt"].each do |format|
114
+
115
+ method_details = MethodMapper.find_method_detail( Milestone, format )
116
+
117
+ method_details.should_not be_nil
118
+
119
+ method_details.operator.should == 'project'
120
+ method_details.operator_for(:belongs_to).should == 'project'
121
+
122
+ method_details.operator_for(:assignment).should be_nil
123
+ method_details.operator_for(:has_many).should be_nil
124
+ end
125
+
126
+ end
127
+
128
+ it "should populate required Class for belongs_to operator method details" do
129
+
130
+ MethodMapper.find_operators( LoaderRelease )
131
+ MethodMapper.find_operators( LongAndComplexTableLinkedToVersion )
132
+
133
+ # release.project = project.id
134
+ [:project, 'project', "PROJECT", "prOJECt"].each do |format|
135
+
136
+ method_details = MethodMapper.find_method_detail( LoaderRelease, format )
137
+
138
+ method_details.operator_class_name.should == 'Project'
139
+ method_details.operator_class.should == Project
140
+ end
141
+
142
+
143
+ #LongAndComplexTableLinkedToVersion.version = version.id
144
+
145
+ [:version, "Version", "verSION"].each do |format|
146
+ method_details = MethodMapper.find_method_detail( LongAndComplexTableLinkedToVersion, format )
147
+
148
+ method_details.operator_type.should == :belongs_to
149
+
150
+ method_details.operator_class_name.should == 'Version'
151
+ method_details.operator_class.should == Version
152
+ end
153
+ end
154
+
155
+ it "should populate required Class for has_one operator method details" do
156
+
157
+ MethodMapper.find_operators( Version )
158
+
159
+ # version.long_and_complex_table_linked_to_version = LongAndComplexTableLinkedToVersion.create()
160
+
161
+ [:long_and_complex_table_linked_to_version, 'LongAndComplexTableLinkedToVersion', "Long And Complex_Table_Linked To Version", "Long_And_Complex_Table_Linked_To_Version"].each do |format|
162
+ method_details = MethodMapper.find_method_detail( Version, format )
163
+
164
+ method_details.should_not be_nil
165
+
166
+ method_details.operator.should == 'long_and_complex_table_linked_to_version'
167
+
168
+ method_details.operator_type.should == :has_one
169
+
170
+ method_details.operator_class_name.should == 'LongAndComplexTableLinkedToVersion'
171
+ method_details.operator_class.should == LongAndComplexTableLinkedToVersion
172
+ end
173
+ end
174
+
175
+
176
+ it "should find has_many operator for method details" do
177
+
178
+ [:milestones, "Mile Stones", 'mileSTONES', 'MileStones'].each do |format|
179
+
180
+ method_details = MethodMapper.find_method_detail( Project, format )
181
+
182
+ method_details.class.should == MethodDetail
183
+
184
+ result = 'milestones'
185
+ method_details.operator.should == result
186
+ method_details.operator_for(:has_many).should == result
187
+
188
+ method_details.operator_for(:belongs_to).should be_nil
189
+ method_details.operator_for(:assignments).should be_nil
190
+ end
191
+
192
+ end
193
+
194
+
195
+ it "should return nil when non existent column name" do
196
+ ["On sale", 'on_sale'].each do |format|
197
+ detail = MethodMapper.find_method_detail( @klazz, format )
198
+
199
+ detail.should be_nil
200
+ end
201
+ end
202
+
203
+
204
+ it "should find a set of methods based on a list of column names" do
205
+
206
+ mapper = MethodMapper.new
207
+
208
+ [:value_as_string, 'value_as_string', "VALUE as_STRING", "value as string"].each do |format|
209
+
210
+ method_details = MethodMapper.find_method_detail( @klazz, format )
211
+
212
+ method_details.class.should == MethodDetail
213
+
214
+ method_details.col_type.should_not be_nil
215
+ method_details.col_type.name.should == 'value_as_string'
216
+ method_details.col_type.default.should == nil
217
+ method_details.col_type.sql_type.should include 'varchar(255)' # db specific, sqlite
218
+ method_details.col_type.type.should == :string
219
+ end
220
+ end
221
+
222
+ end
data/spec/models.rb ADDED
@@ -0,0 +1,55 @@
1
+
2
+ class Project < ActiveRecord::Base
3
+
4
+ has_one :owner
5
+
6
+ has_many :milestones
7
+
8
+ has_many :loader_releases
9
+ has_many :versions, :through => :loader_releases
10
+
11
+
12
+ #has_many :release_versions, :through => :loader_releases, :source => :versions
13
+
14
+ has_and_belongs_to_many :categories
15
+
16
+ end
17
+
18
+ class Owner < ActiveRecord::Base
19
+ belongs_to :project
20
+ end
21
+
22
+ class Milestone < ActiveRecord::Base
23
+ belongs_to :project
24
+ #validate the name, cost
25
+ end
26
+
27
+ # had_and_belongs to join table
28
+ class Category < ActiveRecord::Base
29
+ has_and_belongs_to_many :projects
30
+ end
31
+
32
+
33
+ class Version < ActiveRecord::Base
34
+ has_many :releases
35
+
36
+ has_one :long_and_complex_table_linked_to_version
37
+ end
38
+
39
+ # Join Table with additional columns
40
+ class LoaderRelease < ActiveRecord::Base
41
+
42
+ belongs_to :project
43
+ belongs_to :version
44
+
45
+ #validate the name
46
+ end
47
+
48
+ class Empty < ActiveRecord::Base
49
+ end
50
+
51
+ # Join Table with additional columns
52
+ class LongAndComplexTableLinkedToVersion < ActiveRecord::Base
53
+
54
+ belongs_to :version
55
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,19 +1,86 @@
1
-
2
-
3
- RSpec::Runner.configure do |config|
4
- # config.use_transactional_fixtures = true
5
- # config.use_instantiated_fixtures = false
6
- # config.fixture_path = RAILS_ROOT + '/spec/fixtures'
7
-
8
- # You can declare fixtures for each behaviour like this:
9
- # describe "...." do
10
- # fixtures :table_a, :table_b
11
- #
12
- # Alternatively, if you prefer to declare them only once, you can
13
- # do so here, like so ...
14
- #
15
- # config.global_fixtures = :table_a, :table_b
16
- #
17
- # If you declare global fixtures, be aware that they will be declared
18
- # for all of your examples, even those that don't use them.
1
+ #require 'active_support'
2
+ require 'active_record'
3
+ require 'erb'
4
+
5
+ require File.dirname(__FILE__) + '/../lib/ar_loader'
6
+
7
+
8
+ #.# Copyright:: (c) Autotelik Media Ltd 2011
9
+ # Author :: Tom Statter
10
+ # Date :: Aug 2011
11
+ # License:: MIT
12
+ #
13
+ # Details:: Spec Helper for Active Record Loader
14
+ #
15
+ #
16
+ # We are not setup as a Rails project so need to mimic an active record database setup so
17
+ # we have some AR models top test against. Create an in memory database from scratch.
18
+ #
19
+
20
+ def db_connect( env = 'test_file')
21
+
22
+ require 'active_record'
23
+
24
+ # Some active record stuff seems to rely on the RAILS_ENV being set ?
25
+
26
+ ENV['RAILS_ENV'] = env
27
+
28
+ configuration = {}
29
+
30
+ configuration[:database_configuration] = YAML::load(ERB.new(IO.read( File.dirname(__FILE__) + '/database.yml')).result)
31
+ db = configuration[:database_configuration][ env ]
32
+
33
+ puts "Setting DB Config - #{db.inspect}"
34
+ ActiveRecord::Base.configurations = db
35
+
36
+ #ActiveRecord::Base.logger = Logger.new(STDOUT)
37
+
38
+ puts "Connecting to DB"
39
+ ActiveRecord::Base.establish_connection( db )
40
+
41
+ require 'logger'
42
+ logdir = File.dirname(__FILE__) + '/logs'
43
+ FileUtils.mkdir_p(logdir) unless File.exists?(logdir)
44
+ ActiveRecord::Base.logger = Logger.new(logdir + '/test.log')
45
+
46
+ #puts "Connected to DB - #{ActiveRecord::Base.connection.inspect}"
47
+
48
+ require File.dirname(__FILE__) + '/models' # load our test model definitions
49
+
50
+ # handle migration changes or reset of test DB
51
+ migrate_up
52
+
53
+ end
54
+
55
+ def db_clear
56
+ [Project, Milestone, Category, Version, LoaderRelease].each {|x| x.delete_all}
57
+ end
58
+
59
+ def load_in_memory
60
+ load "#{Rails.root}/db/schema.rb"
61
+ end
62
+
63
+ def migrate_up
64
+ ActiveRecord::Migrator.up( File.dirname(__FILE__) + '/db/migrate')
65
+ end
66
+
67
+
68
+ $fixture_path = File.join(File.dirname(__FILE__), 'fixtures')
69
+
70
+ RSpec.configure do |config|
71
+ # config.use_transactional_fixtures = true
72
+ # config.use_instantiated_fixtures = false
73
+ # config.fixture_path = RAILS_ROOT + '/spec/fixtures'
74
+
75
+ # You can declare fixtures for each behaviour like this:
76
+ # describe "...." do
77
+ # fixtures :table_a, :table_b
78
+ #
79
+ # Alternatively, if you prefer to declare them only once, you can
80
+ # do so here, like so ...
81
+ #
82
+ # config.global_fixtures = :table_a, :table_b
83
+ #
84
+ # If you declare global fixtures, be aware that they will be declared
85
+ # for all of your examples, even those that don't use them.
19
86
  end
@@ -1,158 +1,224 @@
1
- unless defined? SPREE_ROOT
2
- ENV["RAILS_ENV"] = "test"
3
- case
4
- when ENV["SPREE_ENV_FILE"]
5
- require ENV["SPREE_ENV_FILE"]
6
- when File.dirname(__FILE__) =~ %r{vendor/SPREE/vendor/extensions}
7
- require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../../")}/config/environment"
8
- else
9
- require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
10
- end
11
- end
12
- require "#{SPREE_ROOT}/spec/spec_helper"
13
-
14
- if File.directory?(File.dirname(__FILE__) + "/scenarios")
15
- Scenario.load_paths.unshift File.dirname(__FILE__) + "/scenarios"
16
- end
17
- if File.directory?(File.dirname(__FILE__) + "/matchers")
18
- Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
19
- end
20
-
21
- require File.dirname(__FILE__) + '/spec_helper'
22
-
23
- describe 'ExcelLoader' do
24
-
25
- before do
26
- @klazz = Product
27
- MethodMapper.clear
28
- end
29
-
30
- it "should populate operators for a given AR model" do
31
- MethodMapper.find_operators( @klazz )
32
-
33
- MethodMapper.has_many.should_not be_empty
34
- MethodMapper.assignments.should_not be_empty
35
-
36
- hmf = MethodMapper.has_many_for(@klazz)
37
- arf = MethodMapper.assignments_for(@klazz)
38
-
39
- (hmf & arf).should_not be_empty # Associations provide << or =
40
-
41
- hmf.should include('properties')
42
- arf.should include('count_on_hand') # example of a column
43
- arf.should include('cost_price') # example of delegated assignment (available through Variant)
44
-
45
- MethodMapper.column_types.should be_is_a(Hash)
46
- MethodMapper.column_types.should_not be_empty
47
-
48
- MethodMapper.column_type_for(@klazz, 'count_on_hand').should_not be_nil
49
- end
50
-
51
- it "should populate operators respecting unique option" do
52
- MethodMapper.find_operators( @klazz, :unique => true )
53
-
54
- hmf = MethodMapper.has_many_for(@klazz)
55
- arf = MethodMapper.assignments_for(@klazz)
56
-
57
- (hmf & arf).should be_empty
58
- end
59
-
60
- it "should populate assignment method and col type for different forms of a column name" do
61
-
62
- MethodMapper.find_operators( @klazz )
63
-
64
- ["Count On hand", 'count_on_hand', "Count OnHand", "COUNT ONHand"].each do |format|
65
- mmap = MethodMapper.determine_calls( @klazz, format )
66
-
67
- mmap.class.should == MethodDetail
68
-
69
- mmap.assignment.should == 'count_on_hand='
70
- mmap.has_many.should be_nil
71
-
72
- mmap.col_type.should_not be_nil
73
- mmap.col_type.name.should == 'count_on_hand'
74
- mmap.col_type.default.should == 0
75
- mmap.col_type.sql_type.should == 'int(10)'
76
- mmap.col_type.type.should == :integer
77
- end
78
- end
79
-
80
- it "should populate both methods for different forms of an association name" do
81
-
82
- MethodMapper.find_operators( @klazz )
83
- ["product_option_types", "product option types", 'product Option_types', "ProductOptionTypes", "Product_Option_Types"].each do |format|
84
- mmap = MethodMapper.determine_calls( @klazz, format )
85
-
86
- mmap.assignment.should == 'product_option_types='
87
- mmap.has_many.should == 'product_option_types'
88
-
89
- mmap.col_type.should be_nil
90
- end
91
- end
92
-
93
-
94
- it "should not populate anything when non existent column name" do
95
- ["On sale", 'on_sale'].each do |format|
96
- mmap = MethodMapper.determine_calls( @klazz, format )
97
-
98
- mmap.class.should == MethodDetail
99
- mmap.assignment.should be_nil
100
- mmap.has_many.should be_nil
101
- mmap.col_type.should be_nil
102
- end
103
- end
104
-
105
- it "should enable correct assignment and sending of a value to AR model" do
106
-
107
- MethodMapper.find_operators( @klazz )
108
-
109
- mmap = MethodMapper.determine_calls( @klazz, 'count on hand' )
110
- mmap.assignment.should == 'count_on_hand='
111
-
112
- x = @klazz.new
113
-
114
- x.should be_new_record
115
-
116
- x.send( mmap.assignment, 2 )
117
- x.count_on_hand.should == 2
118
- x.on_hand.should == 2 # helper method I know looks at same thing
119
-
120
- mmap = MethodMapper.determine_calls( @klazz, 'SKU' )
121
- mmap.assignment.should == 'sku='
122
- x.send( mmap.assignment, 'TEST_SK 001' )
123
- x.sku.should == 'TEST_SK 001'
124
- end
125
-
126
- it "should enable correct assignment and sending of association to AR model" do
127
-
128
- MethodMapper.find_operators( @klazz )
129
-
130
- mmap = MethodMapper.determine_calls( @klazz, 'taxons' )
131
- mmap.has_many.should == 'taxons'
132
-
133
- x = @klazz.new
134
-
135
- # NEW ASSOCIATION ASSIGNMENT v.,mn
136
- x.send( mmap.has_many ) << Taxon.new
137
- x.taxons.size.should == 1
138
-
139
- x.send( mmap.has_many ) << [Taxon.new, Taxon.new]
140
- x.taxons.size.should == 3
141
-
142
- # EXISTING ASSOCIATIONS
143
- x = Product.find :first
144
-
145
- t = Taxonomy.find_or_create_by_name( 'BlahSpecTest' )
146
-
147
- if x
148
- sz = x.taxons.size
149
- x.send(mmap.has_many) << t.root
150
- x.taxons.size.should == sz + 1
151
- else
152
- puts "WARNING : Test not run could not find any Test Products"
153
- end
154
-
155
- end
156
-
157
-
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ require 'spree_helper'
4
+
5
+ include ARLoader
6
+
7
+ describe 'SpreeLoader' do
8
+
9
+ before(:all) do
10
+ db_connect( 'test_file' ) # , test_memory, test_mysql
11
+ Spree.load
12
+ Spree.migrate_up
13
+
14
+ @klazz = Product
15
+
16
+ # TODO create proper suite of fixtures for Spree testing
17
+ @prop1 = Property.find_or_create_by_name( 'RSpecTestProperty')
18
+ @prop2 = Property.find_or_create_by_name( 'AN Other RSpecTestProperty')
19
+ @prop3 = Property.find_or_create_by_name( 'AN Other RSpecTestProperty')
20
+
21
+ end
22
+
23
+ before do
24
+
25
+ MethodMapper.clear
26
+ MethodMapper.find_operators( @klazz )
27
+
28
+ # TOFIX - weird error
29
+ # NameError:
30
+ # undefined local variable or method `check_price' for #<Variant:0x1031f6658>
31
+ # but that method defined on Variant class in variant.rb
32
+
33
+ #@product = Product.new( :sku => "TRspec001", :name => 'Test RSPEC Product', :price => 99.99 )
34
+ #@product.save
35
+ end
36
+
37
+ it "should populate operators for a Spree Product" do
38
+
39
+ MethodMapper.has_many.should_not be_empty
40
+ MethodMapper.belongs_to.should_not be_empty
41
+ MethodMapper.assignments.should_not be_empty
42
+
43
+
44
+ assign = MethodMapper.assignments_for(@klazz)
45
+
46
+ assign.should include('count_on_hand') # Example of a simple column
47
+ assign.should include('cost_price') # Example of delegated assignment (available through Variant)
48
+
49
+ MethodMapper.assignments[@klazz].should include('cost_price')
50
+
51
+ has_many_ops = MethodMapper.has_many_for(@klazz)
52
+
53
+ has_many_ops.should include('properties') # Product can have many properties
54
+
55
+ MethodMapper.has_many[@klazz].should include('properties')
56
+
57
+ btf = MethodMapper.belongs_to_for(@klazz)
58
+
59
+ btf.should include('tax_category') # Example of a belongs_to assignment
60
+
61
+ MethodMapper.belongs_to[@klazz].should include('tax_category')
62
+
63
+ MethodMapper.column_types[@klazz].size.should == @klazz.columns.size
64
+ end
65
+
66
+
67
+ it "should find method details correctly for different forms of a column name" do
68
+
69
+ ["Count On hand", 'count_on_hand', "Count OnHand", "COUNT ONHand"].each do |format|
70
+
71
+ method_details = MethodMapper.find_method_detail( @klazz, format )
72
+
73
+ method_details.operator.should == 'count_on_hand'
74
+ method_details.operator_for(:assignment).should == 'count_on_hand'
75
+
76
+ method_details.operator_for(:belongs_to).should be_nil
77
+ method_details.operator_for(:has_many).should be_nil
78
+
79
+ method_details.col_type.should_not be_nil
80
+ method_details.col_type.name.should == 'count_on_hand'
81
+ method_details.col_type.default.should == 0
82
+ method_details.col_type.sql_type.should include 'int' # works on mysql and sqlite
83
+ method_details.col_type.type.should == :integer
84
+ end
85
+ end
86
+
87
+ it "should populate method details correctly for has_many forms of association name" do
88
+
89
+ MethodMapper.has_many[@klazz].should include('product_option_types')
90
+
91
+ ["product_option_types", "product option types", 'product Option_types', "ProductOptionTypes", "Product_Option_Types"].each do |format|
92
+ method_detail = MethodMapper.find_method_detail( @klazz, format )
93
+
94
+ method_detail.should_not be_nil
95
+
96
+ method_detail.operator_for(:has_many).should eq('product_option_types')
97
+ method_detail.operator_for(:belongs_to).should be_nil
98
+ method_detail.operator_for(:assignment).should be_nil
99
+ end
100
+ end
101
+
102
+
103
+ it "should enable correct assignment to a column on Product" do
104
+
105
+ method_detail = MethodMapper.find_method_detail( @klazz, 'count on hand' )
106
+ method_detail.operator.should == 'count_on_hand'
107
+
108
+ klazz_object = @klazz.new
109
+
110
+ klazz_object.should be_new_record
111
+
112
+ method_detail.assign( klazz_object, 2 )
113
+ klazz_object.count_on_hand.should == 2
114
+
115
+ method_detail.assign( klazz_object, 5 )
116
+ klazz_object.count_on_hand.should == 5
117
+
118
+ method = MethodMapper.find_method_detail( @klazz, 'SKU' )
119
+ method.operator.should == 'sku'
120
+
121
+ method.assign( klazz_object, 'TEST_SK 001')
122
+ klazz_object.sku.should == 'TEST_SK 001'
123
+
124
+ end
125
+
126
+ it "should enable assignment to has_many association on new object" do
127
+
128
+ method_detail = MethodMapper.find_method_detail( @klazz, 'taxons' )
129
+
130
+ method_detail.operator.should == 'taxons'
131
+
132
+ klazz_object = @klazz.new
133
+
134
+ klazz_object.taxons.size.should == 0
135
+
136
+ # NEW ASSOCIATION ASSIGNMENT
137
+
138
+ # assign via the send operator directly on load object
139
+ klazz_object.send( method_detail.operator ) << Taxon.new
140
+
141
+ klazz_object.taxons.size.should == 1
142
+
143
+ klazz_object.send( method_detail.operator ) << [Taxon.new, Taxon.new]
144
+ klazz_object.taxons.size.should == 3
145
+
146
+ # Use generic assignment on method detail - expect has_many to use << not =
147
+ method_detail.assign( klazz_object, Taxon.new )
148
+ klazz_object.taxons.size.should == 4
149
+
150
+ method_detail.assign( klazz_object, [Taxon.new, Taxon.new])
151
+ klazz_object.taxons.size.should == 6
152
+ end
153
+
154
+ it "should enable assignment to has_many association using existing objects" do
155
+
156
+ MethodMapper.find_operators( @klazz )
157
+
158
+ method_detail = MethodMapper.find_method_detail( @klazz, 'product_properties' )
159
+
160
+ method_detail.operator.should == 'product_properties'
161
+
162
+ klazz_object = @klazz.new
163
+
164
+ ProductProperty.new(:property => @prop1)
165
+
166
+ # NEW ASSOCIATION ASSIGNMENT
167
+ klazz_object.send( method_detail.operator ) << ProductProperty.new
168
+
169
+ klazz_object.product_properties.size.should == 1
170
+
171
+ klazz_object.send( method_detail.operator ) << [ProductProperty.new, ProductProperty.new]
172
+ klazz_object.product_properties.size.should == 3
173
+
174
+ # Use generic assignment on method detail - expect has_many to use << not =
175
+ method_detail.assign( klazz_object, ProductProperty.new(:property => @prop1) )
176
+ klazz_object.product_properties.size.should == 4
177
+
178
+ method_detail.assign( klazz_object, [ProductProperty.new(:property => @prop2), ProductProperty.new(:property => @prop3)])
179
+ klazz_object.product_properties.size.should == 6
180
+
181
+ end
182
+
183
+ it "should process a simple .xls spreadsheet" do
184
+
185
+ Zone.delete_all
186
+
187
+ loader = ExcelLoader.new(Zone)
188
+
189
+ count = Zone.count
190
+ loader.load( $fixture_path + '/SpreeZoneExample.xls')
191
+
192
+ loader.loaded_count.should == (Zone.count - count)
193
+ end
194
+
195
+ it "should process a simple csv file", :focus => false do
196
+
197
+ Zone.delete_all
198
+
199
+ loader = CsvLoader.new(Zone)
200
+
201
+ count = Zone.count
202
+ loader.load( $fixture_path + '/SpreeZoneExample.csv')
203
+
204
+ loader.loaded_count.should == (Zone.count - count)
205
+ end
206
+
207
+ it "should load Products via specific Spree loader", :focus => true do
208
+
209
+ require 'product_loader'
210
+
211
+ Product.delete_all; Variant.delete_all; Taxon.delete_all
212
+
213
+ count = Product.count
214
+
215
+ loader = ARLoader::ProductLoader.new
216
+
217
+ # REQUIRED 'set' methods on Product i.e will not validate/save without these
218
+
219
+ loader.load($fixture_path + '/SpreeProducts.xls', :mandatory => ['sku', 'name', 'price'] )
220
+
221
+ loader.loaded_count.should == (Product.count - count)
222
+ end
223
+
158
224
  end