activeadmin-xls 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a30a7f1fc93455cecb1aac5d28026454061ebdcd
4
- data.tar.gz: a1342476206f3a3b7ba04c15df545d620af315eb
3
+ metadata.gz: 0061e54090d183ee6259739d20d7db62eb890790
4
+ data.tar.gz: 7691fe01a10bcdd3aac3239f690ae98f95258460
5
5
  SHA512:
6
- metadata.gz: acd27c54cbf49c5148d94625f4872b89291513fbea277ff8fb0e96231a40ce8172fb9cae4d91ad4e1adeda135ce45feb704a5396a2c66252a49f97abf3ab9de8
7
- data.tar.gz: 9baa56bf539d13050c67b6a9e911323a0d5bd04bd43b6182eb32f0de4e6c125aaca61b32adafa86addd387072d751db5497f1b3273320abbd2aa044912b19f0e
6
+ metadata.gz: 522ac0e6309ad124d216acdd64228efec606836dd75369f90b9f8e2e806e017c658190a841c56bf54b3e77fe72bd3b5cac00be571db3602745a22f432855f33d
7
+ data.tar.gz: ffab449bd41cfb19b97d5b879d656f531a2cde929e98a5188b90765a5bce506200fd328f3f49a1ce4819d8837c8d5e994839abf4a36bd3c8e2dc1cbff97d1990
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.2
5
+
6
+ gemfile:
7
+ - gemfiles/rails_42.gemfile
8
+ - gemfiles/rails_51.gemfile
9
+
10
+ script:
11
+ - bundle exec rake setup
12
+ - bundle exec rake
@@ -0,0 +1 @@
1
+ --no-private --protected lib/**/*.rb - README.md LICENSE
data/Gemfile CHANGED
@@ -14,4 +14,5 @@ group :test do
14
14
  gem 'rspec-mocks', '~> 3.7'
15
15
  gem 'rspec-rails', '~> 3.7'
16
16
  gem 'simplecov', require: false
17
+ gem 'codecov', require: false
17
18
  end
data/README.md CHANGED
@@ -1,23 +1,25 @@
1
1
  # Active Admin Xls
2
2
 
3
- Excel Spreadsheet Export for [Active Admin](https://www.activeadmin.info/)
3
+ Excel Spreadsheet Export for [Active Admin]
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/activeadmin-xls.svg)](https://badge.fury.io/rb/activeadmin-xls)
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]
6
10
 
7
11
  ## Synopsis
8
12
 
9
13
  This gem provides xls downloads for Active Admin resources.
10
14
 
11
- 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].
12
16
 
13
- Usage example:
17
+ ## Usage
14
18
 
15
- Add the following to your Gemfile and you are good to go.
16
- All resource index views will now include a link for download directly
17
- to xls.
19
+ Add the following to your Gemfile. All resource index views will now include a link for download directly to xls.
18
20
 
19
21
  ```ruby
20
- gem 'activeadmin-xls', '~>1.1.0'
22
+ gem 'activeadmin-xls', '~>2.0.0'
21
23
  ```
22
24
 
23
25
  For Active Admin 1.0, you will also have to update config/initializers/active_admin.rb. Update the download\_links setting to include xls:
@@ -26,6 +28,10 @@ For Active Admin 1.0, you will also have to update config/initializers/active_ad
26
28
  config.download_links = %i[csv xml json xls]
27
29
  ```
28
30
 
31
+ ## Dependencies
32
+
33
+ This gem depends on [spreadsheet] to generate xls files.
34
+
29
35
  ## Examples
30
36
 
31
37
  Here are a few quick examples of things you can easily tweak.
@@ -126,30 +132,46 @@ Running specs for this gem requires that you construct a rails application.
126
132
 
127
133
  To execute the specs, navigate to the gem directory, run bundle install and run these to rake tasks:
128
134
 
129
- ### Rails 3.2
135
+ ### Rails 4.2
130
136
 
131
137
  ```text
