@@ -82,23 +82,15 @@ def batch_replace(header_key, options)
8282 # end
8383 #
8484 def batch_slice_columns ( slice_columns )
85- # Only set @use_indexes for the first batch so that @use_indexes are in correct
86- # position for subsequent batches
87- unless defined? ( @use_indexes )
88- @use_indexes = [ ]
89- headers . values . each_with_index do |val , index |
90- @use_indexes << index if val . in? ( slice_columns )
91- end
92- return csv_lines if @use_indexes . empty?
93-
94- # slice CSV headers
95- @headers = headers . to_a . values_at ( *@use_indexes ) . to_h
96- end
85+ columns = headers . values
86+ indexes = columns . each_index . select { |i | columns [ i ] . in? ( slice_columns ) }
87+ return csv_lines if indexes . empty?
9788
98- # slice CSV values
99- csv_lines . map! do |line |
100- line . values_at ( *@use_indexes )
101- end
89+ # @headers is reset to the full set at the start of every batch (see
90+ # #batch_import), so each call narrows the previous call's result and every
91+ # batch slices the same way — calling this more than once now composes (#186).
92+ @headers = headers . to_a . values_at ( *indexes ) . to_h
93+ csv_lines . map! { |line | line . values_at ( *indexes ) }
10294 end
10395
10496 def values_at ( header_key )
@@ -129,17 +121,18 @@ def process_file
129121 end
130122
131123 def prepare_headers
132- headers = self . headers . present? ? self . headers : yield
133- blank_positions = headers . each_index . select { |i | headers [ i ] . to_s . strip . empty? }
124+ names = self . headers . present? ? self . headers : yield
125+ blank_positions = names . each_index . select { |i | names [ i ] . to_s . strip . empty? }
134126 unless blank_positions . empty?
135127 raise ActiveAdminImport ::Exception ,
136128 "blank column header at column #{ blank_positions . map { |i | i + 1 } . join ( ', ' ) } "
137129 end
138130
139- headers = headers . map ( &:to_s )
140- @headers = Hash [ headers . zip ( headers . map { |el | el . underscore . gsub ( /\s +/ , '_' ) } ) ] . with_indifferent_access
141- @headers . merge! ( options [ :headers_rewrites ] . symbolize_keys . slice ( *@headers . symbolize_keys . keys ) )
142- @headers
131+ names = names . map ( &:to_s )
132+ # @source_headers is the complete parsed header row; batch_import copies it
133+ # into the per-batch working @headers (see #batch_import).
134+ @source_headers = Hash [ names . zip ( names . map { |el | el . underscore . gsub ( /\s +/ , '_' ) } ) ] . with_indifferent_access
135+ @source_headers . merge! ( options [ :headers_rewrites ] . symbolize_keys . slice ( *@source_headers . symbolize_keys . keys ) )
143136 end
144137
145138 def run_callback ( name )
@@ -148,6 +141,9 @@ def run_callback(name)
148141
149142 def batch_import
150143 batch_result = nil
144+ # Every batch re-parses full-width rows, so restore the full header set
145+ # before slicing; batch_slice_columns then narrows this working copy.
146+ @headers = @source_headers . dup
151147 @resource . transaction do
152148 run_callback ( :before_batch_import )
153149 batch_result = resource . import ( headers . values , csv_lines , import_options )
0 commit comments