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 +4 -4
- data/.travis.yml +12 -0
- data/.yardopts +1 -0
- data/Gemfile +1 -0
- data/README.md +38 -16
- data/Rakefile +21 -2
- data/activeadmin-xls.gemspec +2 -2
- data/gemfiles/rails_51.gemfile +22 -0
- data/lib/active_admin/xls/builder.rb +158 -29
- data/lib/active_admin/xls/dsl.rb +48 -1
- data/lib/active_admin/xls/engine.rb +2 -2
- data/lib/active_admin/xls/resource_controller_extension.rb +26 -29
- data/lib/active_admin/xls/resource_extension.rb +15 -0
- data/lib/active_admin/xls/version.rb +2 -1
- data/spec/rails_helper.rb +0 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/rails_template.rb +43 -32
- data/spec/xls/unit/resource_controller_spec.rb +3 -33
- metadata +9 -7
- data/.yardops +0 -1
- data/gemfiles/rails_32.gemfile +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0061e54090d183ee6259739d20d7db62eb890790
|
4
|
+
data.tar.gz: 7691fe01a10bcdd3aac3239f690ae98f95258460
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 522ac0e6309ad124d216acdd64228efec606836dd75369f90b9f8e2e806e017c658190a841c56bf54b3e77fe72bd3b5cac00be571db3602745a22f432855f33d
|
7
|
+
data.tar.gz: ffab449bd41cfb19b97d5b879d656f531a2cde929e98a5188b90765a5bce506200fd328f3f49a1ce4819d8837c8d5e994839abf4a36bd3c8e2dc1cbff97d1990
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private --protected lib/**/*.rb - README.md LICENSE
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,23 +1,25 @@
|
|
1
1
|
# Active Admin Xls
|
2
2
|
|
3
|
-
Excel Spreadsheet Export for [Active Admin]
|
3
|
+
Excel Spreadsheet Export for [Active Admin]
|
4
4
|
|
5
|
-
[![
|
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 [
|
15
|
+
This gem borrows heavily from [activeadmin-axlsx] and [to_xls].
|
12
16
|
|
13
|
-
Usage
|
17
|
+
## Usage
|
14
18
|
|
15
|
-
Add the following to your Gemfile
|
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', '~>
|
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
|
135
|
+
### Rails 4.2
|
130
136
|
|
131
137
|
```text
|
132
|
-
bundle install --gemfile=gemfiles/
|
138
|
+
bundle install --gemfile=gemfiles/rails_42.gemfile
|
133
139
|
```
|
134
140
|
|
135
141
|
```text
|
136
|
-
BUNDLE_GEMFILE=gemfiles/
|
142
|
+
BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake setup
|
137
143
|
```
|
138
144
|
|
139
145
|
```text
|
140
|
-
BUNDLE_GEMFILE=gemfiles/
|
146
|
+
BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake
|
141
147
|
```
|
142
148
|
|
143
|
-
### Rails
|
149
|
+
### Rails 5.1
|
144
150
|
|
145
151
|
```text
|
146
|
-
bundle install --gemfile=gemfiles/
|
152
|
+
bundle install --gemfile=gemfiles/rails_51.gemfile
|
147
153
|
```
|
148
154
|
|
149
155
|
```text
|
150
|
-
BUNDLE_GEMFILE=gemfiles/
|
156
|
+
BUNDLE_GEMFILE=gemfiles/rails_51.gemfile bundle exec rake setup
|
151
157
|
```
|
152
158
|
|
153
159
|
```text
|
154
|
-
BUNDLE_GEMFILE=gemfiles/
|
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
|
-
|
9
|
-
|
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
|
data/activeadmin-xls.gemspec
CHANGED
@@ -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.
|
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 = '>=
|
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
|
13
|
-
# @option [Hash] :header_format
|
14
|
-
# to the header row. Any properties specified will be merged with
|
15
|
-
# default header styles.
|
16
|
-
# @option [Array] :i18n_scope
|
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]
|
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
|
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
|
26
|
-
#
|
27
|
-
#
|
25
|
+
# after_filter do |sheet|
|
26
|
+
# # todo
|
27
|
+
# end
|
28
28
|
# end
|
29
|
-
#
|
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
|
-
#
|
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
|
65
|
-
#
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
129
|
-
#
|
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
|
-
#
|
142
|
-
#
|
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
|
-
|
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
|
data/lib/active_admin/xls/dsl.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module ActiveAdmin
|
2
2
|
module Xls
|
3
|
-
#
|
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
|
-
#
|
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
|
-
:
|
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.
|
5
|
-
base.send :
|
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
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
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
|
-
|
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
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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 <
|
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 <
|
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 <
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
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
|
-
|
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:
|
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-
|
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.
|
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.
|
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
|
-
- ".
|
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:
|
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
|
data/gemfiles/rails_32.gemfile
DELETED
@@ -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: "../"
|