activeadmin-xls 1.0.5 → 2.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b3cefe4337bc929cc027541a8b378764fcee9c29
4
- data.tar.gz: 6ece12827ba7c2e0b85772b357c368a29d973c51
3
+ metadata.gz: '08d961ae05e4dca5b44e3e1615ce356fb8dd7e59'
4
+ data.tar.gz: 2c8f37c8e0c43cf10e91b9889576efeb3ff98297
5
5
  SHA512:
6
- metadata.gz: a505457094d423aad3857be11f8aaf26adafa48957678296019324c15736be6bc89c40be0b41e4e3ea79ed17d9abd205e4463937aca9f40618193bf7eb3e8de4
7
- data.tar.gz: 689a4ae242134e3cc0e7d7729b539eadca9349bbd141431422b7f0a83b10be7b3f72012ec60c92019b036973b9debe6f3e0b9ef947d35f815a51bb2dffb9c4a2
6
+ metadata.gz: c523bd762b313b3cb7002044462b80d5b300bb49c37606aa2b72da2da5e29702ba3c85c021fd886aad099fb606e6c5f2e0bff78118e872673311e66af7862bf5
7
+ data.tar.gz: fffc68d9617a1b2d61a7e639d4579379f4a4779eaa570d485c52dc86270649171fdf81b5583cf3d0f023ed66267e8011a5339c98fab73e63bddc148bf1ec9d41
data/.gitignore CHANGED
@@ -1,7 +1,7 @@
1
1
  spec/rails
2
2
  *.gem
3
3
  coverage
4
- *.xlsx
4
+ *.xls
5
5
  doc
6
6
  *.un~
