activeadmin-xls 1.1.0 → 2.0.0
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 +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: "../"
|