ar_loader 0.0.4 → 0.0.6
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/LICENSE +9 -9
- data/README.markdown +221 -210
- data/Rakefile +76 -76
- data/lib/VERSION +1 -1
- data/lib/ar_loader.rb +66 -53
- data/lib/engine/file_definitions.rb +353 -353
- data/lib/engine/jruby/jexcel_file.rb +181 -181
- data/lib/engine/jruby/method_mapper_excel.rb +43 -43
- data/lib/engine/mapping_file_definitions.rb +87 -87
- data/lib/engine/method_detail.rb +140 -139
- data/lib/engine/method_mapper.rb +156 -156
- data/lib/engine/method_mapper_csv.rb +27 -27
- data/lib/engine/word.rb +70 -70
- data/lib/loaders/loader_base.rb +73 -60
- data/lib/loaders/spree/image_loader.rb +41 -46
- data/lib/loaders/spree/product_loader.rb +91 -92
- data/lib/to_b.rb +24 -24
- data/spec/database.yml +6 -0
- data/spec/db/migrate/20110803201325_create_testbed.rb +25 -0
- data/spec/excel_loader_spec.rb +98 -137
- data/spec/spec_helper.rb +18 -36
- data/spec/spree_loader_spec.rb +158 -0
- data/tasks/{seed_fu_product_template.erb → config/seed_fu_product_template.erb} +15 -15
- data/tasks/{tidy_config.txt → config/tidy_config.txt} +12 -12
- data/tasks/db_tasks.rake +64 -64
- data/tasks/excel_loader.rake +113 -100
- data/tasks/file_tasks.rake +37 -37
- data/tasks/spree/image_load.rake +107 -102
- data/tasks/spree/product_loader.rake +107 -106
- data/tasks/word_to_seedfu.rake +166 -166
- metadata +61 -47
data/lib/engine/method_detail.rb
CHANGED
@@ -1,139 +1,140 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Aug 2010
|
4
|
-
# License:: MIT
|
5
|
-
#
|
6
|
-
# Details:: This class provides information and access to the individual methods
|
7
|
-
# on an AR model. Populated by, and coupled with MethodMapper,
|
8
|
-
# which does the model interrogation work.
|
9
|
-
# Enables 'loaders' to iterate over the MethodMapper results set,
|
10
|
-
# and assign values to AR object, without knowing anything about that receiving object.
|
11
|
-
#
|
12
|
-
# =>
|
13
|
-
require 'to_b'
|
14
|
-
|
15
|
-
class MethodDetail
|
16
|
-
|
17
|
-
# When looking up an association, try each of these in turn till a match
|
18
|
-
# i.e find_by_name .. find_by_title and so on
|
19
|
-
@@insistent_find_by_list ||= [:id, :name, :title]
|
20
|
-
|
21
|
-
attr_accessor :klass, :name, :assignment, :col_type
|
22
|
-
attr_accessor :has_many, :has_many_class_name, :has_many_class
|
23
|
-
attr_accessor :belongs_to, :belongs_to_class_name, :belongs_to_class
|
24
|
-
|
25
|
-
@@default_values = {}
|
26
|
-
@@prefixes = {}
|
27
|
-
|
28
|
-
|
29
|
-
def initialize(klass, name, assignment, belongs_to, has_many, col_type = nil)
|
30
|
-
@klass, @name, @assignment, @has_many, @belongs_to, @col_type = klass, name, assignment, has_many, belongs_to, col_type
|
31
|
-
|
32
|
-
if(@has_many)
|
33
|
-
begin
|
34
|
-
@has_many_class = Kernel.const_get(@has_many.classify)
|
35
|
-
@has_many_class_name = @has_many.classify
|
36
|
-
rescue
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
if(@belongs_to)
|
41
|
-
begin
|
42
|
-
@belongs_to_class = Kernel.const_get(@belongs_to.classify)
|
43
|
-
@belongs_to_class_name = @belongs_to.classify
|
44
|
-
rescue
|
45
|
-
# TODO - try other forms of the name, set to nil, or bomb out ?
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def assign( record, value )
|
51
|
-
#puts "DEBUG: assign: [#{@name}]"
|
52
|
-
|
53
|
-
data = value
|
54
|
-
|
55
|
-
if(@@default_values[@name])
|
56
|
-
puts "WARNING nil value supplied for [#{@name}] - Using default : [#{@@default_values[@name]}]"
|
57
|
-
data = @@default_values[@name]
|
58
|
-
else
|
59
|
-
puts "WARNING nil value supplied for [#{@name}] - No default"
|
60
|
-
end if(data.nil?)
|
61
|
-
|
62
|
-
data = "#{@@prefixes[@name]}#{data}" if(@@prefixes[@name])
|
63
|
-
|
64
|
-
if( @belongs_to )
|
65
|
-
|
66
|
-
#puts "DEBUG : BELONGS_TO #{@belongs_to} - Lookup #{data} in DB"
|
67
|
-
insistent_belongs_to(record, data)
|
68
|
-
|
69
|
-
elsif( @assignment && @col_type )
|
70
|
-
|
71
|
-
record.send( @assignment, @col_type.type_cast( data ) )
|
72
|
-
|
73
|
-
elsif( @assignment )
|
74
|
-
|
75
|
-
insistent_assignment(record, data)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# Attempt to find the associated object via id, name, title ....
|
80
|
-
def insistent_belongs_to( record, value )
|
81
|
-
|
82
|
-
@@insistent_find_by_list.each do |x|
|
83
|
-
begin
|
84
|
-
item = @belongs_to_class.send( "find_by_#{x}", value)
|
85
|
-
if(item)
|
86
|
-
record.send("#{@belongs_to}=", item)
|
87
|
-
break
|
88
|
-
end
|
89
|
-
rescue => e
|
90
|
-
puts e.inspect
|
91
|
-
if(x == @@insistent_method_list.last)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
@@insistent_method_list ||= [:to_i, :to_f, :to_b]
|
101
|
-
begin
|
102
|
-
record.send(@assignment, value)
|
103
|
-
rescue => e
|
104
|
-
puts e.inspect
|
105
|
-
@@insistent_method_list.each do |f|
|
106
|
-
begin
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Aug 2010
|
4
|
+
# License:: MIT
|
5
|
+
#
|
6
|
+
# Details:: This class provides information and access to the individual methods
|
7
|
+
# on an AR model. Populated by, and coupled with MethodMapper,
|
8
|
+
# which does the model interrogation work.
|
9
|
+
# Enables 'loaders' to iterate over the MethodMapper results set,
|
10
|
+
# and assign values to AR object, without knowing anything about that receiving object.
|
11
|
+
#
|
12
|
+
# =>
|
13
|
+
require 'to_b'
|
14
|
+
|
15
|
+
class MethodDetail
|
16
|
+
|
17
|
+
# When looking up an association, try each of these in turn till a match
|
18
|
+
# i.e find_by_name .. find_by_title and so on
|
19
|
+
@@insistent_find_by_list ||= [:id, :name, :title]
|
20
|
+
|
21
|
+
attr_accessor :klass, :name, :assignment, :col_type
|
22
|
+
attr_accessor :has_many, :has_many_class_name, :has_many_class
|
23
|
+
attr_accessor :belongs_to, :belongs_to_class_name, :belongs_to_class
|
24
|
+
|
25
|
+
@@default_values = {}
|
26
|
+
@@prefixes = {}
|
27
|
+
|
28
|
+
|
29
|
+
def initialize(klass, name, assignment, belongs_to, has_many, col_type = nil)
|
30
|
+
@klass, @name, @assignment, @has_many, @belongs_to, @col_type = klass, name, assignment, has_many, belongs_to, col_type
|
31
|
+
|
32
|
+
if(@has_many)
|
33
|
+
begin
|
34
|
+
@has_many_class = Kernel.const_get(@has_many.classify)
|
35
|
+
@has_many_class_name = @has_many.classify
|
36
|
+
rescue
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if(@belongs_to)
|
41
|
+
begin
|
42
|
+
@belongs_to_class = Kernel.const_get(@belongs_to.classify)
|
43
|
+
@belongs_to_class_name = @belongs_to.classify
|
44
|
+
rescue
|
45
|
+
# TODO - try other forms of the name, set to nil, or bomb out ?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def assign( record, value )
|
51
|
+
#puts "DEBUG: assign: [#{@name}]"
|
52
|
+
|
53
|
+
data = value
|
54
|
+
|
55
|
+
if(@@default_values[@name])
|
56
|
+
puts "WARNING nil value supplied for [#{@name}] - Using default : [#{@@default_values[@name]}]"
|
57
|
+
data = @@default_values[@name]
|
58
|
+
else
|
59
|
+
puts "WARNING nil value supplied for [#{@name}] - No default"
|
60
|
+
end if(data.nil?)
|
61
|
+
|
62
|
+
data = "#{@@prefixes[@name]}#{data}" if(@@prefixes[@name])
|
63
|
+
|
64
|
+
if( @belongs_to )
|
65
|
+
|
66
|
+
#puts "DEBUG : BELONGS_TO #{@belongs_to} - Lookup #{data} in DB"
|
67
|
+
insistent_belongs_to(record, data)
|
68
|
+
|
69
|
+
elsif( @assignment && @col_type )
|
70
|
+
puts "DEBUG : COl TYPE defined for #{@name} : #{@assignment} => #{data} #{@col_type.inspect}"
|
71
|
+
record.send( @assignment, @col_type.type_cast( data ) )
|
72
|
+
|
73
|
+
elsif( @assignment )
|
74
|
+
puts "DEBUG : No COL TYPE found for #{@name} : #{@assignment} => #{data}"
|
75
|
+
insistent_assignment(record, data)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Attempt to find the associated object via id, name, title ....
|
80
|
+
def insistent_belongs_to( record, value )
|
81
|
+
|
82
|
+
@@insistent_find_by_list.each do |x|
|
83
|
+
begin
|
84
|
+
item = @belongs_to_class.send( "find_by_#{x}", value)
|
85
|
+
if(item)
|
86
|
+
record.send("#{@belongs_to}=", item)
|
87
|
+
break
|
88
|
+
end
|
89
|
+
rescue => e
|
90
|
+
puts "ERROR: #{e.inspect}"
|
91
|
+
if(x == @@insistent_method_list.last)
|
92
|
+
raise "I'm sorry I have failed to assign [#{value}] to #{@assignment}" unless value.nil?
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def insistent_assignment( record, value )
|
99
|
+
puts "DEBUG: RECORD CLASS #{record.class}"
|
100
|
+
@@insistent_method_list ||= [:to_s, :to_i, :to_f, :to_b]
|
101
|
+
begin
|
102
|
+
record.send(@assignment, value)
|
103
|
+
rescue => e
|
104
|
+
puts e.inspect
|
105
|
+
@@insistent_method_list.each do |f|
|
106
|
+
begin
|
107
|
+
|
108
|
+
record.send(@assignment, value.send( f) )
|
109
|
+
break
|
110
|
+
rescue => e
|
111
|
+
#puts "DEBUG: insistent_assignment: #{e.inspect}"
|
112
|
+
if f == @@insistent_method_list.last
|
113
|
+
puts "I'm sorry I have failed to assign [#{value}] to #{@assignment}"
|
114
|
+
raise "I'm sorry I have failed to assign [#{value}] to #{@assignment}" unless value.nil?
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.set_default_value( name, value )
|
122
|
+
@@default_values[name] = value
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.default_value(name)
|
126
|
+
@@default_values[name]
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.set_prefix( name, value )
|
130
|
+
@@prefixes[name] = value
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.default_value(name)
|
134
|
+
@@prefixes[name]
|
135
|
+
end
|
136
|
+
|
137
|
+
def pp
|
138
|
+
"#{@name} => #{@assignment} : #{@has_many}"
|
139
|
+
end
|
140
|
+
end
|
data/lib/engine/method_mapper.rb
CHANGED
@@ -1,157 +1,157 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Aug 2010
|
4
|
-
# License:: MIT
|
5
|
-
#
|
6
|
-
# Details:: A base class that stores details of all possible associations on AR classes and,
|
7
|
-
# given user supplied class and name, attempts to find correct attribute/association.
|
8
|
-
#
|
9
|
-
# Derived classes define where the user supplied list of names originates from.
|
10
|
-
#
|
11
|
-
# Example usage, load from a spreadsheet where the column names are only
|
12
|
-
# an approximation of the actual associations. Given a column heading of
|
13
|
-
# 'Product Properties' on class Product, find_method_detail() would search AR model,
|
14
|
-
# and return details of real has_many association 'product_properties'.
|
15
|
-
#
|
16
|
-
# This real association can then be used to send spreadsheet row data to the AR object.
|
17
|
-
#
|
18
|
-
require 'method_detail'
|
19
|
-
|
20
|
-
class MethodMapper
|
21
|
-
|
22
|
-
attr_accessor :header_row, :headers
|
23
|
-
attr_accessor :methods
|
24
|
-
|
25
|
-
@@has_many = Hash.new
|
26
|
-
@@belongs_to = Hash.new
|
27
|
-
@@assignments = Hash.new
|
28
|
-
@@column_types = Hash.new
|
29
|
-
|
30
|
-
def initialize
|
31
|
-
@methods = []
|
32
|
-
@headers = []
|
33
|
-
end
|
34
|
-
|
35
|
-
# Build complete picture of the methods whose names listed in method_list
|
36
|
-
# Handles method names as defined by a user or in file headers where names may
|
37
|
-
# not be exactly as required e.g handles capitalisation, white space, _ etc
|
38
|
-
|
39
|
-
def find_method_details( klass, method_list )
|
40
|
-
@methods = method_list.collect { |x| MethodMapper::find_method_detail( klass, x ) }
|
41
|
-
end
|
42
|
-
|
43
|
-
def method_names()
|
44
|
-
@methods.collect( &:name )
|
45
|
-
end
|
46
|
-
|
47
|
-
def check_mandatory( mandatory_list )
|
48
|
-
method_list = method_names()
|
49
|
-
|
50
|
-
mandatory_list.each { |x| raise "Mandatory column missing - need a '#{x}' column" unless(method_list.index(x)) }
|
51
|
-
end
|
52
|
-
|
53
|
-
# Create picture of the operators for assignment available on an AR model,
|
54
|
-
# including via associations (which provide both << and = )
|
55
|
-
#
|
56
|
-
def self.find_operators(klass, options = {} )
|
57
|
-
|
58
|
-
if( options[:reload] || @@has_many[klass].nil? )
|
59
|
-
@@has_many[klass] = klass.reflect_on_all_associations(:has_many).map { |i| i.name.to_s }
|
60
|
-
klass.reflect_on_all_associations(:has_and_belongs_to_many).inject(@@has_many[klass]) { |x,i| x << i.name.to_s }
|
61
|
-
end
|
62
|
-
|
63
|
-
# puts "DEBUG: Has Many Associations:", @@has_many[klass].inspect
|
64
|
-
|
65
|
-
if( options[:reload] || @@belongs_to[klass].nil? )
|
66
|
-
@@belongs_to[klass] = klass.reflect_on_all_associations(:belongs_to).map { |i| i.name.to_s }
|
67
|
-
end
|
68
|
-
|
69
|
-
# puts "DEBUG: Belongs To Associations:", @@belongs_to[klass].inspect
|
70
|
-
|
71
|
-
if( options[:reload] || @@assignments[klass].nil? )
|
72
|
-
@@assignments[klass] = (klass.column_names + klass.instance_methods.grep(/=/).map{|i| i.gsub(/=/, '')})
|
73
|
-
@@assignments[klass] = @@assignments[klass] - @@has_many[klass] if(@@has_many[klass])
|
74
|
-
@@assignments[klass] = @@assignments[klass] - @@belongs_to[klass] if(@@belongs_to[klass])
|
75
|
-
|
76
|
-
@@assignments[klass].uniq!
|
77
|
-
|
78
|
-
@@assignments[klass].each do |assign|
|
79
|
-
found = klass.columns.find{ |col| col.name == assign }
|
80
|
-
@@column_types[column_key(klass, assign)] = found if found
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
# Find the proper format of name, appropriate call + column type for a given name.
|
86
|
-
# e.g Given users entry in spread sheet check for pluralization, missing underscores etc
|
87
|
-
#
|
88
|
-
# If not nil returned method can be used directly in for example klass.new.send( call, .... )
|
89
|
-
#
|
90
|
-
def self.find_method_detail( klass, name )
|
91
|
-
true_name, assign, belongs_to, has_many = nil, nil, nil, nil
|
92
|
-
|
93
|
-
# TODO - check out regexp to do this work better plus Inflections ??
|
94
|
-
[
|
95
|
-
name,
|
96
|
-
name.gsub(' ', '_'),
|
97
|
-
name.gsub(' ', ''),
|
98
|
-
name.gsub(' ', '_').downcase,
|
99
|
-
name.gsub(' ', '').downcase,
|
100
|
-
name.gsub(' ', '_').underscore
|
101
|
-
|
102
|
-
].each do |n|
|
103
|
-
has_many = (@@has_many[klass] && @@has_many[klass].include?(n)) ? n : nil
|
104
|
-
belongs_to = (@@belongs_to[klass] && @@belongs_to[klass].include?(n)) ? n : nil
|
105
|
-
assign = (@@assignments[klass] && @@assignments[klass].include?(n))? n + '=' : nil
|
106
|
-
|
107
|
-
if(assign || has_many || belongs_to)
|
108
|
-
true_name = n
|
109
|
-
break
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
return MethodDetail.new(klass, true_name, assign, belongs_to, has_many, @@column_types[column_key(klass, true_name)])
|
114
|
-
end
|
115
|
-
|
116
|
-
def self.clear
|
117
|
-
@@has_many.clear
|
118
|
-
@@assignments.clear
|
119
|
-
@@column_types.clear
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.column_key(klass, column)
|
123
|
-
"#{klass.name}:#{column}"
|
124
|
-
end
|
125
|
-
|
126
|
-
def self.has_many
|
127
|
-
@@has_many
|
128
|
-
end
|
129
|
-
def self.assignments
|
130
|
-
@@assignments
|
131
|
-
end
|
132
|
-
def self.column_types
|
133
|
-
@@column_types
|
134
|
-
end
|
135
|
-
|
136
|
-
def self.has_many_for(klass)
|
137
|
-
@@has_many[klass]
|
138
|
-
end
|
139
|
-
def self.assignments_for(klass)
|
140
|
-
@@assignments[klass]
|
141
|
-
end
|
142
|
-
|
143
|
-
def self.column_type_for(klass, column)
|
144
|
-
@@column_types[column_key(klass, column)]
|
145
|
-
end
|
146
|
-
|
147
|
-
|
148
|
-
def find_or_new( klass, condition_hash = {} )
|
149
|
-
@records[klass] = klass.find(:all, :conditions => condition_hash)
|
150
|
-
if @records[klass].any?
|
151
|
-
return @records[klass].first
|
152
|
-
else
|
153
|
-
return klass.new
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Aug 2010
|
4
|
+
# License:: MIT
|
5
|
+
#
|
6
|
+
# Details:: A base class that stores details of all possible associations on AR classes and,
|
7
|
+
# given user supplied class and name, attempts to find correct attribute/association.
|
8
|
+
#
|
9
|
+
# Derived classes define where the user supplied list of names originates from.
|
10
|
+
#
|
11
|
+
# Example usage, load from a spreadsheet where the column names are only
|
12
|
+
# an approximation of the actual associations. Given a column heading of
|
13
|
+
# 'Product Properties' on class Product, find_method_detail() would search AR model,
|
14
|
+
# and return details of real has_many association 'product_properties'.
|
15
|
+
#
|
16
|
+
# This real association can then be used to send spreadsheet row data to the AR object.
|
17
|
+
#
|
18
|
+
require 'method_detail'
|
19
|
+
|
20
|
+
class MethodMapper
|
21
|
+
|
22
|
+
attr_accessor :header_row, :headers
|
23
|
+
attr_accessor :methods
|
24
|
+
|
25
|
+
@@has_many = Hash.new
|
26
|
+
@@belongs_to = Hash.new
|
27
|
+
@@assignments = Hash.new
|
28
|
+
@@column_types = Hash.new
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@methods = []
|
32
|
+
@headers = []
|
33
|
+
end
|
34
|
+
|
35
|
+
# Build complete picture of the methods whose names listed in method_list
|
36
|
+
# Handles method names as defined by a user or in file headers where names may
|
37
|
+
# not be exactly as required e.g handles capitalisation, white space, _ etc
|
38
|
+
|
39
|
+
def find_method_details( klass, method_list )
|
40
|
+
@methods = method_list.collect { |x| MethodMapper::find_method_detail( klass, x ) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_names()
|
44
|
+
@methods.collect( &:name )
|
45
|
+
end
|
46
|
+
|
47
|
+
def check_mandatory( mandatory_list )
|
48
|
+
method_list = method_names()
|
49
|
+
|
50
|
+
mandatory_list.each { |x| raise "Mandatory column missing - need a '#{x}' column" unless(method_list.index(x)) }
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create picture of the operators for assignment available on an AR model,
|
54
|
+
# including via associations (which provide both << and = )
|
55
|
+
#
|
56
|
+
def self.find_operators(klass, options = {} )
|
57
|
+
|
58
|
+
if( options[:reload] || @@has_many[klass].nil? )
|
59
|
+
@@has_many[klass] = klass.reflect_on_all_associations(:has_many).map { |i| i.name.to_s }
|
60
|
+
klass.reflect_on_all_associations(:has_and_belongs_to_many).inject(@@has_many[klass]) { |x,i| x << i.name.to_s }
|
61
|
+
end
|
62
|
+
|
63
|
+
# puts "DEBUG: Has Many Associations:", @@has_many[klass].inspect
|
64
|
+
|
65
|
+
if( options[:reload] || @@belongs_to[klass].nil? )
|
66
|
+
@@belongs_to[klass] = klass.reflect_on_all_associations(:belongs_to).map { |i| i.name.to_s }
|
67
|
+
end
|
68
|
+
|
69
|
+
# puts "DEBUG: Belongs To Associations:", @@belongs_to[klass].inspect
|
70
|
+
|
71
|
+
if( options[:reload] || @@assignments[klass].nil? )
|
72
|
+
@@assignments[klass] = (klass.column_names + klass.instance_methods.grep(/=/).map{|i| i.gsub(/=/, '')})
|
73
|
+
@@assignments[klass] = @@assignments[klass] - @@has_many[klass] if(@@has_many[klass])
|
74
|
+
@@assignments[klass] = @@assignments[klass] - @@belongs_to[klass] if(@@belongs_to[klass])
|
75
|
+
|
76
|
+
@@assignments[klass].uniq!
|
77
|
+
|
78
|
+
@@assignments[klass].each do |assign|
|
79
|
+
found = klass.columns.find{ |col| col.name == assign }
|
80
|
+
@@column_types[column_key(klass, assign)] = found if found
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Find the proper format of name, appropriate call + column type for a given name.
|
86
|
+
# e.g Given users entry in spread sheet check for pluralization, missing underscores etc
|
87
|
+
#
|
88
|
+
# If not nil returned method can be used directly in for example klass.new.send( call, .... )
|
89
|
+
#
|
90
|
+
def self.find_method_detail( klass, name )
|
91
|
+
true_name, assign, belongs_to, has_many = nil, nil, nil, nil
|
92
|
+
|
93
|
+
# TODO - check out regexp to do this work better plus Inflections ??
|
94
|
+
[
|
95
|
+
name,
|
96
|
+
name.gsub(' ', '_'),
|
97
|
+
name.gsub(' ', ''),
|
98
|
+
name.gsub(' ', '_').downcase,
|
99
|
+
name.gsub(' ', '').downcase,
|
100
|
+
name.gsub(' ', '_').underscore
|
101
|
+
|
102
|
+
].each do |n|
|
103
|
+
has_many = (@@has_many[klass] && @@has_many[klass].include?(n)) ? n : nil
|
104
|
+
belongs_to = (@@belongs_to[klass] && @@belongs_to[klass].include?(n)) ? n : nil
|
105
|
+
assign = (@@assignments[klass] && @@assignments[klass].include?(n))? n + '=' : nil
|
106
|
+
|
107
|
+
if(assign || has_many || belongs_to)
|
108
|
+
true_name = n
|
109
|
+
break
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
return MethodDetail.new(klass, true_name, assign, belongs_to, has_many, @@column_types[column_key(klass, true_name)])
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.clear
|
117
|
+
@@has_many.clear
|
118
|
+
@@assignments.clear
|
119
|
+
@@column_types.clear
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.column_key(klass, column)
|
123
|
+
"#{klass.name}:#{column}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.has_many
|
127
|
+
@@has_many
|
128
|
+
end
|
129
|
+
def self.assignments
|
130
|
+
@@assignments
|
131
|
+
end
|
132
|
+
def self.column_types
|
133
|
+
@@column_types
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.has_many_for(klass)
|
137
|
+
@@has_many[klass]
|
138
|
+
end
|
139
|
+
def self.assignments_for(klass)
|
140
|
+
@@assignments[klass]
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.column_type_for(klass, column)
|
144
|
+
@@column_types[column_key(klass, column)]
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def find_or_new( klass, condition_hash = {} )
|
149
|
+
@records[klass] = klass.find(:all, :conditions => condition_hash)
|
150
|
+
if @records[klass].any?
|
151
|
+
return @records[klass].first
|
152
|
+
else
|
153
|
+
return klass.new
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
157
|
end
|
@@ -1,28 +1,28 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Jan 2011
|
4
|
-
# License:: MIT
|
5
|
-
#
|
6
|
-
# Details:: Extract the headings from a user supplied CSV file, and map heading names
|
7
|
-
# to the attributes and/or assocaiitons of an AR Model defined by supplied klass.
|
8
|
-
#
|
9
|
-
require 'method_mapper'
|
10
|
-
|
11
|
-
class MethodMapperCsv < MethodMapper
|
12
|
-
|
13
|
-
# Read the headers from CSV file and map to ActiveRecord members/associations
|
14
|
-
|
15
|
-
def initialize( file_name, klass, sheet_number = 0 )
|
16
|
-
super
|
17
|
-
|
18
|
-
File.open(file_name) do
|
19
|
-
@headers = @header_row.split(/,/)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Gather list of all possible 'setter' methods on AR class (instance variables and associations)
|
23
|
-
self.find_operators( klass )
|
24
|
-
|
25
|
-
# Convert the list of headers into suitable calls on the Active Record class
|
26
|
-
find_method_details( klass, @headers )
|
27
|
-
end
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Jan 2011
|
4
|
+
# License:: MIT
|
5
|
+
#
|
6
|
+
# Details:: Extract the headings from a user supplied CSV file, and map heading names
|
7
|
+
# to the attributes and/or assocaiitons of an AR Model defined by supplied klass.
|
8
|
+
#
|
9
|
+
require 'method_mapper'
|
10
|
+
|
11
|
+
class MethodMapperCsv < MethodMapper
|
12
|
+
|
13
|
+
# Read the headers from CSV file and map to ActiveRecord members/associations
|
14
|
+
|
15
|
+
def initialize( file_name, klass, sheet_number = 0 )
|
16
|
+
super
|
17
|
+
|
18
|
+
File.open(file_name) do
|
19
|
+
@headers = @header_row.split(/,/)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Gather list of all possible 'setter' methods on AR class (instance variables and associations)
|
23
|
+
self.find_operators( klass )
|
24
|
+
|
25
|
+
# Convert the list of headers into suitable calls on the Active Record class
|
26
|
+
find_method_details( klass, @headers )
|
27
|
+
end
|
28
28
|
end
|