activeadmin-xls 1.0.4
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 +7 -0
- data/.bundle/config +1 -0
- data/.editorconfig +9 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.yardops +1 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +30 -0
- data/LICENSE +22 -0
- data/README.md +131 -0
- data/Rakefile +23 -0
- data/activeadmin-xls.gemspec +27 -0
- data/lib/active_admin/xls/builder.rb +259 -0
- data/lib/active_admin/xls/dsl.rb +26 -0
- data/lib/active_admin/xls/engine.rb +20 -0
- data/lib/active_admin/xls/resource_controller_extension.rb +57 -0
- data/lib/active_admin/xls/resource_extension.rb +13 -0
- data/lib/active_admin/xls/version.rb +5 -0
- data/lib/activeadmin-xls.rb +9 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/rails_template.rb +73 -0
- data/spec/support/rails_template_with_data.rb +59 -0
- data/spec/support/templates/admin/stores.rb +1 -0
- data/spec/support/templates/cucumber.rb +24 -0
- data/spec/support/templates/cucumber_with_reloading.rb +5 -0
- data/spec/support/templates/en.yml +15 -0
- data/spec/xls/unit/build_download_format_links_spec.rb +48 -0
- data/spec/xls/unit/builder_spec.rb +195 -0
- data/spec/xls/unit/dsl_spec.rb +52 -0
- data/spec/xls/unit/resource_controller_spec.rb +44 -0
- data/spec/xls/unit/resource_spec.rb +26 -0
- metadata +120 -0
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter "/rails/"
|
4
|
+
end
|
5
|
+
|
6
|
+
# prepare ENV for rails
|
7
|
+
require 'rails'
|
8
|
+
ENV['RAILS_ROOT'] = File.expand_path("../rails/rails-#{Rails::VERSION::STRING}", __FILE__)
|
9
|
+
|
10
|
+
# ensure testing application is in place
|
11
|
+
unless File.exists?(ENV['RAILS_ROOT'])
|
12
|
+
puts "Please run bundle exec rake setup before running the specs."
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
|
16
|
+
# load up activeadmin and activeadmin-xls
|
17
|
+
require 'activeadmin-xls'
|
18
|
+
ActiveAdmin.application.load_paths = [ENV['RAILS_ROOT'] + "/app/admin"]
|
19
|
+
# start up rails
|
20
|
+
require ENV['RAILS_ROOT'] + '/config/environment'
|
21
|
+
|
22
|
+
# and finally,here's rspec
|
23
|
+
require 'rspec/rails'
|
24
|
+
ActiveAdmin.application.authentication_method = false
|
25
|
+
ActiveAdmin.application.current_user_method = false
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Rails template to build the sample app for specs
|
2
|
+
|
3
|
+
# Create a cucumber database and environment
|
4
|
+
copy_file File.expand_path('../templates/cucumber.rb', __FILE__), "config/environments/cucumber.rb"
|
5
|
+
copy_file File.expand_path('../templates/cucumber_with_reloading.rb', __FILE__), "config/environments/cucumber_with_reloading.rb"
|
6
|
+
|
7
|
+
gsub_file 'config/database.yml', /^test:.*\n/, "test: &test\n"
|
8
|
+
gsub_file 'config/database.yml', /\z/, "\ncucumber:\n <<: *test\n database: db/cucumber.sqlite3"
|
9
|
+
gsub_file 'config/database.yml', /\z/, "\ncucumber_with_reloading:\n <<: *test\n database: db/cucumber.sqlite3"
|
10
|
+
|
11
|
+
# Generate some test models
|
12
|
+
generate :model, "post title:string body:text published_at:datetime author_id:integer category_id:integer"
|
13
|
+
inject_into_file 'app/models/post.rb', " belongs_to :author, :class_name => 'User'\n belongs_to :category\n accepts_nested_attributes_for :author\n", :after => "class Post < ActiveRecord::Base\n"
|
14
|
+
# Rails 3.2.3 model generator declare attr_accessible
|
15
|
+
inject_into_file 'app/models/post.rb', " attr_accessible :author\n", :before => "end" if Rails::VERSION::STRING >= '3.2.3'
|
16
|
+
generate :model, "user type:string first_name:string last_name:string username:string age:integer"
|
17
|
+
inject_into_file 'app/models/user.rb', " has_many :posts, :foreign_key => 'author_id'\n", :after => "class User < ActiveRecord::Base\n"
|
18
|
+
generate :model, "publisher --migration=false --parent=User"
|
19
|
+
generate :model, 'category name:string description:text'
|
20
|
+
inject_into_file 'app/models/category.rb', " has_many :posts\n accepts_nested_attributes_for :posts\n", :after => "class Category < ActiveRecord::Base\n"
|
21
|
+
generate :model, 'store name:string'
|
22
|
+
|
23
|
+
# Generate a model with string ids
|
24
|
+
generate :model, "tag name:string"
|
25
|
+
gsub_file(Dir['db/migrate/*_create_tags.rb'][0], /\:tags\sdo\s.*/, ":tags, :id => false, :primary_key => :id do |t|\n\t\t\tt.string :id\n" )
|
26
|
+
id_model_setup = <<-EOF
|
27
|
+
self.primary_key = :id
|
28
|
+
before_create :set_id
|
29
|
+
|
30
|
+
private
|
31
|
+
def set_id
|
32
|
+
self.id = 8.times.inject("") { |s,e| s << (i = Kernel.rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }
|
33
|
+
end
|
34
|
+
EOF
|
35
|
+
inject_into_file 'app/models/tag.rb', id_model_setup, :after => "class Tag < ActiveRecord::Base\n"
|
36
|
+
|
37
|
+
if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 1 #Rails 3.1 Gotcha
|
38
|
+
gsub_file 'app/models/tag.rb', /self\.primary_key.*$/, "define_attr_method :primary_key, :id"
|
39
|
+
end
|
40
|
+
|
41
|
+
# Configure default_url_options in test environment
|
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
|
+
|
44
|
+
# Add our local Active Admin to the load path
|
45
|
+
inject_into_file "config/environment.rb", "\nrequire \"activeadmin-xls\"\n", :after => "require File.expand_path('../application', __FILE__)"
|
46
|
+
|
47
|
+
# Add some translations
|
48
|
+
append_file "config/locales/en.yml", File.read(File.expand_path('../templates/en.yml', __FILE__))
|
49
|
+
|
50
|
+
# Add predefined admin resources
|
51
|
+
directory File.expand_path('../templates/admin', __FILE__), "app/admin"
|
52
|
+
|
53
|
+
run "rm Gemfile"
|
54
|
+
run "rm -r test"
|
55
|
+
run "rm -r spec"
|
56
|
+
|
57
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
58
|
+
|
59
|
+
# we need this routing path, named "logout_path", for testing
|
60
|
+
route <<-EOS
|
61
|
+
devise_scope :user do
|
62
|
+
match '/admin/logout' => 'active_admin/devise/sessions#destroy', :as => :logout
|
63
|
+
end
|
64
|
+
EOS
|
65
|
+
|
66
|
+
generate :'active_admin:install'
|
67
|
+
|
68
|
+
# Setup a root path for devise
|
69
|
+
route "root :to => 'admin/dashboard#index'"
|
70
|
+
|
71
|
+
rake "db:migrate"
|
72
|
+
rake "db:test:prepare"
|
73
|
+
run "/usr/bin/env RAILS_ENV=cucumber rake db:migrate"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Use the default
|
2
|
+
apply File.expand_path("../rails_template.rb", __FILE__)
|
3
|
+
|
4
|
+
# Register Active Admin controllers
|
5
|
+
%w{ Post User Category }.each do |type|
|
6
|
+
generate :'active_admin:resource', type
|
7
|
+
end
|
8
|
+
|
9
|
+
scopes = <<-EOF
|
10
|
+
scope :all, :default => true
|
11
|
+
|
12
|
+
scope :drafts do |posts|
|
13
|
+
posts.where(["published_at IS NULL"])
|
14
|
+
end
|
15
|
+
|
16
|
+
scope :scheduled do |posts|
|
17
|
+
posts.where(["posts.published_at IS NOT NULL AND posts.published_at > ?", Time.now.utc])
|
18
|
+
end
|
19
|
+
|
20
|
+
scope :published do |posts|
|
21
|
+
posts.where(["posts.published_at IS NOT NULL AND posts.published_at < ?", Time.now.utc])
|
22
|
+
end
|
23
|
+
|
24
|
+
scope :my_posts do |posts|
|
25
|
+
posts.where(:author_id => current_admin_user.id)
|
26
|
+
end
|
27
|
+
|
28
|
+
EOF
|
29
|
+
inject_into_file 'app/admin/posts.rb', scopes , :after => "ActiveAdmin.register Post do\n"
|
30
|
+
|
31
|
+
# Setup some default data
|
32
|
+
append_file "db/seeds.rb", <<-EOF
|
33
|
+
users = ["Jimi Hendrix", "Jimmy Page", "Yngwie Malmsteen", "Eric Clapton", "Kirk Hammett"].collect do |name|
|
34
|
+
first, last = name.split(" ")
|
35
|
+
User.create! :first_name => first,
|
36
|
+
:last_name => last,
|
37
|
+
:username => [first,last].join('-').downcase,
|
38
|
+
:age => rand(80)
|
39
|
+
end
|
40
|
+
|
41
|
+
categories = ["Rock", "Pop Rock", "Alt-Country", "Blues", "Dub-Step"].collect do |name|
|
42
|
+
Category.create! :name => name
|
43
|
+
end
|
44
|
+
|
45
|
+
published_at_values = [Time.now.utc - 5.days, Time.now.utc - 1.day, nil, Time.now.utc + 3.days]
|
46
|
+
|
47
|
+
1_000.times do |i|
|
48
|
+
user = users[i % users.size]
|
49
|
+
cat = categories[i % categories.size]
|
50
|
+
published_at = published_at_values[i % published_at_values.size]
|
51
|
+
Post.create :title => "Blog Post \#{i}",
|
52
|
+
:body => "Blog post \#{i} is written by \#{user.username} about \#{cat.name}",
|
53
|
+
:category_id => cat.id,
|
54
|
+
:published_at => published_at,
|
55
|
+
:author => user
|
56
|
+
end
|
57
|
+
EOF
|
58
|
+
|
59
|
+
rake 'db:seed'
|
@@ -0,0 +1 @@
|
|
1
|
+
ActiveAdmin.register Store
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path('config/environments/test', Rails.root)
|
2
|
+
|
3
|
+
# rails/railties/lib/rails/test_help.rb aborts if the environment is not 'test'. (Rails 3.0.0.beta3)
|
4
|
+
# We can't run Cucumber/RSpec/Test_Unit tests in different environments then.
|
5
|
+
#
|
6
|
+
# For now, I patch StringInquirer so that Rails.env.test? returns true when Rails.env is 'test' or 'cucumber'
|
7
|
+
#
|
8
|
+
# https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/4458-rails-should-allow-test-to-run-in-cucumber-environment
|
9
|
+
module ActiveSupport
|
10
|
+
class StringInquirer < String
|
11
|
+
def method_missing(method_name, *arguments)
|
12
|
+
if method_name.to_s[-1,1] == "?"
|
13
|
+
test_string = method_name.to_s[0..-2]
|
14
|
+
if test_string == 'test'
|
15
|
+
self == 'test' or self == 'cucumber'
|
16
|
+
else
|
17
|
+
self == test_string
|
18
|
+
end
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
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
|
11
|
+
activerecord:
|
12
|
+
models:
|
13
|
+
store:
|
14
|
+
one: Bookstore
|
15
|
+
other: Bookstores
|
@@ -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 xls download link" do
|
46
|
+
pagination.children.last.content.should match(/XLS/)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ActiveAdmin
|
4
|
+
module Xls
|
5
|
+
describe Builder do
|
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
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'lets us say we dont want the header' do
|
24
|
+
builder.skip_header
|
25
|
+
builder.instance_values["skip_header"].should be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'lets us add custom columns' do
|
29
|
+
builder.column(:hoge)
|
30
|
+
builder.columns.size.should == content_columns.size + 2
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'lets us clear all columns' do
|
34
|
+
builder.clear_columns
|
35
|
+
builder.columns.size.should == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'Using Procs for delayed content generation' do
|
39
|
+
|
40
|
+
let(:post) { Post.new(:title => "Hot Dawg") }
|
41
|
+
|
42
|
+
before do
|
43
|
+
builder.column(:hoge) { |resource| "#{resource.title} - with cheese" }
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'stores the block when defining a column for later execution.' do
|
47
|
+
builder.columns.last.data.should be_a(Proc)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'evaluates custom column blocks' do
|
51
|
+
builder.columns.last.data.call(post).should == "Hot Dawg - with cheese"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'sheet generation without headers' do
|
57
|
+
let!(:users) { [User.new(first_name: 'bob', last_name: 'nancy')] }
|
58
|
+
|
59
|
+
let!(:posts) { [Post.new(title: 'bob', body: 'is a swell guy', author: users.first)] }
|
60
|
+
|
61
|
+
let!(:builder) {
|
62
|
+
Builder.new(Post, header_style: { sz: 10, fg_color: "FF0000" }, i18n_scope: [:xls, :post]) do
|
63
|
+
skip_header
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
before do
|
68
|
+
User.stub!(:all) { users }
|
69
|
+
Post.stub!(:all) { posts }
|
70
|
+
# disable clean up so we can get the package.
|
71
|
+
builder.stub(:clean_up) { false }
|
72
|
+
builder.serialize(Post.all)
|
73
|
+
@package = builder.send(:package)
|
74
|
+
@collection = builder.collection
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'does not serialize the header' do
|
78
|
+
not_header = @package.workbook.worksheets.first.rows.first
|
79
|
+
not_header.cells.first.value.should_not == 'Title'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'whitelisted sheet generation' do
|
84
|
+
let!(:users) { [User.new(first_name: 'bob', last_name: 'nancy')] }
|
85
|
+
|
86
|
+
let!(:posts) { [Post.new(title: 'bob', body: 'is a swell guy', author: users.first)] }
|
87
|
+
|
88
|
+
let!(:builder) {
|
89
|
+
Builder.new(Post, header_style: { sz: 10, fg_color: "FF0000" }, i18n_scope: [:xls, :post]) do
|
90
|
+
skip_header
|
91
|
+
whitelist
|
92
|
+
column :title
|
93
|
+
end
|
94
|
+
}
|
95
|
+
|
96
|
+
before do
|
97
|
+
User.stub!(:all) { users }
|
98
|
+
Post.stub!(:all) { posts }
|
99
|
+
# disable clean up so we can get the package.
|
100
|
+
builder.stub(:clean_up) { false }
|
101
|
+
builder.serialize(Post.all)
|
102
|
+
@package = builder.send(:package)
|
103
|
+
@collection = builder.collection
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'does not serialize the header' do
|
107
|
+
sheet = @package.workbook.worksheets.first
|
108
|
+
sheet.rows.first.cells.size.should == 1
|
109
|
+
sheet.rows.first.cells.first.value.should == @collection.first.title
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'Sheet generation with a highly customized configuration.' do
|
114
|
+
|
115
|
+
let!(:users) { [User.new(first_name: 'bob', last_name: 'nancy')] }
|
116
|
+
|
117
|
+
let!(:posts) { [Post.new(title: 'bob', body: 'is a swell guy', author: users.first)] }
|
118
|
+
|
119
|
+
let!(:builder) {
|
120
|
+
Builder.new(Post, header_style: { sz: 10, fg_color: "FF0000" }, i18n_scope: [:xls, :post]) do
|
121
|
+
delete_columns :id, :created_at, :updated_at
|
122
|
+
column(:author) { |resource| "#{resource.author.first_name} #{resource.author.last_name}" }
|
123
|
+
after_filter { |sheet|
|
124
|
+
sheet.add_row []
|
125
|
+
sheet.add_row ['Author Name', 'Number of Posts']
|
126
|
+
data = []
|
127
|
+
labels = []
|
128
|
+
User.all.each do |user|
|
129
|
+
data << user.posts.size
|
130
|
+
labels << "#{user.first_name} #{user.last_name}"
|
131
|
+
sheet.add_row [labels.last, data.last]
|
132
|
+
end
|
133
|
+
chart_color = %w(88F700 279CAC B2A200 FD66A3 F20062 C8BA2B 67E6F8 DFFDB9 FFE800 B6F0F8)
|
134
|
+
sheet.add_chart(::xls::Pie3DChart, :title => "post by author") do |chart|
|
135
|
+
chart.add_series :data => data, :labels => labels, :colors => chart_color
|
136
|
+
chart.start_at 4, 0
|
137
|
+
chart.end_at 7, 20
|
138
|
+
end
|
139
|
+
}
|
140
|
+
before_filter do |sheet|
|
141
|
+
collection.first.author.first_name = 'Set In Proc'
|
142
|
+
sheet.add_row ['Created', Time.zone.now]
|
143
|
+
sheet.add_row []
|
144
|
+
end
|
145
|
+
end
|
146
|
+
}
|
147
|
+
|
148
|
+
before(:all) do
|
149
|
+
User.stub!(:all) { users }
|
150
|
+
Post.stub!(:all) { posts }
|
151
|
+
# disable clean up so we can get the package.
|
152
|
+
builder.stub(:clean_up) { false }
|
153
|
+
builder.serialize(Post.all)
|
154
|
+
@package = builder.send(:package)
|
155
|
+
@collection = builder.collection
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'provides the collection object' do
|
159
|
+
@collection.count.should == Post.all.count
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'merges our customizations with the default header style' do
|
163
|
+
builder.header_style[:sz].should be(10)
|
164
|
+
builder.header_style[:fg_color].should == 'FF0000'
|
165
|
+
builder.header_style[:bg_color].should == '00'
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'uses the specified i18n_scope' do
|
169
|
+
builder.i18n_scope.should == [:xls, :post]
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'translates the header row based on our i18n scope' do
|
173
|
+
header_row = @package.workbook.worksheets.first.rows[2]
|
174
|
+
header_row.cells.map(&:value).should == ['Title', 'Content', 'Published On', 'Publisher']
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'processes the before filter' do
|
178
|
+
@package.workbook.worksheets.first["A1"].value.should == 'Created'
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'lets us work against the collection in the before filter' do
|
182
|
+
@package.workbook.worksheets.first.rows.last.cells.first.value.should == 'Set In Proc nancy'
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'processes the after filter' do
|
186
|
+
@package.workbook.charts.size.should == 1
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'has no OOXML validation errors' do
|
190
|
+
@package.validate.size.should == 0
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ActiveAdmin
|
4
|
+
module Xls
|
5
|
+
describe ::ActiveAdmin::ResourceDSL do
|
6
|
+
context 'in a registraiton block' do
|
7
|
+
let(:builder) {
|
8
|
+
config = ActiveAdmin.register(Post) do
|
9
|
+
xls(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
|
+
skip_header
|
15
|
+
end
|
16
|
+
end
|
17
|
+
config.xls_builder
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
it "uses our customized i18n scope" do
|
22
|
+
builder.i18n_scope.should == [:rspec]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "removed the columns we told it to ignore" do
|
26
|
+
[:id, :create_at].each do |removed|
|
27
|
+
builder.columns.index{|column| column.name == removed}.should be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "added the columns we declared" do
|
32
|
+
builder.columns.index{ |column| column.name == :author}.should_not be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has a before filter set" do
|
36
|
+
builder.instance_values["before_filter"].should be_a(Proc)
|
37
|
+
end
|
38
|
+
it "has an after filter set" do
|
39
|
+
builder.instance_values["after_filter"].should be_a(Proc)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "indicates that the header should be excluded" do
|
43
|
+
builder.instance_values['skip_header'].should be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "updates the header style" do
|
47
|
+
builder.header_style[:sz].should be(20)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe ActiveAdmin::ResourceController do
|
3
|
+
|
4
|
+
let(:mime) { Mime::Type.lookup_by_extension(:xls) }
|
5
|
+
|
6
|
+
let(:request) do
|
7
|
+
ActionController::TestRequest.new.tap do |test_request|
|
8
|
+
test_request.accept = mime
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:response) { ActionController::TestResponse.new }
|
13
|
+
|
14
|
+
let(:controller) do
|
15
|
+
Admin::CategoriesController.new.tap do |controller|
|
16
|
+
controller.request = request
|
17
|
+
controller.response = response
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:filename) { "#{controller.resource_class.to_s.downcase.pluralize}-#{Time.now.strftime("%Y-%m-%d")}.xls" }
|
22
|
+
|
23
|
+
it 'generates an xls filename' do
|
24
|
+
controller.xls_filename.should == filename
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when making requests with the xls mime type' do
|
28
|
+
it 'returns xls attachment when requested' do
|
29
|
+
controller.send :index
|
30
|
+
response.headers["Content-Disposition"].should == "attachment; filename=\"#{filename}\""
|
31
|
+
response.headers["Content-Transfer-Encoding"].should == 'binary'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns max_csv_records for per_page' do
|
35
|
+
controller.send(:per_page).should == controller.send(:max_csv_records)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'kicks back to the default per_page when we are not specifying a xls mime type' do
|
39
|
+
controller.request.accept = 'text/html'
|
40
|
+
controller.send(:per_page).should == ActiveAdmin.application.default_per_page
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include ActiveAdmin
|
3
|
+
|
4
|
+
module ActiveAdmin
|
5
|
+
module Xls
|
6
|
+
describe Resource do
|
7
|
+
let(:resource) { ActiveAdmin.register(Post) }
|
8
|
+
|
9
|
+
let(:custom_builder) do
|
10
|
+
Builder.new(Post) do |builder|
|
11
|
+
column(:fake) { :fake }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when registered' do
|
16
|
+
it "each resource has an xls_builer" do
|
17
|
+
resource.xls_builder.should be_a(Builder)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "We can specify our own configured builder" do
|
21
|
+
lambda { resource.xls_builder = custom_builder }.should_not raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|