Skip to content

Commit 8938efd

Browse files
authored
Merge pull request #10 from thambley/issue1
Don't access the database unless and until necessary
2 parents 1f90877 + affa32f commit 8938efd

21 files changed

+430
-254
lines changed

.gemignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.bundle/*

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ doc
88
.rbenv-version
99
.ruby-version
1010
/Gemfile.lock
11+
gemfiles/*.gemfile.lock

CHANGELOG.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
# Changelog
22

3-
## 1.0.2
3+
## 1.0.5
44

5-
### Bug Fixes
5+
### Updates
66

7-
* Fixes undefined local variable or `method max_per_page` [#3][] by [@rewritten][]
7+
* Fix #1 - Unnecessary database access
8+
* Fix broken tests
9+
10+
## 1.0.4
11+
12+
### Updates
13+
14+
* Minor bug fixes / typo corrections
815

916
## 1.0.3
1017

1118
### Updates
1219

1320
* Move require rake from gemspec to lib/activeadmin-xls.rb [#4][] by [@ejaypcanaria][]
1421

22+
## 1.0.2
23+
24+
### Bug Fixes
25+
26+
* Fixes undefined local variable or `method max_per_page` [#3][] by [@rewritten][]
27+
1528
<!--- Link List --->
1629
[#3]: https://github.com/thambley/activeadmin-xls/issues/3
1730
[#4]: https://github.com/thambley/activeadmin-xls/pull/4

Gemfile

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,17 @@
11
source 'https://rubygems.org'
22

3-
gem 'activeadmin', '~> 1.0'
43
gem 'spreadsheet', '~> 1.1', '>= 1.1.4'
54

65
group :development, :test do
7-
gem 'haml', require: false
86
gem 'rails-i18n' # Gives us default i18n for many languages
9-
gem 'rdiscount' # For yard
10-
gem 'sprockets'
117
gem 'sqlite3'
128
gem 'yard'
139
end
1410

1511
group :test do
16-
gem 'capybara'
1712
gem 'cucumber-rails', require: false
1813
gem 'database_cleaner'
19-
gem 'guard-coffeescript'
20-
gem 'guard-rspec'
21-
gem 'inherited_resources'
22-
gem 'jasmine'
23-
gem 'jslint_on_rails', '~> 1.0.6'
24-
gem 'launchy'
25-
gem 'rspec-mocks'
26-
gem 'rspec-rails'
27-
gem 'sass-rails'
28-
gem 'shoulda-matchers', '1.0.0'
14+
gem 'rspec-mocks', '~> 3.7'
15+
gem 'rspec-rails', '~> 3.7'
2916
gem 'simplecov', require: false
3017
end

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,35 @@ end
113113
## Specs
114114

115115
Running specs for this gem requires that you construct a rails application.
116-
To execute the specs, navigate to the gem directory,
117-
run bundle install and run these to rake tasks:
116+
117+
To execute the specs, navigate to the gem directory, run bundle install and run these to rake tasks:
118+
119+
### Rails 3.2
120+
121+
```text
122+
bundle install --gemfile=gemfiles/rails_32.gemfile
123+
```
124+
125+
```text
126+
BUNDLE_GEMFILE=gemfiles/rails_32.gemfile bundle exec rake setup
127+
```
128+
129+
```text
130+
BUNDLE_GEMFILE=gemfiles/rails_32.gemfile bundle exec rake
131+
```
132+
133+
### Rails 4.2
134+
135+
```text
136+
bundle install --gemfile=gemfiles/rails_42.gemfile
137+
```
118138

119139
```text
120-
bundle exec rake setup
140+
BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake setup
121141
```
122142

123143
```text
124-
bundle exec rake
144+
BUNDLE_GEMFILE=gemfiles/rails_42.gemfile bundle exec rake
125145
```
126146

127147
## Copyright and License

Rakefile

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
#!/usr/bin/env rake
2-
require "activeadmin"
3-
require "rspec/core/rake_task"
2+
require 'rspec/core/rake_task'
43

5-
desc "Creates a test rails app for the specs to run against"
4+
desc 'Creates a test rails app for the specs to run against'
65
task :setup do
76
require 'rails/version'
8-
system("mkdir spec/rails") unless File.exists?("spec/rails")
7+
system('mkdir spec/rails') unless File.exist?('spec/rails')
8+
puts "system \"bundle exec rails new spec/rails/rails-#{Rails::VERSION::STRING} -m spec/support/rails_template_with_data.rb\""
99
system "bundle exec rails new spec/rails/rails-#{Rails::VERSION::STRING} -m spec/support/rails_template_with_data.rb"
1010
end
1111

1212
RSpec::Core::RakeTask.new
13-
task :default => :spec
14-
task :test => :spec
13+
task default: :spec
14+
task test: :spec
1515

16-
desc "build the gem"
16+
desc 'build the gem'
1717
task :build do
18-
system "gem build activeadmin-xls.gemspec"
18+
system 'gem build activeadmin-xls.gemspec'
1919
end
20-
desc "build and release the gem"
21-
task :release => :build do
20+
desc 'build and release the gem'
21+
task release: :build do
2222
system "gem push activeadmin-xls-#{ActiveAdmin::Xls::VERSION}.gem"
2323
end

activeadmin-xls.gemspec

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ Gem::Specification.new do |s|
1515
s.description = <<-DESC
1616
This gem provides excel/xls downloads for resources in Active Admin.
1717
DESC
18-
s.files = `git ls-files`.split("\n").sort
19-
s.test_files = `git ls-files -- {spec}/*`.split("\n")
20-
s.test_files = Dir.glob('{spec/**/*}')
18+
19+
git_tracked_files = `git ls-files`.split("\n").sort
20+
gem_ignored_files = `git ls-files -i -X .gemignore`.split("\n")
21+
22+
s.files = git_tracked_files - gem_ignored_files
2123

