@@ -29,7 +29,10 @@ class Builder
2929 # @see ActiveAdmin::Axlsx::DSL
3030 def initialize ( resource_class , options = { } , &block )
3131 @skip_header = false
32- @columns = resource_columns ( resource_class )
32+ @resource_class = resource_class
33+ @columns = [ ]
34+ @columns_loaded = false
35+ @column_updates = [ ]
3336 parse_options options
3437 instance_eval ( &block ) if block_given?
3538 end
@@ -60,9 +63,7 @@ def skip_header
6063
6164 # The scope to use when looking up column names to generate the
6265 # report header
63- def i18n_scope
64- @i18n_scope ||= nil
65- end
66+ attr_reader :i18n_scope
6667
6768 # This is the I18n scope that will be used when looking up your
6869 # colum names in the current I18n locale.
@@ -83,7 +84,12 @@ def before_filter(&block)
8384 end
8485
8586 # The columns this builder will be serializing
86- attr_reader :columns
87+ def columns
88+ # execute each update from @column_updates
89+ # set @columns_loaded = true
90+ load_columns unless @columns_loaded
91+ @columns
92+ end
8793
8894 # The collection we are serializing.
8995 # @note This is only available after serialize has been called,
@@ -94,34 +100,50 @@ def before_filter(&block)
94100 # only render specific columns. To remove specific columns use
95101 # ignore_column.
96102 def clear_columns
103+ @columns_loaded = true
104+ @column_updates = [ ]
105+
97106 @columns = [ ]
98107 end
99108
100109 # Clears the default columns array so you can whitelist only the columns
101110 # you want to export
102- def whitelist
103- @columns = [ ]
104- end
111+ alias whitelist clear_columns
105112
106113 # Add a column
107114 # @param [Symbol] name The name of the column.
108115 # @param [Proc] block A block of code that is executed on the resource
109116 # when generating row data for this column.
110117 def column ( name , &block )
111- @columns << Column . new ( name , block )
118+ if @columns_loaded
119+ columns << Column . new ( name , block )
120+ else
121+ column_lambda = lambda do
122+ column ( name , &block )
123+ end
124+ @column_updates << column_lambda
125+ end
112126 end
113127
114128 # removes columns by name
115129 # each column_name should be a symbol
116130 def delete_columns ( *column_names )
117- @columns . delete_if { |column | column_names . include? ( column . name ) }
131+ if @columns_loaded
132+ columns . delete_if { |column | column_names . include? ( column . name ) }
133+ else
134+ delete_lambda = lambda do
135+ delete_columns ( *column_names )
136+ end
137+ @column_updates << delete_lambda
138+ end
118139 end
119140
120141 # Serializes the collection provided
121142 # @return [Spreadsheet::Workbook]
122- def serialize ( collection , view_context )
143+ def serialize ( collection , view_context = nil )
123144 @collection = collection
124145 @view_context = view_context
146+ load_columns unless @columns_loaded
125147 apply_filter @before_filter
126148 export_collection ( collection )
127149 apply_filter @after_filter
@@ -145,6 +167,15 @@ def localized_name(i18n_scope = nil)
145167
146168 private
147169
170+ def load_columns
171+ return if @columns_loaded
172+ @columns = resource_columns ( @resource_class )
173+ @columns_loaded = true
174+ @column_updates . each ( &:call )
175+ @column_updates = [ ]
176+ columns
177+ end
178+
148179 def to_stream
149180 stream = StringIO . new ( '' )
150181 book . write stream
@@ -158,11 +189,11 @@ def clean_up
158189
159190 def export_collection ( collection )
160191 return if columns . none?
161- row_index = 0
192+ row_index = sheet . dimensions [ 1 ]
162193
163194 unless @skip_header
164- header_row ( collection )
165- row_index = 1
195+ header_row ( sheet . row ( row_index ) , collection )
196+ row_index + = 1
166197 end
167198
168199 collection . each do |resource |
@@ -173,14 +204,13 @@ def export_collection(collection)
173204
174205 # tranform column names into array of localized strings
175206 # @return [Array]
176- def header_row ( collection )
177- row = sheet . row ( 0 )
207+ def header_row ( row , collection )
178208 apply_format_to_row ( row , create_format ( header_format ) )
179209 fill_row ( row , header_data_for ( collection ) )
180210 end
181211
182212 def header_data_for ( collection )
183- resource = collection . first
213+ resource = collection . first || @resource_class . new
184214 columns . map do |column |
185215 column . localized_name ( i18n_scope ) if in_scope ( resource , column )
186216 end . compact
0 commit comments