7
7
  .yardoc
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.6.5
5
+
6
+ gemfile:
7
+ - gemfiles/rails_42.gemfile
8
+ - gemfiles/rails_52.gemfile
9
+ - gemfiles/rails_60.gemfile
10
+
11
+ script:
12
+ - bundle exec rake setup
13
+ - bundle exec rake
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --no-private --protected lib/**/*.rb - README.md LICENSE
data/CHANGELOG.md CHANGED
@@ -1,33 +1,83 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ## 2.0.3
6
+
7
+ ### Changed
8
+
9
+ * ignore test/ folder for gem building [#21][] by [@cprodhomme][]
10
+
11
+ ## 2.0.2
12
+
13
+ ### Changed
14
+
15
+ * Remove ActiveAdmin runtime dependency version limit '<2' [#16][] by [@reaper][]
16
+
17
+ ## 2.0.1
18
+
19
+ ### Fixed
20
+
21
+ * fix issue with xls_builder retaining data between requests when there is an exception on a computed field [#13][]
22
+
23
+ ## 2.0.0
24
+
25
+ ### Changed
26
+
27
+ * Drop support for ruby 1.9, rails 3.2, and ActiveAdmin 0.6.6.
28
+ * Add support for rails 5.1 [#8][]
29
+
30
+ ## 1.1.0
31
+
32
+ ### Added
33
+
34
+ * Add only_columns [#7][]
35
+
36
+ ### Fixed
37
+
38
+ * Fix typo in README.md [#11][] by [@cpunion][]
39
+
40
+ ### Changed
41
+
42
+ * Update tests for ActiveAdmin 1.2
43
+
3
44
  ## 1.0.5
4
45
 
5
- ### Updates
46
+ ### Fixed
6
47
 
7
48
  * Fix #1 - Unnecessary database access
8
49
  * Fix broken tests
9
50
 
10
51
  ## 1.0.4
11
52
 
12
- ### Updates
53
+ ### Fixed
13
54
 
14
55
  * Minor bug fixes / typo corrections
15
56
 
16
57
  ## 1.0.3
17
58
 
18
- ### Updates
59
+ ### Fixed
19
60
 
20
61
  * Move require rake from gemspec to lib/activeadmin-xls.rb [#4][] by [@ejaypcanaria][]
21
62
 
22
63
  ## 1.0.2
23
64
 
24
- ### Bug Fixes
65
+ ### Fixed
25
66
 
26
67
  * Fixes undefined local variable or `method max_per_page` [#3][] by [@rewritten][]
27
68
 
28
69
  <!--- Link List --->
29
70
  [#3]: https://github.com/thambley/activeadmin-xls/issues/3
30
71
  [#4]: https://github.com/thambley/activeadmin-xls/pull/4
72
+ [#7]: https://github.com/thambley/activeadmin-xls/issues/7
73
+ [#8]: https://github.com/thambley/activeadmin-xls/issues/8
74
+ [#11]: https://github.com/thambley/activeadmin-xls/pull/11
75
+ [#13]: https://github.com/thambley/activeadmin-xls/issues/13
76
+ [#16]: https://github.com/thambley/activeadmin-xls/pull/16
77
+ [#21]: https://github.com/thambley/activeadmin-xls/pull/21
31
78
 
32
79
  [@rewritten]: https://github.com/rewritten
33
80
  [@ejaypcanaria]: https://github.com/ejaypcanaria
81
+ [@cpunion]: https://github.com/cpunion
82
+ [@reaper]: https://github.com/reaper
83
+ [@cprodhomme]: https://github.com/cprodhomme
data/Gemfile CHANGED
@@ -4,11 +4,11 @@ gem 'spreadsheet', '~> 1.1', '>= 1.1.4'
4
4
 
5
5
  group :development, :test do
6
6
  gem 'rails-i18n' # Gives us default i18n for many languages
7
- gem 'sqlite3'
8
7
  gem 'yard'
9
8
  end
10
9
 
11
10
  group :test do
11
+ gem 'codecov', require: false
12
12
  gem 'cucumber-rails', require: false
13
13
  gem 'database_cleaner'
14
14
  gem 'rspec-mocks', '~> 3.7'
data/README.md CHANGED
@@ -1,34 +1,38 @@
1
- # Active Admin Xls: Excel Spreadsheet Export for Active Admin
1
+ # Active Admin Xls
2
2
 
3
- **Git**: [http://github.com/thambley/activeadmin-xls](http://github.com/thambley/activeadmin-xls)
3
+ Excel Spreadsheet Export for [Active Admin]
4
4
 
5
- **Author**: Todd Hambley
6
-
7
- **Copyright**: 2014 ~ 2017
8
-
9
- **License**: MIT License
10
-
11
- **Latest Version**: 1.0.4
12
-
13
- **Release Date**: 2017.11.22
5
+ [![Version][rubygems_badge]][rubygems]
6
+ [![Travis CI][travis_badge]][travis]
7
+ [![Quality][codeclimate_badge]][codeclimate]
8
+ [![Coverage][codecov_badge]][codecov]
9
+ [![Inch CI][inch_badge]][inch]
14
10
 
15
11
  ## Synopsis
16
12
 
17
13
  This gem provides xls downloads for Active Admin resources.
18
14
 
19
- This gem borrows heavily from [https://github.com/randym/activeadmin-axlsx](https://github.com/randym/activeadmin-axlsx) and [https://github.com/splendeo/to_xls](https://github.com/splendeo/to_xls).
15
+ This gem borrows heavily from [activeadmin-axlsx] and [to_xls].
20
16
 
21
- Usage example:
17
+ ## Usage
22
18
 
23
- Add the following to your Gemfile and you are good to go.
24
- All resource index views will now include a link for download directly
25
- to xls.
19
+ Add the following to your Gemfile. All resource index views will now include a link for download directly to xls.
26
20
 
27
21
  ```ruby
28
- gem 'activeadmin-xls'
22
+ gem 'activeadmin-xls', '~>2.0.0'
29
23
  ```
30
24
 
31
- ## Cool Toys
25
+ For Active Admin 1.0 and above, you will also have to update config/initializers/active_admin.rb. Update the download\_links setting to include xls:
26
+
27
+ ```ruby
28
+ config.download_links = %i[csv xml json xls]
29
+ ```
30
+
31
+ ## Dependencies
32
+
33
+ This gem depends on [spreadsheet] to generate xls files.
34
+
35
+ ## Examples
32
36
 
33
37
  Here are a few quick examples of things you can easily tweak.
34
38
 
@@ -71,6 +75,15 @@ ActiveAdmin.register Post do
71
75
  end
72
76
  ```
73
77
 
78
+ ### Restrict columns to a list
79
+
80
+ ```ruby
81
+ # app/admin/posts.rb
82
+ ActiveAdmin.register Post do
83
+ config.xls_builder.only_columns :title, :author
84
+ end
85
+ ```
86
+
74
87
  ## Using the DSL
75
88
 
76
89
  Everything that you do with the config's default builder can be done via
@@ -91,10 +104,13 @@ ActiveAdmin.register Post do
91
104
  # Do not serialize the header, only output data.
92
105
  # skip_header
93
106
 
107
+ # restrict columns to a list without customization
108
+ # only_columns :title, :author
109
+
94
110
  # deleting columns from the report
95
111
  delete_columns :id, :created_at, :updated_at
96
112
 
97
- # adding a column to the report
113
+ # adding a column to the report with customization
98
114
  column(:author) { |post| "#{post.author.first_name} #{post.author.last_name}" }
99
115
 
100
116
  # inserting additional data with after_filter
@@ -110,42 +126,66 @@ ActiveAdmin.register Post do
110
126
  end
111
127
  ```
112
128
 
113
- ## Specs
129
+ ## Testing
114
130
 
115
131
  Running specs for this gem requires that you construct a rails application.
116
132
 
117
133
  To execute the specs, navigate to the gem directory, run bundle install and run these to rake tasks:
118
134
 
119
- ### Rails 3.2
135
+ ### Rails 4.2
120
136
 
121
137
  ```text
122
- bundle install --gemfile=gemfiles/rails_32.gemfile
138
+ bundle install --gemfile=gemfiles/rails_42.gemfile
123
139
  ```
124
140
 
125
141
  ```text
126
- BUNDLE_GEMFILE=gemfiles/rails_32.gemfile bundle exec rake setup
142
+ BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake setup
127
143
  ```
128
144
 
129
145
  ```text
130
- BUNDLE_GEMFILE=gemfiles/rails_32.gemfile bundle exec rake
146
+ BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake
131
147
  ```
132
148
 
133
- ### Rails 4.2
149
+ ### Rails 5.2
134
150
 
135
151
  ```text
136
- bundle install --gemfile=gemfiles/rails_42.gemfile
152
+ bundle install --gemfile=gemfiles/rails_52.gemfile
137
153
  ```
138
154
 
139
155
  ```text
140
- BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake setup
156
+ BUNDLE_GEMFILE=gemfiles/rails_52.gemfile bundle exec rake setup
141
157
  ```
142
158
 
143
159
  ```text
144
- BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake
160
+ BUNDLE_GEMFILE=gemfiles/rails_52.gemfile bundle exec rake
145
161
  ```
146
162
 
147
- ## Copyright and License
163
+ ### Rails 6.0
148
164
 
149
- activeadmin-xls &copy; 2014 by [Todd Hambley](mailto:thambley@travelleaders.com).
165
+ ```text
166
+ bundle install --gemfile=gemfiles/rails_60.gemfile
167
+ ```
168
+
169
+ ```text
170
+ BUNDLE_GEMFILE=gemfiles/rails_60.gemfile bundle exec rake setup
171
+ ```
172
+
173
+ ```text
174
+ BUNDLE_GEMFILE=gemfiles/rails_60.gemfile bundle exec rake
175
+ ```
150
176
 
151
- activeadmin-xls is licensed under the MIT license. Please see the LICENSE document for more information.
177
+ [Active Admin]:https://www.activeadmin.info/
178
+ [activeadmin-axlsx]:https://github.com/randym/activeadmin-axlsx
179
+ [to_xls]:https://github.com/splendeo/to_xls
180
+ [spreadsheet]:https://github.com/zdavatz/spreadsheet
181
+
182
+ [rubygems_badge]: https://img.shields.io/gem/v/activeadmin-xls.svg
183
+ [rubygems]: https://rubygems.org/gems/activeadmin-xls
184
+ [travis_badge]: https://img.shields.io/travis/thambley/activeadmin-xls/master.svg
185
+ [travis]: https://travis-ci.org/thambley/activeadmin-xls
186
+ [codeclimate_badge]: https://api.codeclimate.com/v1/badges/e294712bac54d4520182/maintainability
187
+ [codeclimate]: https://codeclimate.com/github/thambley/activeadmin-xls/maintainability
188
+ [codecov_badge]: https://codecov.io/gh/thambley/activeadmin-xls/branch/master/graph/badge.svg
189
+ [codecov]: https://codecov.io/gh/thambley/activeadmin-xls
190
+ [inch_badge]: http://inch-ci.org/github/thambley/activeadmin-xls.svg?branch=master
191
+ [inch]: http://inch-ci.org/github/thambley/activeadmin-xls
data/Rakefile CHANGED
@@ -1,12 +1,31 @@
1
1
  #!/usr/bin/env rake
2
+ require File.expand_path('../lib/active_admin/xls/version', __FILE__)
2
3
  require 'rspec/core/rake_task'
3
4
 
4
5
  desc 'Creates a test rails app for the specs to run against'
5
6
  task :setup do
6
7
  require 'rails/version'
7
- system('mkdir spec/rails') unless File.exist?('spec/rails')
8
- puts "system \"bundle exec rails new spec/rails/rails-#{Rails::VERSION::STRING} -m spec/support/rails_template_with_data.rb\""
9
- system "bundle exec rails new spec/rails/rails-#{Rails::VERSION::STRING} -m spec/support/rails_template_with_data.rb"
8
+ base_dir = 'spec/rails'
9
+ app_dir = "#{base_dir}/rails-#{Rails::VERSION::STRING}"
10
+ template = 'rails_template_with_data'
11
+
12
+ if File.exist? app_dir
13
+ puts "test app #{app_dir} already exists; skipping"
14
+ else
15
+ system "mkdir -p #{base_dir}"
16
+ args = %W[
17
+ -m spec/support/#{template}.rb
18
+ --skip-bundle
19
+ --skip-listen
20
+ --skip-turbolinks
21
+ --skip-test-unit
22
+ --skip-coffee
23
+ ]
24
+
25
+ command = ['bundle', 'exec', 'rails', 'new', app_dir, *args].join(' ')
26
+ env = { 'BUNDLE_GEMFILE' => ENV['BUNDLE_GEMFILE'] }
27
+ Bundler.with_clean_env { Kernel.exec(env, command) }
28
+ end
10
29
  end
11
30
 
12
31
  RSpec::Core::RakeTask.new
@@ -17,6 +36,7 @@ desc 'build the gem'
17
36
  task :build do
18
37
  system 'gem build activeadmin-xls.gemspec'
19
38
  end
39
+
20
40
  desc 'build and release the gem'
21
41
  task release: :build do
22
42
  system "gem push activeadmin-xls-#{ActiveAdmin::Xls::VERSION}.gem"
@@ -19,11 +19,11 @@ Gem::Specification.new do |s|
19
19
  git_tracked_files = `git ls-files`.split("\n").sort
20
20
  gem_ignored_files = `git ls-files -i -X .gemignore`.split("\n")
21
21
 
22
- s.files = git_tracked_files - gem_ignored_files
22
+ s.files = (git_tracked_files - gem_ignored_files).reject { |f| f.match(%r{^(test|spec|features)/}) }
23
23
 
24
- s.add_runtime_dependency 'activeadmin', '>= 0.6.6', '< 2'
24
+ s.add_runtime_dependency 'activeadmin', '>= 1.0.0'
25
25
  s.add_runtime_dependency 'spreadsheet', '~> 1.0'
26
26
 
27
- s.required_ruby_version = '>= 1.9.2'
27
+ s.required_ruby_version = '>= 2.0.0'
28
28
  s.require_path = 'lib'
29
29
  end
@@ -6,9 +6,11 @@ ruby_minor_version = RUBY_VERSION.split('.')[1].to_i
6
6
 
7
7
  eval_gemfile(File.expand_path(File.join('..', 'Gemfile'), __dir__))
8
8
 
9
- gem 'activeadmin', '1.0.0'
9
+ gem 'activeadmin', '1.4.3'
10
10
  gem 'devise', '~> 4.2'
11
- gem 'rails', '4.2.10'
11
+ gem 'rails', '4.2.11'
12
+ gem 'sprockets', '< 4.0'
13
+ gem 'sqlite3', '~> 1.3.0'
12
14
  gem 'turbolinks', '~> 5.0.0'
13
15
  gem 'tzinfo-data'
14
16
 
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+ source 'https://rubygems.org'
3
+
4
+ ruby_major_version = RUBY_VERSION.split('.')[0].to_i
5
+ ruby_minor_version = RUBY_VERSION.split('.')[1].to_i
6
+
7
+ eval_gemfile(File.expand_path(File.join('..', 'Gemfile'), __dir__))
8
+
9
+ gem 'activeadmin', '2.4.0'
10
+ gem 'bootsnap', require: false
11
+ gem 'devise', '~> 4.7'
12
+ gem 'rails', ' ~> 5.2'
13
+ gem 'sqlite3', '~> 1.4.0'
14
+ gem 'turbolinks', '~> 5.2.0'
15
+ gem 'tzinfo-data'
16
+
17
+ group :test do
18
+ gem 'shoulda-matchers', '~> 3.1'
19
+ if ruby_major_version > 2 || (ruby_major_version == 2 && ruby_minor_version > 1)
20
+ gem 'test-unit', '~> 3.0'
21
+ end
22
+ end
23
+
24
+ gemspec path: "../"
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ source 'https://rubygems.org'
3
+
4
+ ruby_major_version = RUBY_VERSION.split('.')[0].to_i
5
+ ruby_minor_version = RUBY_VERSION.split('.')[1].to_i
6
+
7
+ eval_gemfile(File.expand_path(File.join('..', 'Gemfile'), __dir__))
8
+
9
+ gem 'activeadmin', '2.4.0'
10
+ gem 'bootsnap', require: false
11
+ gem 'devise', '~> 4.7'
12
+ gem 'rails', '~> 6'
13
+ gem 'sqlite3', '~> 1.4.0'
14
+ gem 'turbolinks', '~> 5.2.0'
15
+ gem 'tzinfo-data'
16
+ gem 'webpacker', '~> 4.x'
17
+
18
+ group :test do
19
+ gem 'shoulda-matchers', '~> 3.1'
20
+ if ruby_major_version > 2 || (ruby_major_version == 2 && ruby_minor_version > 1)
21
+ gem 'test-unit', '~> 3.0'
22
+ end
23
+ end
24
+
25
+ gemspec path: "../"
@@ -7,26 +7,28 @@ module ActiveAdmin
7
7
  class Builder
8
8
  include MethodOrProcHelper
9
9
 
10
- # @param resource_class The resource this builder generate column
10
+ # @param [Class] resource_class The resource this builder generate column
11
11
  # information for.
12
- # @param [Hash] options the options for this builder
13
- # @option [Hash] :header_format - a hash of format properties to apply
14
- # to the header row. Any properties specified will be merged with the
15
- # default header styles. @see https://github.com/zdavatz/spreadsheet/blob/master/lib/spreadsheet/format.rb
16
- # @option [Array] :i18n_scope - the I18n scope to use when looking
12
+ # @param [Hash] options the options for the builder
13
+ # @option options [Hash] :header_format A hash of format properties to
14
+ # apply to the header row. Any properties specified will be merged with
15
+ # the default header styles.
16
+ # @option options [Array] :i18n_scope the I18n scope to use when looking
17
17
  # up localized column headers.
18
- # @param [Block] Any block given will evaluated against this instance of
18
+ # @param [Block] block Block given will evaluated against this instance of
19
19
  # Builder. That means you can call any method on the builder from within
20
20
  # that block.
21
21
  # @example
22
- # ActiveAdmin::Xls:Builder.new(Post, i18n: [:xls]) do
22
+ # ActiveAdmin::Xls::Builder.new(Post, i18n: [:xls]) do
23
23
  # delete_columns :id, :created_at, :updated_at
24
24
  # column(:author_name) { |post| post.author.name }
25
- # after_filter { |sheet|
26
- #
27
- # }
25
+ # after_filter do |sheet|
26
+ # # todo
27
+ # end
28
28
  # end
29
- # @see ActiveAdmin::Axlsx::DSL
29
+ #
30
+ # @see DSL
31
+ # @see https://github.com/zdavatz/spreadsheet/blob/master/lib/spreadsheet/format.rb
30
32
  def initialize(resource_class, options = {}, &block)
31
33
  @skip_header = false
32
34
  @resource_class = resource_class
@@ -39,6 +41,8 @@ module ActiveAdmin
39
41
 
40
42
  # The default header style
41
43
  # @return [Hash]
44
+ #
45
+ # @see https://github.com/zdavatz/spreadsheet/blob/master/lib/spreadsheet/format.rb
42
46
  def header_format
43
47
  @header_format ||= {}
44
48
  end
@@ -47,9 +51,28 @@ module ActiveAdmin
47
51
 
48
52
  # This has can be used to override the default header style for your
49
53
  # sheet. Any values you provide will be merged with the default styles.
50
- # Precidence is given to your hash
54
+ # Precedence is given to your hash
55
+ #
56
+ # @example In Builder.new
57
+ # options = {
58
+ # header_format: { weight: :bold },
59
+ # i18n_scope: %i[xls post]
60
+ # }
61
+ # Builder.new(Post, options) do
62
+ # skip_header
63
+ # end
64
+ #
65
+ # @example With DSL
66
+ # ActiveAdmin.register Post do
67
+ # xls(header_format: { weight: :bold }, i18n_scope: %i[xls post]) do
68
+ # skip_header
69
+ # end
70
+ # end
71
+ #
72
+ # @example Simple DSL without block
73
+ # xls header_format: { weight: :bold }
74
+ #
51
75
  # @see https://github.com/zdavatz/spreadsheet/blob/master/lib/spreadsheet/format.rb
52
- # for more details on how to create and apply style.
53
76
  def header_format=(format_hash)
54
77
  @header_format = header_format.merge(format_hash)
55
78
  end
@@ -57,33 +80,85 @@ module ActiveAdmin
57
80
  alias header_style= header_format=
58
81
 
59
82
  # Indicates that we do not want to serialize the column headers
83
+ #
84
+ # @example In Builder.new
85
+ # options = {
86
+ # header_format: { weight: :bold },
87
+ # i18n_scope: %i[xls post]
88
+ # }
89
+ # Builder.new(Post, options) do
90
+ # skip_header
91
+ # end
92
+ #
93
+ # @example With DSL
94
+ # ActiveAdmin.register Post do
95
+ # xls(header_format: { weight: :bold }, i18n_scope: %i[xls post]) do
96
+ # skip_header
97
+ # end
98
+ # end
60
99
  def skip_header
61
100
  @skip_header = true
62
101
  end
63
102
 
64
- # The scope to use when looking up column names to generate the
65
- # report header
66
- attr_reader :i18n_scope
67
-
68
- # This is the I18n scope that will be used when looking up your
69
- # colum names in the current I18n locale.
103
+ # The I18n scope that will be used when looking up your
104
+ # column names in the current I18n locale.
70
105
  # If you set it to [:active_admin, :resources, :posts] the
71
106
  # serializer will render the value at active_admin.resources.posts.title
72
107
  # in the current translations
108
+ #
73
109
  # @note If you do not set this, the column name will be titleized.
74
- attr_writer :i18n_scope
110
+ attr_accessor :i18n_scope
75
111
 
76
112
  # The stored block that will be executed after your report is generated.
113
+ #
114
+ # @yieldparam sheet [Spreadsheet::Worksheet] the worksheet where the
115
+ # collection has been serialized
116
+ #
117
+ # @example With DSL
118
+ # xls do
119
+ # after_filter do |sheet|
120
+ # row_number = sheet.dimensions[1]
121
+ # sheet.update_row(row_number)
122
+ # row_number += 1
123
+ # sheet.update_row(row_number, 'Author Name', 'Number of Posts')
124
+ # users = collection.map(&:author).uniq(&:id)
125
+ # users.each do |user|
126
+ # row_number += 1
127
+ # sheet.update_row(row_number,
128
+ # "#{user.first_name} #{user.last_name}",
129
+ # user.posts.size)
130
+ # end
131
+ # end
132
+ # end
77
133
  def after_filter(&block)
78
134
  @after_filter = block
79
135
  end
80
136
 
81
137
  # the stored block that will be executed before your report is generated.
138
+ #
139
+ # @yieldparam sheet [Spreadsheet::Worksheet] the worksheet where the
140
+ # collection has been serialized
141
+ #
142
+ # @example with DSL
143
+ # xls do
144
+ # before_filter do |sheet|
145
+ # users = collection.map(&:author)
146
+ # users.each do |user|
147
+ # user.first_name = 'Set In Proc' if user.first_name == 'bob'
148
+ # end
149
+ # row_number = sheet.dimensions[1]
150
+ # sheet.update_row(row_number, 'Created', Time.zone.now)
151
+ # row_number += 1
152
+ # sheet.update_row(row_number, '')
153
+ # end
154
+ # end
82
155
  def before_filter(&block)
83
156
  @before_filter = block
84
157
  end
85
158
 
86
- # The columns this builder will be serializing
159
+ # Returns the columns the builder will serialize.
160
+ #
161
+ # @return [Array<Column>] columns configued on the builder.
87
162
  def columns
88
163
  # execute each update from @column_updates
89
164
  # set @columns_loaded = true
@@ -92,13 +167,20 @@ module ActiveAdmin
92
167
  end
93
168
 
94
169
  # The collection we are serializing.
170
+ #
95
171
  # @note This is only available after serialize has been called,
96
172
  # and is reset on each subsequent call.
97
173
  attr_reader :collection
98
174
 
99
- # removes all columns from the builder. This is useful when you want to
175
+ # Removes all columns from the builder. This is useful when you want to
100
176
  # only render specific columns. To remove specific columns use
101
177
  # ignore_column.
178
+ #
179
+ # @example Using alias whitelist
180
+ # Builder.new(Post, header_style: {}, i18n_scope: %i[xls post]) do
181
+ # whitelist
182
+ # column :title
183
+ # end
102
184
  def clear_columns
103
185
  @columns_loaded = true
104
186
  @column_updates = []
@@ -114,6 +196,18 @@ module ActiveAdmin
114
196
  # @param [Symbol] name The name of the column.
115
197
  # @param [Proc] block A block of code that is executed on the resource
116
198
  # when generating row data for this column.
199
+ #
200
+ # @example With block
201
+ # xls(i18n_scope: [:rspec], header_style: { size: 20 }) do
202
+ # delete_columns :id, :created_at
203
+ # column(:author) { |post| post.author.first_name }
204
+ # end
205
+ #
206
+ # @example With default value
207
+ # Builder.new(Post, header_style: {}, i18n_scope: %i[xls post]) do
208
+ # whitelist
209
+ # column :title
210
+ # end
117
211
  def column(name, &block)
118
212
  if @columns_loaded
119
213
  columns << Column.new(name, block)
@@ -125,8 +219,20 @@ module ActiveAdmin
125
219
  end
126
220
  end
127
221
 
128
- # removes columns by name
129
- # each column_name should be a symbol
222
+ # Removes columns by name.
223
+ # Each column_name should be a symbol.
224
+ #
225
+ # @example In Builder.new
226
+ # options = {
227
+ # header_style: { size: 10, color: 'red' },
228
+ # i18n_scope: %i[xls post]
229
+ # }
230
+ # Builder.new(Post, options) do
231
+ # delete_columns :id, :created_at, :updated_at
232
+ # column(:author) do |resource|
233
+ # "#{resource.author.first_name} #{resource.author.last_name}"
234
+ # end
235
+ # end
130
236
  def delete_columns(*column_names)
131
237
  if @columns_loaded
132
238
  columns.delete_if { |column| column_names.include?(column.name) }
@@ -138,27 +244,61 @@ module ActiveAdmin
138
244
  end
139
245
  end
140
246
 
247
+ # Removes all columns, and add columns by name.
248
+ # Each column_name should be a symbol
249
+ #
250
+ # @example
251
+ # config.xls_builder.only_columns :title, :author
252
+ def only_columns(*column_names)
253
+ clear_columns
254
+ column_names.each do |column_name|
255
+ column column_name
256
+ end
257
+ end
258
+
141
259
  # Serializes the collection provided
260
+ #
261
+ # @param collection [Enumerable] list of resources to serialize
262
+ # @param view_context object on which unknown methods may be executed
142
263
  # @return [Spreadsheet::Workbook]
143
264
  def serialize(collection, view_context = nil)
144
265
  @collection = collection
145
266
  @view_context = view_context
267
+ book = Spreadsheet::Workbook.new
268
+ sheet = book.create_worksheet
146
269
  load_columns unless @columns_loaded
147
- apply_filter @before_filter
148
- export_collection(collection)
149
- apply_filter @after_filter
150
- to_stream
270
+ apply_filter @before_filter, sheet
271
+ export_collection collection, sheet
272
+ apply_filter @after_filter, sheet
273
+ to_stream book
151
274
  end
152
275
 
153
- # Xls column
276
+ # Xls column information
154
277
  class Column
278
+ # @param name [String, Symbol] Name of the column. If the name of the
279
+ # column is an existing attribute of the resource class, the value
280
+ # can be retreived automatically if no block is specified
281
+ # @param block [Proc] A procedure to generate data for the column
282
+ # instead of retreiving the value from the resource directly
155
283
  def initialize(name, block = nil)
156
284
  @name = name
157
285
  @data = block || @name
158
286
  end
159
287
 
160
- attr_reader :name, :data
288
+ # @return [String, Symbol] Column name
289
+ attr_reader :name
290
+
291
+ # @return [String, Symbol, Proc] The column name used to look up the
292
+ # value, or a block used to generate the value to display.
293
+ attr_reader :data
161
294
 
295
+ # Returns a localized version of the column name if a scope is given.
296
+ # Otherwise, it returns the titleized column name without translation.
297
+ #
298
+ # @param i18n_scope [String, Symbol, Array<String>, Array<Symbol>]
299
+ # Translation scope. If not provided, the column name will be used.
300
+ #
301
+ # @see I18n
162
302
  def localized_name(i18n_scope = nil)
163
303
  return name.to_s.titleize unless i18n_scope
164
304
  I18n.t name, scope: i18n_scope
@@ -176,18 +316,13 @@ module ActiveAdmin
176
316
  columns
177
317
  end
178
318
 
179
- def to_stream
319
+ def to_stream(book)
180
320
  stream = StringIO.new('')
181
321
  book.write stream
182
- clean_up
183
322
  stream.string
184
323
  end
185
324
 
186
- def clean_up
187
- @book = @sheet = nil
188
- end
189
-
190
- def export_collection(collection)
325
+ def export_collection(collection, sheet)
191
326
  return if columns.none?
192
327
  row_index = sheet.dimensions[1]
193
328
 
@@ -216,7 +351,7 @@ module ActiveAdmin
216
351
  end.compact
217
352
  end
218
353
 
219
- def apply_filter(filter)
354
+ def apply_filter(filter, sheet)
220
355
  filter.call(sheet) if filter
221
356
  end
222
357
 
@@ -238,14 +373,6 @@ module ActiveAdmin
238
373
  resource.respond_to?(column.name)
239
374
  end
240
375
 
241
- def sheet
242
- @sheet ||= book.create_worksheet
243
- end
244
-
245
- def book
246
- @book ||= ::Spreadsheet::Workbook.new
247
- end
248
-
249
376
  def resource_columns(resource)
250
377
  [Column.new(:id)] + resource.content_columns.map do |column|
251
378
  Column.new(column.name.to_sym)