132
- bundle install --gemfile=gemfiles/rails_32.gemfile
138
+ bundle install --gemfile=gemfiles/rails_42.gemfile
133
139
  ```
134
140
 
135
141
  ```text
136
- BUNDLE_GEMFILE=gemfiles/rails_32.gemfile bundle exec rake setup
142
+ BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake setup
137
143
  ```
138
144
 
139
145
  ```text
140
- BUNDLE_GEMFILE=gemfiles/rails_32.gemfile bundle exec rake
146
+ BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake
141
147
  ```
142
148
 
143
- ### Rails 4.2
149
+ ### Rails 5.1
144
150
 
145
151
  ```text
146
- bundle install --gemfile=gemfiles/rails_42.gemfile
152
+ bundle install --gemfile=gemfiles/rails_51.gemfile
147
153
  ```
148
154
 
149
155
  ```text
150
- BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake setup
156
+ BUNDLE_GEMFILE=gemfiles/rails_51.gemfile bundle exec rake setup
151
157
  ```
152
158
 
153
159
  ```text
154
- BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake
160
+ BUNDLE_GEMFILE=gemfiles/rails_51.gemfile bundle exec rake
155
161
  ```
162
+
163
+ [Active Admin]:https://www.activeadmin.info/
164
+ [activeadmin-axlsx]:https://github.com/randym/activeadmin-axlsx
165
+ [to_xls]:https://github.com/splendeo/to_xls
166
+ [spreadsheet]:https://github.com/zdavatz/spreadsheet
167
+
168
+ [rubygems_badge]: https://img.shields.io/gem/v/activeadmin-xls.svg
169
+ [rubygems]: https://rubygems.org/gems/activeadmin-xls
170
+ [travis_badge]: https://img.shields.io/travis/thambley/activeadmin-xls/master.svg
171
+ [travis]: https://travis-ci.org/thambley/activeadmin-xls
172
+ [codeclimate_badge]: https://api.codeclimate.com/v1/badges/e294712bac54d4520182/maintainability
173
+ [codeclimate]: https://codeclimate.com/github/thambley/activeadmin-xls/maintainability
174
+ [codecov_badge]: https://codecov.io/gh/thambley/activeadmin-xls/branch/master/graph/badge.svg
175
+ [codecov]: https://codecov.io/gh/thambley/activeadmin-xls
176
+ [inch_badge]: http://inch-ci.org/github/thambley/activeadmin-xls.svg?branch=master
177
+ [inch]: http://inch-ci.org/github/thambley/activeadmin-xls
data/Rakefile CHANGED
@@ -5,8 +5,27 @@ require 'rspec/core/rake_task'
5
5
  desc 'Creates a test rails app for the specs to run against'
6
6
  task :setup do
7
7
  require 'rails/version'
8
- system('mkdir spec/rails') unless File.exist?('spec/rails')
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
@@ -21,9 +21,9 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.files = git_tracked_files - gem_ignored_files
23
23
 
24
- s.add_runtime_dependency 'activeadmin', '>= 0.6.6', '< 2'
24
+ s.add_runtime_dependency 'activeadmin', '>= 1.0.0', '< 2'
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
@@ -0,0 +1,22 @@
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', '1.2.1'
10
+ gem 'devise', '~> 4.2'
11
+ gem 'rails', '5.1.5'
12
+ gem 'turbolinks', '~> 5.0.0'
13
+ gem 'tzinfo-data'
14
+
15
+ group :test do
16
+ gem 'shoulda-matchers', '~> 3.1'
17
+ if ruby_major_version > 2 || (ruby_major_version == 2 && ruby_minor_version > 1)
18
+ gem 'test-unit', '~> 3.0'
19
+ end
20
+ end
21
+
22
+ 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::xls::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,8 +244,11 @@ module ActiveAdmin
138
244
  end
139
245
  end
140
246
 
141
- # remove all columns, and add columns by name
142
- # each column_name should be a symbol
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
143
252
  def only_columns(*column_names)
144
253
  clear_columns
145
254
  column_names.each do |column_name|
@@ -148,6 +257,9 @@ module ActiveAdmin
148
257
  end
149
258
 
150
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
151
263
  # @return [Spreadsheet::Workbook]
152
264
  def serialize(collection, view_context = nil)
153
265
  @collection = collection
@@ -159,15 +271,32 @@ module ActiveAdmin
159
271
  to_stream
160
272
  end
161
273
 
162
- # Xls column
274
+ # Xls column information
163
275
  class Column
276
+ # @param name [String, Symbol] Name of the column. If the name of the
277
+ # column is an existing attribute of the resource class, the value
278
+ # can be retreived automatically if no block is specified
279
+ # @param block [Proc] A procedure to generate data for the column
280
+ # instead of retreiving the value from the resource directly
164
281
  def initialize(name, block = nil)
165
282
  @name = name
166
283
  @data = block || @name
167
284
  end
168
285
 
169
- attr_reader :name, :data
286
+ # @return [String, Symbol] Column name
287
+ attr_reader :name
288
+
289
+ # @return [String, Symbol, Proc] The column name used to look up the
290
+ # value, or a block used to generate the value to display.
291
+ attr_reader :data
170
292
 
293
+ # Returns a localized version of the column name if a scope is given.
294
+ # Otherwise, it returns the titleized column name without translation.
295
+ #
296
+ # @param i18n_scope [String, Symbol, Array<String>, Array<Symbol>]
297
+ # Translation scope. If not provided, the column name will be used.
298
+ #
299
+ # @see I18n
171
300
  def localized_name(i18n_scope = nil)
172
301
  return name.to_s.titleize unless i18n_scope
173
302
  I18n.t name, scope: i18n_scope
@@ -1,6 +1,6 @@
1
1
  module ActiveAdmin
2
2
  module Xls
3
- # extends activeadmin dsl to include xls
3
+ # Extends activeadmin dsl to include xls
4
4
  module DSL
5
5
  delegate(:after_filter,
6
6
  :before_filter,
@@ -15,6 +15,53 @@ module ActiveAdmin
15
15
  to: :xls_builder,
16
16
  prefix: :config)
17
17
 
18
+ # Creates a default XLS Builder to respond to xls requests for this
19
+ # resource. Options are passed to the Builder initialize method.
20
+ #
21
+ # @param [Hash] options the options for the builder
22
+ # @option options [Hash] :header_format a hash of format properties to
23
+ # apply to the header row. Any properties specified will be merged with
24
+ # the default header styles.
25
+ # @option options [Array] :i18n_scope the I18n scope to use when looking
26
+ # up localized column headers.
27
+ # @param [Block] block block given will evaluated against the instance of
28
+ # Builder. That means you can call any method on the builder from within
29
+ # that block.
30
+ # @return A new instance of Builder
31
+ #
32
+ # @example Using the DSL
33
+ # xls(i18n_scope: [:active_admin, :xls, :post],
34
+ # header_format: { weight: :bold, color: :blue }) do
35
+ # # Specify that you want to white list column output.
36
+ # # whitelist
37
+ #
38
+ # # Do not serialize the header, only output data.
39
+ # # skip_header
40
+ #
41
+ # # restrict columns to a list without customization
42
+ # # only_columns :title, :author
43
+ #
44
+ # # deleting columns from the report
45
+ # delete_columns :id, :created_at, :updated_at
46
+ #
47
+ # # adding a column to the report with customization
48
+ # column(:author) do |post|
49
+ # "#{post.author.first_name} #{post.author.last_name}"
50
+ # end
51
+ #
52
+ # # inserting additional data with after_filter
53
+ # after_filter do |sheet|
54
+ # # todo
55
+ # end
56
+ #
57
+ # # inserting data with before_filter
58
+ # before_filter do |sheet|
59
+ # # todo
60
+ # end
61
+ # end
62
+ #
63
+ # @see Builder
64
+ # @see https://github.com/zdavatz/spreadsheet/blob/master/lib/spreadsheet/format.rb
18
65
  def xls(options = {}, &block)
19
66
  config.xls_builder = ActiveAdmin::Xls::Builder.new(
20
67
  config.resource_class,
@@ -1,6 +1,6 @@
1
1
  module ActiveAdmin
2
2
  module Xls
3
- # extends activeadmin with xls downloads
3
+ # Extends ActiveAdmin with xls downloads
4
4
  class Engine < ::Rails::Engine
5
5
  engine_name 'active_admin_xls'
6
6
 
@@ -14,7 +14,7 @@ module ActiveAdmin
14
14
  ActiveAdmin::ResourceDSL.send :include, ActiveAdmin::Xls::DSL
15
15
  ActiveAdmin::Resource.send :include, ActiveAdmin::Xls::ResourceExtension
16
16
  ActiveAdmin::ResourceController.send(
17
- :include,
17
+ :prepend,
18
18
  ActiveAdmin::Xls::ResourceControllerExtension
19
19
  )
20
20
  end
@@ -1,25 +1,19 @@
1
1
  module ActiveAdmin
2
2
  module Xls
3
+ # Extends the resource controller to respond to xls requests
3
4
  module ResourceControllerExtension
4
- def self.included(base)
5
- base.send :alias_method_chain, :per_page, :xls
6
- base.send :alias_method_chain, :index, :xls
7
- base.send :alias_method_chain, :rescue_active_admin_access_denied, :xls
8
- base.send :respond_to, :xls
5
+ def self.prepended(base)
6
+ base.send :respond_to, :xls, only: :index
9
7
  end
10
8
 
11
- def index_with_xls
12
- index_without_xls do |format|
9
+ # Patches index to respond to requests with xls mime type by
10
+ # sending a generated xls document serializing the current
11
+ # collection
12
+ def index
13
+ super do |format|
13
14
  format.xls do
14
- xls_collection = if method(:find_collection).arity.zero?
15
- collection
16
- else
17
- find_collection except: :pagination
18
- end
19
- xls = active_admin_config.xls_builder.serialize(
20
- xls_collection,
21
- view_context
22
- )
15
+ xls = active_admin_config.xls_builder.serialize(xls_collection,
16
+ view_context)
23
17
  send_data(xls,
24
18
  filename: xls_filename,
25
19
  type: Mime::Type.lookup_by_extension(:xls))
@@ -29,7 +23,12 @@ module ActiveAdmin
29
23
  end
30
24
  end
31
25
 
32
- def rescue_active_admin_access_denied_with_xls(exception)
26
+ # Patches rescue_active_admin_access_denied to respond to xls
27
+ # mime type. Provides administrators information on how to
28
+ # configure activeadmin to respond propertly to xls requests
29
+ #
30
+ # param exception [Exception] unauthorized access error
31
+ def rescue_active_admin_access_denied(exception)
33
32
  if request.format == Mime::Type.lookup_by_extension(:xls)
34
33
  respond_to do |format|
35
34
  format.xls do
@@ -38,27 +37,25 @@ module ActiveAdmin
38
37
  end
39
38
  end
40
39
  else
41
- rescue_active_admin_access_denied_without_xls(exception)
40
+ super(exception)
42
41
  end
43
42
  end
44
43
 
45
- # patch per_page to use the CSV record max for pagination
46
- # when the format is xls
47
- def per_page_with_xls
48
- if request.format == Mime::Type.lookup_by_extension(:xls)
49
- return max_per_page if respond_to?(:max_per_page, true)
50
- active_admin_config.max_per_page
51
- end
52
-
53
- per_page_without_xls
54
- end
55
-
56
44
  # Returns a filename for the xls file using the collection_name
57
45
  # and current date such as 'my-articles-2011-06-24.xls'.
46
+ #
47
+ # @return [String] with default filename
58
48
  def xls_filename
59
49
  timestamp = Time.now.strftime('%Y-%m-%d')
60
50
  "#{resource_collection_name.to_s.tr('_', '-')}-#{timestamp}.xls"
61
51
  end
52
+
53
+ # Returns the collection to use when generating an xls file.
54
+ # It uses the find_collection function if it is available, and uses
55
+ # collection if find_collection isn't available.
56
+ def xls_collection
57
+ find_collection except: :pagination
58
+ end
62
59
  end
63
60
  end
64
61
  end
@@ -1,10 +1,25 @@
1
1
  module ActiveAdmin
2
+ # Provides xls functionality to ActiveAdmin resources
2
3
  module Xls
4
+ # Extends ActiveAdmin Resource
3
5
  module ResourceExtension
6
+ # Sets the XLS Builder
7
+ #
8
+ # @param builder [Builder] the new builder object
9
+ # @return [Builder] the builder for this resource
4
10
  def xls_builder=(builder)
5
11
  @xls_builder = builder
6
12
  end
7
13
 
14
+ # Returns the XLS Builder. Creates a new Builder if none exists.
15
+ #
16
+ # @return [Builder] the builder for this resource
17
+ #
18
+ # @example Localize column headers
19
+ # # app/admin/posts.rb
20
+ # ActiveAdmin.register Post do
21
+ # config.xls_builder.i18n_scope = [:active_record, :models, :posts]
22
+ # end
8
23
  def xls_builder
9
24
  @xls_builder ||= ActiveAdmin::Xls::Builder.new(resource_class)
10
25
  end
@@ -1,5 +1,6 @@
1
1
  module ActiveAdmin
2
2
  module Xls
3
- VERSION = '1.1.0'.freeze
3
+ # ActiveAdmin XLS gem version
4
+ VERSION = '2.0.0'.freeze
4
5
  end
5
6
  end
File without changes
@@ -4,6 +4,14 @@ SimpleCov.start do
4
4
  add_filter '/spec/'
5
5
  end
6
6
 
7
+ if ENV['CI'] == 'true'
8
+ require 'codecov'
9
+ SimpleCov.formatters = [
10
+ SimpleCov::Formatter::HTMLFormatter,
11
+ SimpleCov::Formatter::Codecov
12
+ ]
13
+ end
14
+
7
15
  ENV['RAILS_ENV'] = 'test'
8
16
 
9
17
  # prepare ENV for rails
@@ -16,24 +16,51 @@ gsub_file(
16
16
  "\ncucumber_with_reloading:\n <<: *test\n database: db/cucumber.sqlite3"
17
17
  )
18
18
 
19
+ if File.exist?('config/secrets.yml')
20
+ require 'securerandom'
21
+ cucumber_secret = SecureRandom.hex(64)
22
+ gsub_file 'config/secrets.yml',
23
+ /\z/,
24
+ "\ncucumber:\n secret_key_base: #{cucumber_secret}"
25
+ end
26
+
27
+ base_record = if Rails::VERSION::MAJOR >= 5
28
+ 'ApplicationRecord'
29
+ else
30
+ 'ActiveRecord::Base'
31
+ end
32
+
19
33
  # Generate some test models
20
34
  generate :model, 'post title:string body:text published_at:datetime author_id:integer category_id:integer'
21
- inject_into_file 'app/models/post.rb', " belongs_to :author, class_name: 'User'\n belongs_to :category\n accepts_nested_attributes_for :author\n", after: "class Post < ActiveRecord::Base\n"
22
- # Rails 3.2.3 model generator declare attr_accessible
23
- if Rails::VERSION::MAJOR == 3
24
- inject_into_file 'app/models/post.rb',
25
- " attr_accessible :author\n",
26
- before: 'end'
27
- end
35
+ post_model_setup = if Rails::VERSION::MAJOR >= 5
36
+ <<-MODEL
37
+ belongs_to :author, class_name: 'User'
38
+ belongs_to :category, optional: true
39
+ accepts_nested_attributes_for :author
40
+ MODEL
41
+ else
42
+ <<-MODEL
43
+ belongs_to :author, class_name: 'User'
44
+ belongs_to :category
45
+ accepts_nested_attributes_for :author
46
+ MODEL
47
+ end
48
+ inject_into_file 'app/models/post.rb',
49
+ post_model_setup,
50
+ after: "class Post < #{base_record}\n"
51
+
28
52
  generate :model, 'user type:string first_name:string last_name:string username:string age:integer'
29
53
  inject_into_file 'app/models/user.rb',
30
54
  " has_many :posts, foreign_key: 'author_id'\n",
31
- after: "class User < ActiveRecord::Base\n"
55
+ after: "class User < #{base_record}\n"
56
+
32
57
  generate :model, 'publisher --migration=false --parent=User'
58
+
33
59
  generate :model, 'category name:string description:text'
34
60
  inject_into_file 'app/models/category.rb',
35
61
  " has_many :posts\n accepts_nested_attributes_for :posts\n",
36
- after: "class Category < ActiveRecord::Base\n"
62
+ after: "class Category < #{base_record}\n"
63
+
37
64
  generate :model, 'store name:string'
38
65
 
39
66
  # Generate a model with string ids
@@ -57,13 +84,7 @@ MODEL
57
84
 
58
85
  inject_into_file 'app/models/tag.rb',
59
86
  id_model_setup,
60
- after: "class Tag < ActiveRecord::Base\n"
61
-
62
- if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 1 # Rails 3.1 Gotcha
63
- gsub_file 'app/models/tag.rb',
64
- /self\.primary_key.*$/,
65
- 'define_attr_method :primary_key, :id'
66
- end
87
+ after: "class Tag < #{base_record}\n"
67
88
 
68
89
  # Configure default_url_options in test environment
69
90
  inject_into_file(
@@ -86,27 +107,17 @@ append_file 'config/locales/en.yml',
86
107
  directory File.expand_path('../templates/admin', __FILE__), 'app/admin'
87
108
 
88
109
  run 'rm Gemfile'
89
- run 'rm -r test'
90
- run 'rm -r spec'
91
110
 
92
111
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
93
112
 
94
- if Rails::VERSION::MAJOR == 3
95
- # we need this routing path, named "logout_path", for testing
96
- route <<-ROUTE
97
- devise_scope :user do
98
- match '/admin/logout' => 'active_admin/devise/sessions#destroy', as: :logout
99
- end
100
- ROUTE
101
- end
102
-
103
113
  generate :'active_admin:install'
104
114
 
105
- if Rails::VERSION::MAJOR > 3
106
- inject_into_file 'config/initializers/active_admin.rb',
107
- " config.download_links = %i[csv xml json xls]\n",
108
- after: " # == Download Links\n"
109
- end
115
+ run 'rm -r test'
116
+ run 'rm -r spec'
117
+
118
+ inject_into_file 'config/initializers/active_admin.rb',
119
+ " config.download_links = %i[csv xml json xls]\n",
120
+ after: " # == Download Links\n"
110
121
 
111
122
  # Setup a root path for devise
112
123
  route "root to: 'admin/dashboard#index'"
@@ -1,22 +1,7 @@
1
1
  require 'spec_helper'
2
- describe ActiveAdmin::ResourceController do
2
+ describe Admin::CategoriesController, type: :controller do
3
3
  let(:mime) { Mime::Type.lookup_by_extension(:xls) }
4
4
 
5
- let(:request) do
6
- ActionController::TestRequest.new.tap do |test_request|
7
- test_request.accept = mime
8
- end
9
- end
10
-
11
- let(:response) { ActionController::TestResponse.new }
12
-
13
- let(:controller) do
14
- Admin::CategoriesController.new.tap do |controller|
15
- controller.request = request
16
- controller.response = response
17
- end
18
- end
19
-
20
5
  let(:filename) do
21
6
  "#{controller.resource_class.to_s.downcase.pluralize}-#{Time.now.strftime('%Y-%m-%d')}.xls"
22
7
  end
@@ -27,26 +12,11 @@ describe ActiveAdmin::ResourceController do
27
12
 
28
13
  context 'when making requests with the xls mime type' do
29
14
  it 'returns xls attachment when requested' do
30
- controller.send :index
15
+ request.accept = mime
16
+ get :index
31
17
  disposition = "attachment; filename=\"#{filename}\""
32
18
  expect(response.headers['Content-Disposition']).to eq(disposition)
33
19
  expect(response.headers['Content-Transfer-Encoding']).to eq('binary')
34
20
  end
35
-
36
- it 'returns max_csv_records for per_page' do
37
- # this might need to go away!
38
- max_csv_records = if controller.respond_to?(:max_csv_records, true)
39
- controller.send(:max_csv_records)
40
- else
41
- controller.send(:per_page)
42
- end
43
- expect(controller.send(:per_page)).to eq(max_csv_records)
44
- end
45
-
46
- it 'uses the default per_page when we do not specify xls mime type' do
47
- controller.request.accept = 'text/html'
48
- aa_default_per_page = ActiveAdmin.application.default_per_page
49
- expect(controller.send(:per_page)).to eq(aa_default_per_page)
50
- end
51
21
  end
52
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeadmin-xls
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Hambley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-27 00:00:00.000000000 Z
11
+ date: 2018-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeadmin
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.6
19
+ version: 1.0.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '2'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 0.6.6
29
+ version: 1.0.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2'
@@ -55,15 +55,16 @@ files:
55
55
  - ".gemignore"
56
56
  - ".gitignore"
57
57
  - ".rspec"
58
- - ".yardops"
58
+ - ".travis.yml"
59
+ - ".yardopts"
59
60
  - CHANGELOG.md
60
61
  - Gemfile
61
62
  - LICENSE
62
63
  - README.md
63
64
  - Rakefile
64
65
  - activeadmin-xls.gemspec
65
- - gemfiles/rails_32.gemfile
66
66
  - gemfiles/rails_42.gemfile
67
+ - gemfiles/rails_51.gemfile
67
68
  - lib/active_admin/xls/builder.rb
68
69
  - lib/active_admin/xls/dsl.rb
69
70
  - lib/active_admin/xls/engine.rb
@@ -71,6 +72,7 @@ files:
71
72
  - lib/active_admin/xls/resource_extension.rb
72
73
  - lib/active_admin/xls/version.rb
73
74
  - lib/activeadmin-xls.rb
75
+ - spec/rails_helper.rb
74
76
  - spec/spec_helper.rb
75
77
  - spec/support/rails_template.rb
76
78
  - spec/support/rails_template_with_data.rb
@@ -95,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
97
  requirements:
96
98
  - - ">="
97
99
  - !ruby/object:Gem::Version
98
- version: 1.9.2
100
+ version: 2.0.0
99
101
  required_rubygems_version: !ruby/object:Gem::Requirement
100
102
  requirements:
101
103
  - - ">="
data/.yardops DELETED
@@ -1 +0,0 @@
1
- --no-private --protected app/**/*.rb - README.md LEGAL
@@ -1,30 +0,0 @@
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 'rails', '3.2.22.5'
10
-
11
- gem 'activeadmin', '0.6.6'
12
-
13
- group :assets do
14
- gem 'coffee-rails', '~> 3.2.1'
15
- gem 'sass-rails', '~> 3.2.3'
16
-
17
- # See https://github.com/sstephenson/execjs#readme for more supported runtimes
18
- # gem 'therubyracer', :platforms => :ruby
19
-
20
- gem 'uglifier', '>= 1.0.3'
21
- end
22
-
23
- group :test do
24
- gem 'shoulda-matchers', '~> 2.8.0'
25
- if ruby_major_version > 2 || (ruby_major_version == 2 && ruby_minor_version > 1)
26
- gem 'test-unit', '~> 3.0'
27
- end
28
- end
29
-
30
- gemspec path: "../"