rgarner-csv-mapper 0.5.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -41,7 +41,7 @@ Rake::RDocTask.new do |rdoc|
41
41
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
42
42
 
43
43
  rdoc.rdoc_dir = 'rdoc'
44
- rdoc.title = "csv-mapper #{version}"
44
+ rdoc.title = "rgarner-csv-mapper #{version}"
45
45
  rdoc.rdoc_files.include('README*')
46
46
  rdoc.rdoc_files.include('lib/**/*.rb')
47
47
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.7.0
@@ -8,6 +8,10 @@ module CsvMapper
8
8
  def initialize(name, index, map_context)
9
9
  @name, @index, @map_context = name, index, map_context
10
10
  end
11
+
12
+ def to_s
13
+ "#{@index}: #{@name}"
14
+ end
11
15
 
12
16
  # Set the index that this map is targeting.
13
17
  #
@@ -51,5 +55,5 @@ module CsvMapper
51
55
  @transformer.call(csv_row, @index)
52
56
  end
53
57
  end
54
- end
58
+ end
55
59
  end
@@ -17,6 +17,7 @@ module CsvMapper
17
17
  @csv_data = csv_data
18
18
  @before_filters = []
19
19
  @after_filters = []
20
+ @named_columns = false
20
21
  @parser_options = {}
21
22
  @start_at_row = 0
22
23
  @stop_at_row = Infinity
@@ -49,17 +50,14 @@ module CsvMapper
49
50
  #
50
51
  # i.e. read_attributes_from_file('files+' => 'files_plus', 'files-' => 'files_minus)
51
52
  def read_attributes_from_file aliases = {}
52
- attributes = FasterCSV.new(@csv_data, @parser_options).readline
53
- @start_at_row = [ @start_at_row, 1 ].max
54
- @csv_data.rewind
55
53
  unnamed_number = 1
56
- attributes.each_with_index do |name, index|
54
+ iterate_headers do |name, index|
57
55
  if name.nil?
58
56
  name = "_field_#{unnamed_number}"
59
- unnamed_number += 1
57
+ unnamed_number += 1
60
58
  end
61
59
  name.strip!
62
- use_name = aliases[name] || name.gsub(/\s+/, '_').gsub(/[\W]+/, '').downcase
60
+ use_name = aliases[name] || attributize_field_name(name)
63
61
  add_attribute use_name, index
64
62
  end
65
63
  end
@@ -72,6 +70,12 @@ module CsvMapper
72
70
  @parser_options.merge :col_sep => @delimited_by
73
71
  end
74
72
 
73
+ # Default csv_mapper behaviour is to use the ordinal position of a mapped attribute.
74
+ # If you prefer to look for a column with the name of the attribute, use this method.
75
+ def named_columns
76
+ @named_columns = true
77
+ end
78
+
75
79
  # Convenience method to 'move' the cursor skipping the current index.
76
80
  def _SKIP_
77
81
  self.move_cursor
@@ -151,6 +155,17 @@ module CsvMapper
151
155
  # An optional first argument is used to move this maps cursor position and as the index of the
152
156
  # new AttributeMap
153
157
  def method_missing(name, *args) # :nodoc:
158
+ existing_map = self.mapped_attributes.find {|attr| attr.name == name}
159
+ return existing_map if existing_map
160
+
161
+ # Effectively add an alias when we see new_field('With/Aliased/Name')
162
+ if args[0].is_a? String
163
+ return add_attribute(name, headers_to_indices.fetch(args[0].downcase))
164
+ end
165
+
166
+ if @named_columns
167
+ return add_attribute(name, headers_to_indices.fetch(name.to_s))
168
+ end
154
169
 
155
170
  if index = args[0]
156
171
  self.move_cursor(index - self.cursor)
@@ -168,6 +183,20 @@ module CsvMapper
168
183
  end).flatten!
169
184
  end
170
185
 
186
+ def iterate_headers
187
+ attributes = FasterCSV.new(@csv_data, @parser_options).readline
188
+ @start_at_row = [ @start_at_row, 1 ].max
189
+ @csv_data.rewind
190
+ attributes.each_with_index { |name, index| yield name, index }
191
+ end
192
+
193
+ def headers_to_indices
194
+ return @h_to_i if @h_to_i
195
+ @h_to_i = {}
196
+ iterate_headers { |name, index| @h_to_i[name.strip.downcase] = index if name }
197
+ @h_to_i
198
+ end
199
+
171
200
  def map_to_class # :nodoc:
172
201
  unless @map_to_klass
173
202
  attrs = mapped_attributes.collect {|attr_map| attr_map.name}
@@ -180,5 +209,9 @@ module CsvMapper
180
209
  def cursor=(value) # :nodoc:
181
210
  @cursor=value
182
211
  end
212
+
213
+ def attributize_field_name(name)
214
+ name.gsub(/\s+/, '_').gsub(/[\W]+/, '').downcase
215
+ end
183
216
  end
184
217
  end
@@ -143,6 +143,44 @@ describe CsvMapper do
143
143
  results[1].number_of_years_old.should == '26'
144
144
  end
145
145
 
146
+ describe "Adding only certain attributes by name or alias" do
147
+ before :all do
148
+ @results = CsvMapper.import(File.dirname(__FILE__) + '/test_with_empty_column_names.csv') do
149
+ named_columns
150
+ surname('Last Name')
151
+ age.map { |row, index| row[index].to_i }
152
+ end
153
+ end
154
+
155
+ it "should have Last name aliased as surname" do
156
+ @results[1].surname.should == 'Doe'
157
+ end
158
+
159
+ it "should transform age to 26 (a Fixnum)" do
160
+ @results[1].age.should == 26
161
+ end
162
+
163
+ it "should not have First Name at all" do
164
+ lambda { @results[1].first_name }.should raise_error(NoMethodError)
165
+ end
166
+
167
+ it "should raise IndexError when adding non-existent fields" do
168
+ lambda {
169
+ @results = CsvMapper.import(File.dirname(__FILE__) + '/test_with_empty_column_names.csv') do
170
+ add_attributes_by_name('doesnt_exist')
171
+ end
172
+ }.should raise_error(IndexError)
173
+ end
174
+
175
+ it "should raise IndexError when adding non-existent aliases" do
176
+ lambda {
177
+ @results = CsvMapper.import(File.dirname(__FILE__) + '/test_with_empty_column_names.csv') do
178
+ my_new_field('doesnt_exist')
179
+ end
180
+ }.should raise_error(IndexError)
181
+ end
182
+ end
183
+
146
184
  it "should be able to assign default column names when column names are null" do
147
185
  results = CsvMapper.import(File.dirname(__FILE__) + '/test_with_empty_column_names.csv') do
148
186
  read_attributes_from_file
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgarner-csv-mapper
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 3
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
9
- - 1
10
- version: 0.5.1
8
+ - 7
9
+ - 0
10
+ version: 0.7.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Luke Pillow
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-08-25 00:00:00 +01:00
19
+ date: 2010-08-27 00:00:00 +01:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency