activeadmin-axlsx 1.0.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.
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/Gemfile +4 -4
- data/Gemfile.lock +52 -43
- data/README.md +70 -7
- data/Rakefile +0 -1
- data/lib/active_admin/axlsx.rb +2 -3
- data/lib/active_admin/axlsx/build_download_format_links.rb +2 -0
- data/lib/active_admin/axlsx/builder.rb +140 -69
- data/lib/active_admin/axlsx/dsl.rb +3 -15
- data/lib/active_admin/axlsx/resource_controller_extension.rb +4 -2
- data/lib/active_admin/axlsx/resource_extension.rb +1 -7
- data/lib/active_admin/axlsx/version.rb +1 -1
- data/spec/axlsx/unit/build_download_format_links_spec.rb +48 -0
- data/spec/axlsx/unit/builder_spec.rb +97 -18
- data/spec/axlsx/unit/dsl_spec.rb +46 -0
- data/spec/axlsx/unit/resource_controller_spec.rb +46 -0
- data/spec/axlsx/unit/resource_spec.rb +10 -18
- data/spec/spec_helper.rb +14 -12
- data/spec/support/rails_template.rb +1 -1
- data/spec/support/rails_template_with_data.rb +2 -1
- data/spec/support/templates/en.yml +9 -0
- metadata +10 -4
- data/lib/active_admin/axlsx/autoload_extension.rb +0 -7
data/.gitignore
CHANGED
data/.rspec
ADDED
data/Gemfile
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
|
-
|
|
2
|
+
gem 'axlsx'
|
|
3
3
|
gemspec
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
group :development, :test do
|
|
6
6
|
gem 'sqlite3'
|
|
7
|
-
|
|
8
7
|
gem 'rake', '~> 0.9.2.2', :require => false
|
|
9
8
|
gem 'haml', '~> 3.1.1', :require => false
|
|
10
9
|
gem 'yard'
|
|
@@ -12,10 +11,11 @@ group :development, :test do
|
|
|
12
11
|
gem "sprockets"
|
|
13
12
|
gem 'rails-i18n' # Gives us default i18n for many languages
|
|
14
13
|
end
|
|
15
|
-
|
|
14
|
+
gem 'simplecov', :require => false, :group => :test
|
|
16
15
|
group :test do
|
|
17
16
|
gem 'inherited_resources'
|
|
18
17
|
gem 'sass-rails'
|
|
18
|
+
gem 'rspec-mocks'
|
|
19
19
|
gem 'rspec-rails', '~> 2.9.0'
|
|
20
20
|
gem 'cucumber-rails', '1.2.1', :require => false
|
|
21
21
|
gem 'capybara', '1.1.2'
|
data/Gemfile.lock
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
activeadmin-axlsx (
|
|
4
|
+
activeadmin-axlsx (2.0.0)
|
|
5
5
|
activeadmin (>= 0.5.0)
|
|
6
6
|
axlsx
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
actionmailer (3.2.
|
|
12
|
-
actionpack (= 3.2.
|
|
11
|
+
actionmailer (3.2.9)
|
|
12
|
+
actionpack (= 3.2.9)
|
|
13
13
|
mail (~> 2.4.4)
|
|
14
|
-
actionpack (3.2.
|
|
15
|
-
activemodel (= 3.2.
|
|
16
|
-
activesupport (= 3.2.
|
|
14
|
+
actionpack (3.2.9)
|
|
15
|
+
activemodel (= 3.2.9)
|
|
16
|
+
activesupport (= 3.2.9)
|
|
17
17
|
builder (~> 3.0.0)
|
|
18
18
|
erubis (~> 2.7.0)
|
|
19
19
|
journey (~> 1.0.4)
|
|
20
20
|
rack (~> 1.4.0)
|
|
21
21
|
rack-cache (~> 1.2)
|
|
22
22
|
rack-test (~> 0.6.1)
|
|
23
|
-
sprockets (~> 2.1
|
|
23
|
+
sprockets (~> 2.2.1)
|
|
24
24
|
activeadmin (0.5.0)
|
|
25
25
|
arbre (>= 1.0.1)
|
|
26
26
|
bourbon (>= 1.0.0)
|
|
@@ -33,18 +33,18 @@ GEM
|
|
|
33
33
|
meta_search (>= 0.9.2)
|
|
34
34
|
rails (>= 3.0.0)
|
|
35
35
|
sass (>= 3.1.0)
|
|
36
|
-
activemodel (3.2.
|
|
37
|
-
activesupport (= 3.2.
|
|
36
|
+
activemodel (3.2.9)
|
|
37
|
+
activesupport (= 3.2.9)
|
|
38
38
|
builder (~> 3.0.0)
|
|
39
|
-
activerecord (3.2.
|
|
40
|
-
activemodel (= 3.2.
|
|
41
|
-
activesupport (= 3.2.
|
|
39
|
+
activerecord (3.2.9)
|
|
40
|
+
activemodel (= 3.2.9)
|
|
41
|
+
activesupport (= 3.2.9)
|
|
42
42
|
arel (~> 3.0.2)
|
|
43
43
|
tzinfo (~> 0.3.29)
|
|
44
|
-
activeresource (3.2.
|
|
45
|
-
activemodel (= 3.2.
|
|
46
|
-
activesupport (= 3.2.
|
|
47
|
-
activesupport (3.2.
|
|
44
|
+
activeresource (3.2.9)
|
|
45
|
+
activemodel (= 3.2.9)
|
|
46
|
+
activesupport (= 3.2.9)
|
|
47
|
+
activesupport (3.2.9)
|
|
48
48
|
i18n (~> 0.6)
|
|
49
49
|
multi_json (~> 1.0)
|
|
50
50
|
addressable (2.3.2)
|
|
@@ -56,8 +56,9 @@ GEM
|
|
|
56
56
|
nokogiri (>= 1.4.1)
|
|
57
57
|
rubyzip (>= 0.9.5)
|
|
58
58
|
bcrypt-ruby (3.0.1)
|
|
59
|
-
bourbon (2.1.
|
|
60
|
-
sass (>= 3.
|
|
59
|
+
bourbon (2.1.2)
|
|
60
|
+
sass (>= 3.2)
|
|
61
|
+
thor
|
|
61
62
|
builder (3.0.4)
|
|
62
63
|
capybara (1.1.2)
|
|
63
64
|
mime-types (>= 1.16)
|
|
@@ -84,13 +85,13 @@ GEM
|
|
|
84
85
|
cucumber (>= 1.1.3)
|
|
85
86
|
nokogiri (>= 1.5.0)
|
|
86
87
|
database_cleaner (0.9.1)
|
|
87
|
-
debugger (1.2.
|
|
88
|
+
debugger (1.2.2)
|
|
88
89
|
columnize (>= 0.3.1)
|
|
89
90
|
debugger-linecache (~> 1.1.1)
|
|
90
|
-
debugger-ruby_core_source (~> 1.1.
|
|
91
|
+
debugger-ruby_core_source (~> 1.1.5)
|
|
91
92
|
debugger-linecache (1.1.2)
|
|
92
93
|
debugger-ruby_core_source (>= 1.1.1)
|
|
93
|
-
debugger-ruby_core_source (1.1.
|
|
94
|
+
debugger-ruby_core_source (1.1.5)
|
|
94
95
|
devise (2.1.2)
|
|
95
96
|
bcrypt-ruby (~> 3.0)
|
|
96
97
|
orm_adapter (~> 0.1)
|
|
@@ -101,17 +102,17 @@ GEM
|
|
|
101
102
|
execjs (1.4.0)
|
|
102
103
|
multi_json (~> 1.0)
|
|
103
104
|
fastercsv (1.5.5)
|
|
104
|
-
ffi (1.
|
|
105
|
+
ffi (1.2.0)
|
|
105
106
|
formtastic (2.2.1)
|
|
106
107
|
actionpack (>= 3.0)
|
|
107
108
|
gherkin (2.11.5)
|
|
108
109
|
json (>= 1.4.6)
|
|
109
|
-
guard (1.5.
|
|
110
|
+
guard (1.5.4)
|
|
110
111
|
listen (>= 0.4.2)
|
|
111
112
|
lumberjack (>= 1.0.2)
|
|
112
113
|
pry (>= 0.9.10)
|
|
113
114
|
thor (>= 0.14.6)
|
|
114
|
-
guard-coffeescript (1.2.
|
|
115
|
+
guard-coffeescript (1.2.1)
|
|
115
116
|
coffee-script (>= 2.2.0)
|
|
116
117
|
guard (>= 1.1.0)
|
|
117
118
|
guard-rspec (1.2.1)
|
|
@@ -141,8 +142,8 @@ GEM
|
|
|
141
142
|
activesupport (>= 3.0.0)
|
|
142
143
|
launchy (2.1.2)
|
|
143
144
|
addressable (~> 2.3)
|
|
144
|
-
libwebsocket (0.1.
|
|
145
|
-
|
|
145
|
+
libwebsocket (0.1.6.1)
|
|
146
|
+
websocket
|
|
146
147
|
listen (0.5.3)
|
|
147
148
|
lumberjack (1.0.2)
|
|
148
149
|
mail (2.4.4)
|
|
@@ -156,7 +157,7 @@ GEM
|
|
|
156
157
|
polyamorous (~> 0.5.0)
|
|
157
158
|
method_source (0.8.1)
|
|
158
159
|
mime-types (1.19)
|
|
159
|
-
multi_json (1.3.
|
|
160
|
+
multi_json (1.3.7)
|
|
160
161
|
nokogiri (1.5.5)
|
|
161
162
|
orm_adapter (0.4.0)
|
|
162
163
|
polyamorous (0.5.0)
|
|
@@ -173,19 +174,19 @@ GEM
|
|
|
173
174
|
rack
|
|
174
175
|
rack-test (0.6.2)
|
|
175
176
|
rack (>= 1.0)
|
|
176
|
-
rails (3.2.
|
|
177
|
-
actionmailer (= 3.2.
|
|
178
|
-
actionpack (= 3.2.
|
|
179
|
-
activerecord (= 3.2.
|
|
180
|
-
activeresource (= 3.2.
|
|
181
|
-
activesupport (= 3.2.
|
|
177
|
+
rails (3.2.9)
|
|
178
|
+
actionmailer (= 3.2.9)
|
|
179
|
+
actionpack (= 3.2.9)
|
|
180
|
+
activerecord (= 3.2.9)
|
|
181
|
+
activeresource (= 3.2.9)
|
|
182
|
+
activesupport (= 3.2.9)
|
|
182
183
|
bundler (~> 1.0)
|
|
183
|
-
railties (= 3.2.
|
|
184
|
+
railties (= 3.2.9)
|
|
184
185
|
rails-i18n (0.7.0)
|
|
185
186
|
i18n (~> 0.5)
|
|
186
|
-
railties (3.2.
|
|
187
|
-
actionpack (= 3.2.
|
|
188
|
-
activesupport (= 3.2.
|
|
187
|
+
railties (3.2.9)
|
|
188
|
+
actionpack (= 3.2.9)
|
|
189
|
+
activesupport (= 3.2.9)
|
|
189
190
|
rack-ssl (~> 1.3.2)
|
|
190
191
|
rake (>= 0.8.7)
|
|
191
192
|
rdoc (~> 3.4)
|
|
@@ -210,31 +211,37 @@ GEM
|
|
|
210
211
|
railties (>= 3.0)
|
|
211
212
|
rspec (~> 2.9.0)
|
|
212
213
|
rubyzip (0.9.9)
|
|
213
|
-
sass (3.2.
|
|
214
|
+
sass (3.2.3)
|
|
214
215
|
sass-rails (3.2.5)
|
|
215
216
|
railties (~> 3.2.0)
|
|
216
217
|
sass (>= 3.1.10)
|
|
217
218
|
tilt (~> 1.3)
|
|
218
|
-
selenium-webdriver (2.
|
|
219
|
+
selenium-webdriver (2.26.0)
|
|
219
220
|
childprocess (>= 0.2.5)
|
|
220
221
|
libwebsocket (~> 0.1.3)
|
|
221
222
|
multi_json (~> 1.0)
|
|
222
223
|
rubyzip
|
|
223
224
|
shoulda-matchers (1.0.0)
|
|
225
|
+
simplecov (0.7.1)
|
|
226
|
+
multi_json (~> 1.0)
|
|
227
|
+
simplecov-html (~> 0.7.1)
|
|
228
|
+
simplecov-html (0.7.1)
|
|
224
229
|
slop (3.3.3)
|
|
225
|
-
sprockets (2.1
|
|
230
|
+
sprockets (2.2.1)
|
|
226
231
|
hike (~> 1.2)
|
|
232
|
+
multi_json (~> 1.0)
|
|
227
233
|
rack (~> 1.0)
|
|
228
234
|
tilt (~> 1.1, != 1.3.0)
|
|
229
235
|
sqlite3 (1.3.6)
|
|
230
236
|
thor (0.16.0)
|
|
231
237
|
tilt (1.3.3)
|
|
232
|
-
treetop (1.4.
|
|
238
|
+
treetop (1.4.12)
|
|
233
239
|
polyglot
|
|
234
240
|
polyglot (>= 0.3.1)
|
|
235
|
-
tzinfo (0.3.
|
|
241
|
+
tzinfo (0.3.35)
|
|
236
242
|
warden (1.2.1)
|
|
237
243
|
rack (>= 1.0)
|
|
244
|
+
websocket (1.0.3)
|
|
238
245
|
xpath (0.1.4)
|
|
239
246
|
nokogiri (~> 1.3)
|
|
240
247
|
yard (0.8.3)
|
|
@@ -243,8 +250,8 @@ PLATFORMS
|
|
|
243
250
|
ruby
|
|
244
251
|
|
|
245
252
|
DEPENDENCIES
|
|
246
|
-
activeadmin
|
|
247
253
|
activeadmin-axlsx!
|
|
254
|
+
axlsx
|
|
248
255
|
capybara (= 1.1.2)
|
|
249
256
|
cucumber-rails (= 1.2.1)
|
|
250
257
|
database_cleaner
|
|
@@ -259,9 +266,11 @@ DEPENDENCIES
|
|
|
259
266
|
rails-i18n
|
|
260
267
|
rake (~> 0.9.2.2)
|
|
261
268
|
rdiscount
|
|
269
|
+
rspec-mocks
|
|
262
270
|
rspec-rails (~> 2.9.0)
|
|
263
271
|
sass-rails
|
|
264
272
|
shoulda-matchers (= 1.0.0)
|
|
273
|
+
simplecov
|
|
265
274
|
sprockets
|
|
266
275
|
sqlite3
|
|
267
276
|
yard
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Active Admin Axlsx: Office Open XML Spreadsheet Export for Active Admin
|
|
2
2
|
====================================
|
|
3
3
|
|
|
4
|
-
If you are using this for
|
|
4
|
+
If you are using this for commercial purposes, or just want to show your
|
|
5
5
|
appreciation for the gem, please don't hesitate to make a donation.
|
|
6
6
|
|
|
7
7
|
[](http://www.pledgie.com/campaigns/17814)
|
|
@@ -38,12 +38,10 @@ resources. It lets you harness the full power of Axlsx when you want to
|
|
|
38
38
|
but for the most part just stays out of your way and adds a link next to
|
|
39
39
|
the csv download for xlsx (Excel/numbers/Libre Office/Google Docs)
|
|
40
40
|
|
|
41
|
-
git ls-files -- {test,spec,features}/*
|
|
42
|
-
|
|
43
41
|

|
|
44
42
|
|
|
45
43
|
Usage example:
|
|
46
|
-
|
|
44
|
+
Simply add the following to your Gemfile and you are good to go.
|
|
47
45
|
All resource index views will now include a link for download directly
|
|
48
46
|
to xlsx.
|
|
49
47
|
|
|
@@ -62,7 +60,7 @@ something adventurous please ping me on irc. (freenode#axlsx)
|
|
|
62
60
|
|
|
63
61
|
```ruby
|
|
64
62
|
#app/admin/posts.rb
|
|
65
|
-
ActiveAdmin.register
|
|
63
|
+
ActiveAdmin.register Post do
|
|
66
64
|
config.xlsx_builder.i18n_scope [:active_record, :models, :posts]
|
|
67
65
|
end
|
|
68
66
|
```
|
|
@@ -71,7 +69,7 @@ end
|
|
|
71
69
|
|
|
72
70
|
```ruby
|
|
73
71
|
#app/admin/posts.rb
|
|
74
|
-
ActiveAdmin.register
|
|
72
|
+
ActiveAdmin.register Post do
|
|
75
73
|
config.xlsx_builder.column('author_name') do |resource|
|
|
76
74
|
resource.author.name
|
|
77
75
|
end
|
|
@@ -82,12 +80,68 @@ end
|
|
|
82
80
|
|
|
83
81
|
```ruby
|
|
84
82
|
#app/admin/posts.rb
|
|
85
|
-
ActiveAdmin.register
|
|
83
|
+
ActiveAdmin.register Post do
|
|
86
84
|
config.xlsx_builder.header_style = { :bg_color => 'FF0000',
|
|
87
85
|
:fg_color => 'FF' }
|
|
88
86
|
end
|
|
89
87
|
```
|
|
90
88
|
|
|
89
|
+
##Remove columns
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
#app/admin/posts.rb
|
|
93
|
+
ActiveAdmin.register Post do
|
|
94
|
+
config.xlsx_builder.delete_columns :id, :created_at, :updated_at
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#Using the DSL
|
|
99
|
+
|
|
100
|
+
Everything that you do with the config'd default builder can be done via
|
|
101
|
+
the resource DSL.
|
|
102
|
+
|
|
103
|
+
Below is an example of the DSL
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
ActiveAdmin.register Post do
|
|
107
|
+
# i18n_scope and header style are set via options
|
|
108
|
+
xlsx(:i18n_scope => [:active_admin, :axlsx, :post],
|
|
109
|
+
:header_style => {:bg_color => 'FF0000', :fg_color => 'FF' }) do
|
|
110
|
+
|
|
111
|
+
# deleting columns from the report
|
|
112
|
+
delete_columns :id, :created_at, :updated_at
|
|
113
|
+
|
|
114
|
+
# adding a column to the report
|
|
115
|
+
column(:author) { |resource| "#{resource.author.first_name} #{resource.author.last_name}" }
|
|
116
|
+
|
|
117
|
+
# creating a chart and inserting additional data with after_filter
|
|
118
|
+
after_filter { |sheet|
|
|
119
|
+
sheet.add_row []
|
|
120
|
+
sheet.add_row ['Author Name', 'Number of Posts']
|
|
121
|
+
data = []
|
|
122
|
+
labels = []
|
|
123
|
+
User.all.each do |user|
|
|
124
|
+
data << user.posts.size
|
|
125
|
+
labels << "#{user.first_name} #{user.last_name}"
|
|
126
|
+
sheet.add_row [labels.last, data.last]
|
|
127
|
+
end
|
|
128
|
+
chart_color = %w(88F700 279CAC B2A200 FD66A3 F20062 C8BA2B 67E6F8 DFFDB9 FFE800 B6F0F8)
|
|
129
|
+
sheet.add_chart(::Axlsx::Pie3DChart, :title => "post by author") do |chart|
|
|
130
|
+
chart.add_series :data => data, :labels => labels, :colors => chart_color
|
|
131
|
+
chart.start_at 4, 0
|
|
132
|
+
chart.end_at 7, 20
|
|
133
|
+
end
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# iserting data with before_filter
|
|
137
|
+
before_filter do |sheet|
|
|
138
|
+
sheet.add_row ['Created', Time.zone.now]
|
|
139
|
+
sheet.add_row []
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
```
|
|
144
|
+
|
|
91
145
|
#Specs
|
|
92
146
|
------
|
|
93
147
|
Running specs for this gem requires that you construct a rails application.
|
|
@@ -101,6 +155,15 @@ bundle exec rake setup
|
|
|
101
155
|
```
|
|
102
156
|
bundle exec rake
|
|
103
157
|
```
|
|
158
|
+
# Changelog
|
|
159
|
+
**2012.11.29** Release 2.0.0
|
|
160
|
+
- resouce content column are now pre-populated.
|
|
161
|
+
- added before and after filters
|
|
162
|
+
- 100% spec coverage
|
|
163
|
+
|
|
164
|
+
**2012.11.16**
|
|
165
|
+
- Fixed DSL referencing
|
|
166
|
+
- Added delete_columns to builder and DSL
|
|
104
167
|
|
|
105
168
|
#Copyright and License
|
|
106
169
|
----------
|
data/Rakefile
CHANGED
data/lib/active_admin/axlsx.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require 'active_admin'
|
|
2
|
-
require 'active_admin/axlsx/autoload_extension'
|
|
3
2
|
require 'active_admin/axlsx/build_download_format_links'
|
|
4
3
|
require 'active_admin/axlsx/version'
|
|
5
4
|
require 'active_admin/axlsx/builder'
|
|
@@ -14,9 +13,9 @@ class Railtie < ::Rails::Railtie
|
|
|
14
13
|
Mime::Type.register "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", :xlsx
|
|
15
14
|
end
|
|
16
15
|
rescue NameError
|
|
17
|
-
|
|
16
|
+
# noop
|
|
18
17
|
end
|
|
19
|
-
|
|
18
|
+
|
|
20
19
|
ActiveAdmin::ResourceDSL.send :include, ActiveAdmin::Axlsx::DSL
|
|
21
20
|
ActiveAdmin::Resource.send :include, ActiveAdmin::Axlsx::ResourceExtension
|
|
22
21
|
ActiveAdmin::ResourceController.send :include, ActiveAdmin::Axlsx::ResourceControllerExtension
|
|
@@ -5,6 +5,8 @@ module ActiveAdmin
|
|
|
5
5
|
base.send :alias_method_chain, :build_download_format_links, :xlsx
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
# We are patching the build_download_format_links to include the :xlsx format
|
|
9
|
+
# Once ActiveAdmin 0.5.1 or higher has been released this can and should be removed.
|
|
8
10
|
def build_download_format_links_with_xlsx(formats = [:csv, :xml, :json, :xlsx])
|
|
9
11
|
build_download_format_links_without_xlsx(formats)
|
|
10
12
|
end
|
|
@@ -2,47 +2,69 @@ require 'axlsx'
|
|
|
2
2
|
|
|
3
3
|
module ActiveAdmin
|
|
4
4
|
module Axlsx
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
# Usage example
|
|
8
|
-
#
|
|
9
|
-
# xlsx_builder = XlsxBuilder.new
|
|
10
|
-
# xlsx_builder.column :id
|
|
11
|
-
# xlsx_builder.column('Name') { |resource| resource.full_name }
|
|
12
|
-
#
|
|
13
|
-
# xlsx_builder = XlsxBuilder.new :shared_strings => true
|
|
14
|
-
# xlsx_builder.column :id
|
|
15
|
-
#
|
|
16
|
-
# xlsx_builder = XlsxBuiler.new :header_style => { :bg_color => '00', :fg_color => 'FF', :sz => 14, :alignment => { :horizontal => :center } }
|
|
17
|
-
# xlsx_buider.i18n_scope [:active_record, :models, :posts]
|
|
18
|
-
class Builder < ActiveAdmin::CSVBuilder
|
|
5
|
+
# Builder for xlsx data using the axlsx gem.
|
|
6
|
+
class Builder
|
|
19
7
|
|
|
20
8
|
include MethodOrProcHelper
|
|
21
9
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
10
|
+
# @param resource_class The resource this builder generate column information for.
|
|
11
|
+
# @param [Hash] options the options for this builder
|
|
12
|
+
# @option [Hash] :header_style - a hash of style properties to apply
|
|
13
|
+
# to the header row. Any properties specified will be merged with the default
|
|
14
|
+
# header styles. @see Axlsx::Styles#add_style
|
|
15
|
+
# @option [Array] :i18n_scope - the I18n scope to use when looking
|
|
16
|
+
# up localized column headers.
|
|
17
|
+
# @param [Block] Any block given will evaluated against this instance of Builder.
|
|
18
|
+
# That means you can call any method on the builder from withing that block.
|
|
19
|
+
# @example
|
|
20
|
+
# ActiveAdmin::Axlsx:Builder.new(Post, i18n: [:axlsx]) do
|
|
21
|
+
# delete_columns :id, :created_at, :updated_at
|
|
22
|
+
# column(:author_name) { |post| post.author.name }
|
|
23
|
+
# column(:
|
|
24
|
+
# after_filter { |sheet|
|
|
25
|
+
# sheet.add_row []
|
|
26
|
+
#
|
|
27
|
+
# sheet.add_row ['Author Name', 'Number of Posts'], :style => self.header_style
|
|
28
|
+
# data = labels = []
|
|
29
|
+
# User.all.each do |user|
|
|
30
|
+
# data << [user.posts.size]
|
|
31
|
+
# labels << user.name
|
|
32
|
+
# sheet.add_row [labels.last, data.last]
|
|
33
|
+
# end
|
|
34
|
+
# chart_color = %w(88F700, 279CAC, B2A200, FD66A3, F20062, C8BA2B, 67E6F8, DFFDB9, FFE800, B6F0F8)
|
|
35
|
+
# sheet.add_chart(Axlsx::Pie3DChart, :title => "post by author") do |chart|
|
|
36
|
+
# chart.add_series :data => data, :labels => labels, :colors => chart_color
|
|
37
|
+
# chart.start_at 2, sheet.rows.size
|
|
38
|
+
# chart.end_at 3, sheet.rows.size + 20
|
|
39
|
+
# end
|
|
40
|
+
# }
|
|
41
|
+
# end
|
|
42
|
+
# @see ActiveAdmin::Axlsx::DSL
|
|
43
|
+
def initialize(resource_class, options={}, &block)
|
|
44
|
+
@columns = resource_columns(resource_class)
|
|
45
|
+
parse_options options
|
|
46
|
+
instance_eval &block if block_given?
|
|
31
47
|
end
|
|
32
48
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
attr_accessor :shared_strings
|
|
49
|
+
# The default header style
|
|
50
|
+
# @return [Hash]
|
|
51
|
+
def header_style
|
|
52
|
+
@header_style ||= { :bg_color => '00', :fg_color => 'FF', :sz => 12, :alignment => { :horizontal => :center } }
|
|
53
|
+
end
|
|
39
54
|
|
|
40
55
|
# This has can be used to override the default header style for your
|
|
41
|
-
# sheet.
|
|
56
|
+
# sheet. Any values you provide will be merged with the default styles.
|
|
57
|
+
# Precidence is given to your hash
|
|
42
58
|
# @see https://github.com/randym/axlsx for more details on how to
|
|
43
59
|
# create and apply style.
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
def header_style=(style_hash)
|
|
61
|
+
@header_style = header_style.merge(style_hash)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The scope to use when looking up column names to generate the report header
|
|
65
|
+
def i18n_scope
|
|
66
|
+
@i18n_scope ||= nil
|
|
67
|
+
end
|
|
46
68
|
|
|
47
69
|
# This is the I18n scope that will be used when looking up your
|
|
48
70
|
# colum names in the current I18n locale.
|
|
@@ -50,65 +72,114 @@ module ActiveAdmin
|
|
|
50
72
|
# serializer will render the value at active_admin.resources.posts.title in the
|
|
51
73
|
# current translations
|
|
52
74
|
# @note If you do not set this, the column name will be titleized.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
# @param [Hash] options the options for this builder
|
|
56
|
-
# @option [Hash] :header_style - a hash of style properties to apply
|
|
57
|
-
# to the header row
|
|
58
|
-
# @option [Array] :i18n_scope - the I18n scope to use when looking
|
|
59
|
-
# up localized column headers.
|
|
60
|
-
# @option [Boolean] :shared_strings - Tells the serializer to use
|
|
61
|
-
# shared strings or not when parsing out the package.
|
|
62
|
-
# @note shared strings are an optional part of the ECMA-376 spec,and
|
|
63
|
-
# are only required when you need to support Numbers.
|
|
64
|
-
def initialize(options={}, &block)
|
|
65
|
-
super
|
|
66
|
-
@header_style = options.delete(:header_style) || @@default_header_style
|
|
67
|
-
@i18n_scope = options.delete(:i18n_scope)
|
|
68
|
-
@shared_strings = options.delete(:shared_strings) || true
|
|
69
|
-
instance_eval &block if block_given?
|
|
75
|
+
def i18n_scope=(scope)
|
|
76
|
+
@i18n_scope = scope
|
|
70
77
|
end
|
|
71
78
|
|
|
72
|
-
#
|
|
73
|
-
def
|
|
74
|
-
@
|
|
79
|
+
# The stored block that will be executed after your report is generated.
|
|
80
|
+
def after_filter(&block)
|
|
81
|
+
@after_filter = block
|
|
75
82
|
end
|
|
76
83
|
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
header_style_id = package.workbook.styles.add_style header_style
|
|
81
|
-
package.workbook.add_worksheet do |sheet|
|
|
82
|
-
sheet.add_row header_row, :style => header_style_id
|
|
83
|
-
collection.each do |resource|
|
|
84
|
-
sheet.add_row columns.map { |column| call_method_or_proc_on resource, column.data }
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
package
|
|
84
|
+
# the stored block that will be executed before your report is generated.
|
|
85
|
+
def before_filter(&block)
|
|
86
|
+
@before_filter = block
|
|
88
87
|
end
|
|
89
88
|
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
# The columns this builder will be serializing
|
|
90
|
+
attr_reader :columns
|
|
91
|
+
|
|
92
|
+
# removes all columns from the builder. This is useful when you want to
|
|
93
|
+
# only render specific columns. To remove specific columns use ignore_column.
|
|
94
|
+
def clear_columns
|
|
95
|
+
@columns = []
|
|
94
96
|
end
|
|
95
97
|
|
|
96
98
|
# Add a column
|
|
99
|
+
# @param [Symbol] name The name of the column.
|
|
100
|
+
# @param [Proc] block A block of code that is executed on the resource
|
|
101
|
+
# when generating row data for this column.
|
|
97
102
|
def column(name, &block)
|
|
98
103
|
@columns << Column.new(name, block)
|
|
99
104
|
end
|
|
100
105
|
|
|
106
|
+
# removes columns by name
|
|
107
|
+
# each column_name should be a symbol
|
|
108
|
+
def delete_columns(*column_names)
|
|
109
|
+
@columns.delete_if { |column| column_names.include?(column.name) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Serializes the collection provided
|
|
113
|
+
# @return [Axlsx::Package]
|
|
114
|
+
def serialize(collection)
|
|
115
|
+
apply_filter @before_filter
|
|
116
|
+
export_collection(collection)
|
|
117
|
+
apply_filter @after_filter
|
|
118
|
+
package
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
protected
|
|
122
|
+
|
|
101
123
|
class Column
|
|
102
|
-
attr_reader :name, :data
|
|
103
124
|
|
|
104
125
|
def initialize(name, block = nil)
|
|
105
126
|
@name = name.to_sym
|
|
106
127
|
@data = block || @name
|
|
107
128
|
end
|
|
108
129
|
|
|
130
|
+
attr_reader :name, :data
|
|
131
|
+
|
|
109
132
|
def localized_name(i18n_scope = nil)
|
|
110
133
|
return name.to_s.titleize unless i18n_scope
|
|
111
|
-
I18n.t name, i18n_scope
|
|
134
|
+
I18n.t name, scope: i18n_scope
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
private
|
|
139
|
+
|
|
140
|
+
def export_collection(collection)
|
|
141
|
+
header_row
|
|
142
|
+
collection.each do |resource|
|
|
143
|
+
sheet.add_row resource_data(resource)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def apply_filter(filter)
|
|
148
|
+
filter.call(sheet) if filter
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def parse_options(options)
|
|
152
|
+
options.each do |key, value|
|
|
153
|
+
self.send("#{key}=", value) if self.respond_to?("#{key}=") && value != nil
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def resource_data(resource)
|
|
158
|
+
columns.map { |column| call_method_or_proc_on resource, column.data }
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def sheet
|
|
162
|
+
@sheet ||= package.workbook.add_worksheet
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# the Axlsx::Package
|
|
166
|
+
def package
|
|
167
|
+
@package ||= ::Axlsx::Package.new(:use_shared_strings => true)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# tranform column names into array of localized strings
|
|
171
|
+
# @return [Array]
|
|
172
|
+
def header_row
|
|
173
|
+
sheet.add_row columns.map { |column| column.localized_name(i18n_scope) }, :style => header_style_id
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def header_style_id
|
|
177
|
+
package.workbook.styles.add_style header_style
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def resource_columns(resource)
|
|
181
|
+
[Column.new(:id)] + resource.content_columns.map do |column|
|
|
182
|
+
Column.new(column.name.to_sym)
|
|
112
183
|
end
|
|
113
184
|
end
|
|
114
185
|
end
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
module ActiveAdmin
|
|
2
2
|
module Axlsx
|
|
3
3
|
module DSL
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
# For example:
|
|
7
|
-
#
|
|
8
|
-
# xlsx do
|
|
9
|
-
# i18n_scope = [:active_admin, :resources, :post]
|
|
10
|
-
# column :name
|
|
11
|
-
# column(:author) { |post| post.author.full_name }
|
|
12
|
-
# end
|
|
13
|
-
#
|
|
14
|
-
# xlsx :header_style => { :bg_color => "00", :fg_color => "FF" } do
|
|
15
|
-
# column :name
|
|
16
|
-
# end
|
|
4
|
+
delegate :ingnore_columns, :column, :after_filer, :i18n_scope, :header_style, to: :xlsx_builder, prefix: :config
|
|
5
|
+
# @see ActiveAdmin::Axlsx::Builder
|
|
17
6
|
def xlsx(options={}, &block)
|
|
18
|
-
config.xlsx_builder =
|
|
7
|
+
config.xlsx_builder = ActiveAdmin::Axlsx::Builder.new(config.resource_class, options, &block)
|
|
19
8
|
end
|
|
20
|
-
|
|
21
9
|
end
|
|
22
10
|
end
|
|
23
11
|
end
|
|
@@ -7,17 +7,19 @@ module ActiveAdmin
|
|
|
7
7
|
base.send :respond_to, :xlsx
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
# patching the index method to allow the xlsx format.
|
|
10
11
|
def index_with_xlsx(options={}, &block)
|
|
11
12
|
index_without_xlsx(options) do |format|
|
|
12
13
|
format.xlsx do
|
|
13
14
|
xlsx = active_admin_config.xlsx_builder.serialize(collection)
|
|
14
|
-
send_data xlsx.to_stream.read, :filename => "#{xlsx_filename}", :type =>
|
|
15
|
+
send_data xlsx.to_stream.read, :filename => "#{xlsx_filename}", :type => Mime::Type.lookup_by_extension(:xlsx)
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
|
|
20
|
+
# patching per_page to use the CSV record max for pagination when the format is xlsx
|
|
19
21
|
def per_page_with_xlsx
|
|
20
|
-
if request.format ==
|
|
22
|
+
if request.format == Mime::Type.lookup_by_extension(:xlsx)
|
|
21
23
|
return max_csv_records
|
|
22
24
|
end
|
|
23
25
|
per_page_without_xlsx
|
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
module ActiveAdmin
|
|
2
2
|
module Axlsx
|
|
3
3
|
module ResourceExtension
|
|
4
|
-
|
|
5
4
|
def xlsx_builder=(builder)
|
|
6
5
|
@xlsx_builder = builder
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def xlsx_builder
|
|
10
|
-
@xlsx_builder ||=
|
|
9
|
+
@xlsx_builder ||= ActiveAdmin::Axlsx::Builder.new(resource_class)
|
|
11
10
|
end
|
|
12
11
|
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
def default_xlsx_builder
|
|
16
|
-
@default_xlsx_builder ||= Axlsx::Builder.default_for_resource(resource_class)
|
|
17
|
-
end
|
|
18
12
|
end
|
|
19
13
|
end
|
|
20
14
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
describe ActiveAdmin::Views::PaginatedCollection do
|
|
3
|
+
def arbre(assigns = {}, helpers = mock_action_view, &block)
|
|
4
|
+
Arbre::Context.new(assigns, helpers, &block)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def render_arbre_component(assigns = {}, helpers = mock_action_view, &block)
|
|
8
|
+
arbre(assigns, helpers, &block).children.first
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Returns a fake action view instance to use with our renderers
|
|
12
|
+
def mock_action_view(assigns = {})
|
|
13
|
+
controller = ActionView::TestCase::TestController.new
|
|
14
|
+
ActionView::Base.send :include, ActionView::Helpers
|
|
15
|
+
ActionView::Base.send :include, ActiveAdmin::ViewHelpers
|
|
16
|
+
ActionView::Base.send :include, Rails.application.routes.url_helpers
|
|
17
|
+
ActionView::Base.new(ActionController::Base.view_paths, assigns, controller)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:view) do
|
|
21
|
+
view = mock_action_view
|
|
22
|
+
view.request.stub!(:query_parameters).and_return({:controller => 'admin/posts', :action => 'index', :page => '1'})
|
|
23
|
+
view.controller.params = {:controller => 'admin/posts', :action => 'index'}
|
|
24
|
+
view
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Helper to render paginated collections within an arbre context
|
|
28
|
+
def paginated_collection(*args)
|
|
29
|
+
render_arbre_component({:paginated_collection_args => args}, view) do
|
|
30
|
+
paginated_collection(*paginated_collection_args)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
let(:collection) do
|
|
35
|
+
posts = [Post.new(:title => "First Post")]
|
|
36
|
+
Kaminari.paginate_array(posts).page(1).per(5)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
let(:pagination) { paginated_collection(collection) }
|
|
40
|
+
|
|
41
|
+
before do
|
|
42
|
+
collection.stub!(:reorder) { collection }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "renders the xlsx download link" do
|
|
46
|
+
pagination.children.last.content.should match(/XLSX/)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,38 +1,117 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
+
|
|
2
3
|
module ActiveAdmin
|
|
3
4
|
module Axlsx
|
|
4
5
|
describe Builder do
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
|
|
7
|
+
let(:builder) { Builder.new(Post) }
|
|
8
|
+
let(:content_columns) { Post.content_columns }
|
|
9
|
+
|
|
10
|
+
context 'the default builder' do
|
|
11
|
+
subject { builder }
|
|
12
|
+
its(:header_style) { should == { :bg_color => '00', :fg_color => 'FF', :sz => 12, :alignment => { :horizontal => :center } } }
|
|
13
|
+
its(:i18n_scope) { should be_nil }
|
|
14
|
+
its("columns.size") { should == content_columns.size + 1 }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context 'customizing a builder' do
|
|
18
|
+
it 'deletes columns we tell it we dont want' do
|
|
19
|
+
builder.delete_columns :id, :body
|
|
20
|
+
builder.columns.size.should == content_columns.size - 1
|
|
8
21
|
end
|
|
9
22
|
|
|
10
|
-
it
|
|
11
|
-
builder.
|
|
23
|
+
it 'lets us add custom columns' do
|
|
24
|
+
builder.column(:hoge)
|
|
25
|
+
builder.columns.size.should == content_columns.size + 2
|
|
12
26
|
end
|
|
13
|
-
end
|
|
14
27
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
it 'lets us clear all columns' do
|
|
29
|
+
builder.clear_columns
|
|
30
|
+
builder.columns.size.should == 0
|
|
18
31
|
end
|
|
19
32
|
|
|
20
|
-
|
|
21
|
-
|
|
33
|
+
context 'Using Procs for delayed content generation' do
|
|
34
|
+
|
|
35
|
+
let(:post) { Post.new(:title => "Hot Dawg") }
|
|
36
|
+
|
|
37
|
+
before do
|
|
38
|
+
builder.column(:hoge) { |resource| "#{resource.title} - with cheese" }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'stores the block when defining a column for later execution.' do
|
|
42
|
+
builder.columns.last.data.should be_a(Proc)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'evaluates custom column blocks' do
|
|
46
|
+
builder.columns.last.data.call(post).should == "Hot Dawg - with cheese"
|
|
47
|
+
end
|
|
22
48
|
end
|
|
23
49
|
end
|
|
24
50
|
|
|
25
|
-
context
|
|
26
|
-
|
|
27
|
-
|
|
51
|
+
context 'Sheet generation with a highly customized configuration.' do
|
|
52
|
+
|
|
53
|
+
let!(:users) { [User.new(first_name: 'bob', last_name: 'nancy')] }
|
|
54
|
+
|
|
55
|
+
let!(:posts) { [Post.new(title: 'bob', body: 'is a swell guy', author: users.first)] }
|
|
56
|
+
|
|
57
|
+
let!(:builder) {
|
|
58
|
+
Builder.new(Post, header_style: { sz: 10, fg_color: "FF0000" }, i18n_scope: [:axlsx, :post]) do
|
|
59
|
+
delete_columns :id, :created_at, :updated_at
|
|
60
|
+
column(:author) { |resource| "#{resource.author.first_name} #{resource.author.last_name}" }
|
|
61
|
+
after_filter { |sheet|
|
|
62
|
+
sheet.add_row []
|
|
63
|
+
sheet.add_row ['Author Name', 'Number of Posts']
|
|
64
|
+
data = []
|
|
65
|
+
labels = []
|
|
66
|
+
User.all.each do |user|
|
|
67
|
+
data << user.posts.size
|
|
68
|
+
labels << "#{user.first_name} #{user.last_name}"
|
|
69
|
+
sheet.add_row [labels.last, data.last]
|
|
70
|
+
end
|
|
71
|
+
chart_color = %w(88F700 279CAC B2A200 FD66A3 F20062 C8BA2B 67E6F8 DFFDB9 FFE800 B6F0F8)
|
|
72
|
+
sheet.add_chart(::Axlsx::Pie3DChart, :title => "post by author") do |chart|
|
|
73
|
+
chart.add_series :data => data, :labels => labels, :colors => chart_color
|
|
74
|
+
chart.start_at 4, 0
|
|
75
|
+
chart.end_at 7, 20
|
|
76
|
+
end
|
|
77
|
+
}
|
|
78
|
+
before_filter do |sheet|
|
|
79
|
+
sheet.add_row ['Created', Time.zone.now]
|
|
80
|
+
sheet.add_row []
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
before(:all) do
|
|
86
|
+
User.stub!(:all) { users }
|
|
87
|
+
Post.stub!(:all) { posts }
|
|
88
|
+
@package = builder.serialize(Post.all)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'merges our customizations with the default header style' do
|
|
92
|
+
builder.header_style[:sz].should be(10)
|
|
93
|
+
builder.header_style[:fg_color].should == 'FF0000'
|
|
94
|
+
builder.header_style[:bg_color].should == '00'
|
|
28
95
|
end
|
|
29
96
|
|
|
30
|
-
|
|
31
|
-
|
|
97
|
+
it 'uses the specified i18n_scope' do
|
|
98
|
+
builder.i18n_scope.should == [:axlsx, :post]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'translates the header row based on our i18n scope' do
|
|
102
|
+
header_row = @package.workbook.worksheets.first.rows[2]
|
|
103
|
+
header_row.cells.map(&:value).should == ['Title', 'Content', 'Published On', 'Publisher']
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'processes the before filter' do
|
|
107
|
+
@package.workbook.worksheets.first["A1"].value.should == 'Created'
|
|
108
|
+
end
|
|
109
|
+
it 'processes the after filter' do
|
|
110
|
+
@package.workbook.charts.size.should == 1
|
|
32
111
|
end
|
|
33
112
|
|
|
34
|
-
it
|
|
35
|
-
|
|
113
|
+
it 'has no OOXML validation errors' do
|
|
114
|
+
@package.validate.size.should == 0
|
|
36
115
|
end
|
|
37
116
|
end
|
|
38
117
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module ActiveAdmin
|
|
4
|
+
module Axlsx
|
|
5
|
+
describe ::ActiveAdmin::ResourceDSL do
|
|
6
|
+
context 'in a registraiton block' do
|
|
7
|
+
let(:builder) {
|
|
8
|
+
config = ActiveAdmin.register(Post) do
|
|
9
|
+
xlsx(i18n_scope: [:rspec], header_style: { sz: 20 }) do
|
|
10
|
+
delete_columns :id, :created_at
|
|
11
|
+
column(:author) { |post| post.author.first_name }
|
|
12
|
+
before_filter { |sheet| sheet.add_row ['before_filter'] }
|
|
13
|
+
after_filter { |sheet| sheet.add_row['after_filter'] }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
config.xlsx_builder
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
it "uses our customized i18n scope" do
|
|
21
|
+
builder.i18n_scope.should == [:rspec]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "removed the columns we told it to ignore" do
|
|
25
|
+
[:id, :create_at].each do |removed|
|
|
26
|
+
builder.columns.index{|column| column.name == removed}.should be_nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "added the columns we declared" do
|
|
31
|
+
builder.columns.index{ |column| column.name == :author}.should_not be_nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "has a before filter set" do
|
|
35
|
+
builder.instance_values["before_filter"].should be_a(Proc)
|
|
36
|
+
end
|
|
37
|
+
it "has an after filter set" do
|
|
38
|
+
builder.instance_values["after_filter"].should be_a(Proc)
|
|
39
|
+
end
|
|
40
|
+
it "updates the header style" do
|
|
41
|
+
builder.header_style[:sz].should be(20)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
describe ActiveAdmin::ResourceController do
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
let(:mime) { Mime::Type.lookup_by_extension(:xlsx) }
|
|
6
|
+
|
|
7
|
+
let(:request) do
|
|
8
|
+
ActionController::TestRequest.new.tap do |test_request|
|
|
9
|
+
test_request.accept = mime
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
let(:response) { ActionController::TestResponse.new }
|
|
14
|
+
|
|
15
|
+
let(:controller) do
|
|
16
|
+
Admin::CategoriesController.new.tap do |controller|
|
|
17
|
+
controller.request = request
|
|
18
|
+
controller.response = response
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:filename) { "#{controller.resource_class.to_s.downcase.pluralize}-#{Time.now.strftime("%Y-%m-%d")}.xlsx" }
|
|
23
|
+
|
|
24
|
+
it 'generates an xlsx filename' do
|
|
25
|
+
controller.xlsx_filename.should == filename
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
context 'when making requests with the xlsx mime type' do
|
|
30
|
+
it 'returns xlsx attachment when requested' do
|
|
31
|
+
controller.send :index
|
|
32
|
+
response.headers["Content-Disposition"].should == "attachment; filename=\"#{filename}\""
|
|
33
|
+
response.headers["Content-Transfer-Encoding"].should == 'binary'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'returns max_csv_records for per_page' do
|
|
37
|
+
controller.send(:per_page).should == controller.send(:max_csv_records)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'kicks back to the default per_page when we are not specifying a xlsx mime type' do
|
|
41
|
+
controller.request.accept = 'text/html'
|
|
42
|
+
controller.send(:per_page).should == ActiveAdmin.application.default_per_page
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
@@ -4,31 +4,23 @@ include ActiveAdmin
|
|
|
4
4
|
module ActiveAdmin
|
|
5
5
|
module Axlsx
|
|
6
6
|
describe Resource do
|
|
7
|
-
|
|
7
|
+
let(:resource) { ActiveAdmin.register(Post) }
|
|
8
8
|
|
|
9
|
-
let(:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@config ||= Resource.new(namespace, Category, options)
|
|
9
|
+
let(:custom_builder) do
|
|
10
|
+
Builder.new(Post) do |builder|
|
|
11
|
+
column(:fake) { :fake }
|
|
12
|
+
end
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
config.xlsx_builder.columns.size.should == Category.content_columns.size + 1
|
|
20
|
-
end
|
|
15
|
+
context 'when registered' do
|
|
16
|
+
it "each resource has an xlsx_builer" do
|
|
17
|
+
resource.xlsx_builder.should be_a(Builder)
|
|
21
18
|
end
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
xlsx_builder = Builder.new
|
|
26
|
-
config.xlsx_builder = xlsx_builder
|
|
27
|
-
config.xlsx_builder.should == xlsx_builder
|
|
28
|
-
end
|
|
20
|
+
it "We can specify our own configured builder" do
|
|
21
|
+
lambda { resource.xlsx_builder = custom_builder }.should_not raise_error
|
|
29
22
|
end
|
|
30
23
|
end
|
|
31
|
-
|
|
32
24
|
end
|
|
33
25
|
end
|
|
34
26
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
require '
|
|
2
|
-
|
|
1
|
+
require 'simplecov'
|
|
2
|
+
SimpleCov.start do
|
|
3
|
+
add_filter "/rails/"
|
|
4
|
+
end
|
|
3
5
|
|
|
6
|
+
# prepare ENV for rails
|
|
7
|
+
require 'rails'
|
|
4
8
|
ENV['RAILS_ROOT'] = File.expand_path("../rails/rails-#{Rails::VERSION::STRING}", __FILE__)
|
|
5
9
|
|
|
10
|
+
# ensure testing application is in place
|
|
6
11
|
unless File.exists?(ENV['RAILS_ROOT'])
|
|
7
12
|
puts "Please run bundle exec rake setup before running the specs."
|
|
8
13
|
exit
|
|
9
14
|
end
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ActiveAdmin.load!
|
|
14
|
-
ActiveAdmin.register(Category)
|
|
15
|
-
ActiveAdmin.register(User)
|
|
16
|
-
ActiveAdmin.register(Post){ belongs_to :user, :optional => true }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
ENV['RAILS_ENV'] = 'test'
|
|
16
|
+
# load up activeadmin and activeadmin-axlsx
|
|
17
|
+
require 'activeadmin-axlsx'
|
|
20
18
|
ActiveAdmin.application.load_paths = [ENV['RAILS_ROOT'] + "/app/admin"]
|
|
19
|
+
|
|
20
|
+
# start up rails
|
|
21
21
|
require ENV['RAILS_ROOT'] + '/config/environment'
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
# and finally,here's rspec
|
|
24
|
+
require 'rspec/rails'
|
|
@@ -42,7 +42,7 @@ end
|
|
|
42
42
|
inject_into_file "config/environments/test.rb", " config.action_mailer.default_url_options = { :host => 'example.com' }\n", :after => "config.cache_classes = true\n"
|
|
43
43
|
|
|
44
44
|
# Add our local Active Admin to the load path
|
|
45
|
-
inject_into_file "config/environment.rb", "\
|
|
45
|
+
inject_into_file "config/environment.rb", "\nrequire \"activeadmin-axlsx\"\n", :after => "require File.expand_path('../application', __FILE__)"
|
|
46
46
|
|
|
47
47
|
# Add some translations
|
|
48
48
|
append_file "config/locales/en.yml", File.read(File.expand_path('../templates/en.yml', __FILE__))
|
|
@@ -24,6 +24,7 @@ scopes = <<-EOF
|
|
|
24
24
|
scope :my_posts do |posts|
|
|
25
25
|
posts.where(:author_id => current_admin_user.id)
|
|
26
26
|
end
|
|
27
|
+
|
|
27
28
|
EOF
|
|
28
29
|
inject_into_file 'app/admin/posts.rb', scopes , :after => "ActiveAdmin.register Post do\n"
|
|
29
30
|
|
|
@@ -49,7 +50,7 @@ append_file "db/seeds.rb", <<-EOF
|
|
|
49
50
|
published_at = published_at_values[i % published_at_values.size]
|
|
50
51
|
Post.create :title => "Blog Post \#{i}",
|
|
51
52
|
:body => "Blog post \#{i} is written by \#{user.username} about \#{cat.name}",
|
|
52
|
-
:
|
|
53
|
+
:category_id => cat.id,
|
|
53
54
|
:published_at => published_at,
|
|
54
55
|
:author => user
|
|
55
56
|
end
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
# Sample translations used to test ActiveAdmin's I18n integration.
|
|
2
|
+
axlsx:
|
|
3
|
+
post:
|
|
4
|
+
id: ID
|
|
5
|
+
title: Title
|
|
6
|
+
body: Content
|
|
7
|
+
published_at: Published On
|
|
8
|
+
author: Publisher
|
|
9
|
+
created_at: Created
|
|
10
|
+
updated_at: Updated
|
|
2
11
|
activerecord:
|
|
3
12
|
models:
|
|
4
13
|
store:
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activeadmin-axlsx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-11-
|
|
12
|
+
date: 2012-11-21 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activeadmin
|
|
@@ -54,6 +54,7 @@ extensions: []
|
|
|
54
54
|
extra_rdoc_files: []
|
|
55
55
|
files:
|
|
56
56
|
- .gitignore
|
|
57
|
+
- .rspec
|
|
57
58
|
- .yardops
|
|
58
59
|
- CHANGELOG.md
|
|
59
60
|
- Gemfile
|
|
@@ -63,7 +64,6 @@ files:
|
|
|
63
64
|
- Rakefile
|
|
64
65
|
- activeadmin-axlsx.gemspec
|
|
65
66
|
- lib/active_admin/axlsx.rb
|
|
66
|
-
- lib/active_admin/axlsx/autoload_extension.rb
|
|
67
67
|
- lib/active_admin/axlsx/build_download_format_links.rb
|
|
68
68
|
- lib/active_admin/axlsx/builder.rb
|
|
69
69
|
- lib/active_admin/axlsx/dsl.rb
|
|
@@ -72,7 +72,10 @@ files:
|
|
|
72
72
|
- lib/active_admin/axlsx/version.rb
|
|
73
73
|
- lib/activeadmin-axlsx.rb
|
|
74
74
|
- screen_capture.png
|
|
75
|
+
- spec/axlsx/unit/build_download_format_links_spec.rb
|
|
75
76
|
- spec/axlsx/unit/builder_spec.rb
|
|
77
|
+
- spec/axlsx/unit/dsl_spec.rb
|
|
78
|
+
- spec/axlsx/unit/resource_controller_spec.rb
|
|
76
79
|
- spec/axlsx/unit/resource_spec.rb
|
|
77
80
|
- spec/spec_helper.rb
|
|
78
81
|
- spec/support/rails_template.rb
|
|
@@ -101,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
101
104
|
version: '0'
|
|
102
105
|
segments:
|
|
103
106
|
- 0
|
|
104
|
-
hash:
|
|
107
|
+
hash: 646391432693346211
|
|
105
108
|
requirements: []
|
|
106
109
|
rubyforge_project:
|
|
107
110
|
rubygems_version: 1.8.24
|
|
@@ -110,7 +113,10 @@ specification_version: 3
|
|
|
110
113
|
summary: Adds excel downloads for resources within the Active Admin framework via
|
|
111
114
|
Axlsx.
|
|
112
115
|
test_files:
|
|
116
|
+
- spec/axlsx/unit/build_download_format_links_spec.rb
|
|
113
117
|
- spec/axlsx/unit/builder_spec.rb
|
|
118
|
+
- spec/axlsx/unit/dsl_spec.rb
|
|
119
|
+
- spec/axlsx/unit/resource_controller_spec.rb
|
|
114
120
|
- spec/axlsx/unit/resource_spec.rb
|
|
115
121
|
- spec/spec_helper.rb
|
|
116
122
|
- spec/support/rails_template.rb
|