2224
s.add_runtime_dependency 'activeadmin', '>= 0.6.6', '< 2'
2325
s.add_runtime_dependency 'spreadsheet', '~> 1.0'

gemfiles/rails_32.gemfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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: "../"

gemfiles/rails_42.gemfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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.0.0'
10+
gem 'devise', '~> 4.2'
11+
gem 'rails', '4.2.10'
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: "../"

lib/active_admin/xls/builder.rb

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ class Builder
2929
# @see ActiveAdmin::Axlsx::DSL
3030
def initialize(resource_class, options = {}, &block)
3131
@skip_header = false
32-
@columns = resource_columns(resource_class)
32+
@resource_class = resource_class
33+
@columns = []
34+
@columns_loaded = false
35+
@column_updates = []
3336
parse_options options
3437
instance_eval(&block) if block_given?
3538
end
@@ -60,9 +63,7 @@ def skip_header
6063

6164
# The scope to use when looking up column names to generate the
6265
# report header
63-
def i18n_scope
64-
@i18n_scope ||= nil
65-
end
66+
attr_reader :i18n_scope
6667

6768
# This is the I18n scope that will be used when looking up your
6869
# colum names in the current I18n locale.
@@ -83,7 +84,12 @@ def before_filter(&block)
8384
end
8485

8586
# The columns this builder will be serializing
86-
attr_reader :columns
87+
def columns
88+
# execute each update from @column_updates
89+
# set @columns_loaded = true
90+
load_columns unless @columns_loaded
91+
@columns
92+
end
8793

8894
# The collection we are serializing.
8995
# @note This is only available after serialize has been called,
@@ -94,34 +100,50 @@ def before_filter(&block)
94100
# only render specific columns. To remove specific columns use
95101
# ignore_column.
96102
def clear_columns
103+
@columns_loaded = true
104+
@column_updates = []
105+
97106
@columns = []
98107
end
99108

100109
# Clears the default columns array so you can whitelist only the columns
101110
# you want to export
102-
def whitelist
103-
@columns = []
104-
end
111+
alias whitelist clear_columns
105112

106113
# Add a column
107114
# @param [Symbol] name The name of the column.
108115
# @param [Proc] block A block of code that is executed on the resource
109116
# when generating row data for this column.
110117
def column(name, &block)
111-
@columns << Column.new(name, block)
118+
if @columns_loaded
119+
columns << Column.new(name, block)
120+
else
121+
column_lambda = lambda do
122+
column(name, &block)
123+
end
124+
@column_updates << column_lambda
125+
end
112126
end
113127

114128
# removes columns by name
115129
# each column_name should be a symbol
116130
def delete_columns(*column_names)
117-
@columns.delete_if { |column| column_names.include?(column.name) }
131+
if @columns_loaded
132+
columns.delete_if { |column| column_names.include?(column.name) }
133+
else
134+
delete_lambda = lambda do
135+
delete_columns(*column_names)
136+
end
137+
@column_updates << delete_lambda
138+
end
118139
end
119140

120141
# Serializes the collection provided
121142
# @return [Spreadsheet::Workbook]
122-
def serialize(collection, view_context)
143+
def serialize(collection, view_context = nil)
123144
@collection = collection
124145
@view_context = view_context
146+
load_columns unless @columns_loaded
125147
apply_filter @before_filter
126148
export_collection(collection)
127149
apply_filter @after_filter
@@ -145,6 +167,15 @@ def localized_name(i18n_scope = nil)
145167

146168
private
147169

170+
def load_columns
171+
return if @columns_loaded
172+
@columns = resource_columns(@resource_class)
173+
@columns_loaded = true
174+
@column_updates.each(&:call)
175+
@column_updates = []
176+
columns
177+
end
178+
148179
def to_stream
149180
stream = StringIO.new('')
150181
book.write stream
@@ -158,11 +189,11 @@ def clean_up
158189

159190
def export_collection(collection)
160191
return if columns.none?
161-
row_index = 0
192+
row_index = sheet.dimensions[1]
162193

163194
unless @skip_header
164-
header_row(collection)
165-
row_index = 1
195+
header_row(sheet.row(row_index), collection)
196+
row_index += 1
166197
end
167198

168199
collection.each do |resource|
@@ -173,14 +204,13 @@ def export_collection(collection)
173204

174205
# tranform column names into array of localized strings
175206
# @return [Array]
176-
def header_row(collection)
177-
row = sheet.row(0)
207+
def header_row(row, collection)
178208
apply_format_to_row(row, create_format(header_format))
179209
fill_row(row, header_data_for(collection))
180210
end
181211

182212
def header_data_for(collection)
183-
resource = collection.first
213+
resource = collection.first || @resource_class.new
184214
columns.map do |column|
185215
column.localized_name(i18n_scope) if in_scope(resource, column)
186216
end.compact

0 commit comments

Comments
 (0)