ar_loader 0.0.6 → 0.0.8

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