resque-reports 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/lib/resque/reports/base_report.rb +37 -27
- data/lib/resque/reports/cache_file.rb +18 -15
- data/lib/resque/reports/common/batched_report.rb +102 -96
- data/lib/resque/reports/extensions/filename_gen.rb +3 -1
- data/lib/resque/reports/extensions/table_building.rb +7 -0
- data/lib/resque/reports/extensions.rb +1 -1
- data/lib/resque/reports/version.rb +1 -1
- data/resque-reports.gemspec +3 -4
- data/spec/resque/reports/base_report_spec.rb +29 -37
- data/spec/resque/reports/csv_report_spec.rb +6 -6
- data/spec/resque/reports/report_job_spec.rb +17 -27
- data/spec/spec_helper.rb +0 -1
- metadata +21 -35
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZWIzNzQwOTcxY2RjOTYxZTk5ZjBlMTY4NjkwNmJjZTU0NjBlZmZlNg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8dbaf30352c2e435726ec9cc9fe1d6364a850efd
|
4
|
+
data.tar.gz: 6d96fded79937853de430a3c332a56901c0e2ea0
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NDg4NTgyMDgwMDczNTI4ZDkxNjJlY2JjZmMzMjQ3NTg2YWY2ODZiMzgyMmJh
|
11
|
-
ZDc0ZmNmNGZkYzIyOGFhNWU1NDU3ZmVlNzAwMDAwMzE4ODliOGU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
Mzg2MmYyNDdkYjc5NDg1ZGJkZTVlNzlmYWFkZDQwOWIzYTgwYWMwNTFjZjhh
|
14
|
-
YjBlNDJhOGYyODAyYjVkOTIzZGQ2MWUyMWU1NWVhMzM4MmYyMmQxMjFmZWVj
|
15
|
-
YTg0MTQ4ZjUwMzBjYzA3OWE5N2IyZWU4NjVkM2NlN2JkYTE5Yzc=
|
6
|
+
metadata.gz: 50e199c9d2788226da04fc4e9ef9c6cad4e0c7313a4e7c40654afe18b7ffae7475aa4759e2b6ae7896fb190f48f438cc2104295d282ec5a778666777b8e8dd06
|
7
|
+
data.tar.gz: 1d1233ca179cc4686ce046a08aeefadadb0d49efd86f086b753f195eaf98b05332aa9c687b6b38cd8cfbb81b1ba607e1eba92c43f363aa132153ad54a269a591
|
@@ -76,17 +76,18 @@ module Resque
|
|
76
76
|
protected
|
77
77
|
|
78
78
|
attr_reader :create_block
|
79
|
-
attr_accessor :
|
80
|
-
:
|
81
|
-
:
|
82
|
-
:
|
83
|
-
|
84
|
-
|
85
|
-
alias_method :
|
86
|
-
alias_method :
|
87
|
-
alias_method :encoding, :
|
88
|
-
alias_method :directory, :
|
89
|
-
alias_method :queue, :
|
79
|
+
attr_accessor :_extension,
|
80
|
+
:_encoding,
|
81
|
+
:_directory,
|
82
|
+
:_queue,
|
83
|
+
:_output_filename
|
84
|
+
|
85
|
+
alias_method :super_extension, :_extension
|
86
|
+
alias_method :extension, :_extension=
|
87
|
+
alias_method :encoding, :_encoding=
|
88
|
+
alias_method :directory, :_directory=
|
89
|
+
alias_method :queue, :_queue=
|
90
|
+
alias_method :output_filename, :_output_filename=
|
90
91
|
|
91
92
|
def set_instance(obj)
|
92
93
|
@instance = obj
|
@@ -98,7 +99,7 @@ module Resque
|
|
98
99
|
|
99
100
|
# override for Extenstions::TableBuilding, to use custom encoding
|
100
101
|
def encoded_string(obj)
|
101
|
-
obj.to_s.encode(
|
102
|
+
obj.to_s.encode(_encoding,
|
102
103
|
invalid: :replace,
|
103
104
|
undef: :replace)
|
104
105
|
end
|
@@ -124,7 +125,6 @@ module Resque
|
|
124
125
|
# Constants #
|
125
126
|
#++
|
126
127
|
|
127
|
-
DEFAULT_EXTENSION = 'txt'
|
128
128
|
DEFAULT_QUEUE = :base
|
129
129
|
|
130
130
|
#--
|
@@ -132,17 +132,29 @@ module Resque
|
|
132
132
|
#++
|
133
133
|
|
134
134
|
def_delegators Const::TO_EIGENCLASS,
|
135
|
-
:
|
136
|
-
:
|
137
|
-
:
|
135
|
+
:_directory,
|
136
|
+
:_extension,
|
137
|
+
:_encoding,
|
138
|
+
:_queue,
|
138
139
|
:create_block,
|
139
140
|
:set_instance,
|
140
|
-
:
|
141
|
-
:job_queue
|
141
|
+
:_extension=
|
142
142
|
|
143
143
|
def_delegators :@cache_file, :filename, :exists?, :ready?
|
144
144
|
def_delegator Const::TO_SUPER, :super_extension
|
145
145
|
|
146
|
+
attr_reader :job_id
|
147
|
+
|
148
|
+
def self.build(options = {})
|
149
|
+
in_background = options.delete(:background)
|
150
|
+
force = options.delete(:force)
|
151
|
+
report = new(options)
|
152
|
+
|
153
|
+
in_background ? report.bg_build(force) : report.build(force)
|
154
|
+
|
155
|
+
report
|
156
|
+
end
|
157
|
+
|
146
158
|
#--
|
147
159
|
# Public instance methods
|
148
160
|
#++
|
@@ -156,9 +168,7 @@ module Resque
|
|
156
168
|
create_dispatch(*args)
|
157
169
|
else
|
158
170
|
if args && (attrs_hash = args.first) && attrs_hash.is_a?(Hash)
|
159
|
-
attrs_hash.each
|
160
|
-
send("#{name}=", value)
|
161
|
-
end
|
171
|
+
attrs_hash.each { |name, value| send("#{name}=", value) }
|
162
172
|
end
|
163
173
|
end
|
164
174
|
|
@@ -182,20 +192,20 @@ module Resque
|
|
182
192
|
args_json = [*@args, force].to_json
|
183
193
|
|
184
194
|
# Check report if it already in progress and tring return its job_id...
|
185
|
-
job_id = ReportJob.enqueued?(report_class, args_json).try(:meta_id)
|
195
|
+
@job_id = ReportJob.enqueued?(report_class, args_json).try(:meta_id)
|
186
196
|
|
187
197
|
# ...and start new job otherwise
|
188
|
-
job_id
|
198
|
+
@job_id ||= ReportJob.enqueue_to(_queue || DEFAULT_QUEUE, report_class, args_json).try(:meta_id)
|
189
199
|
end
|
190
200
|
|
191
201
|
protected
|
192
202
|
|
193
203
|
def init_cache_file
|
194
|
-
|
204
|
+
self._extension = super_extension || DEFAULT_EXTENSION
|
195
205
|
|
196
|
-
@cache_file = CacheFile.new(
|
197
|
-
generate_filename(@args,
|
198
|
-
coding:
|
206
|
+
@cache_file = CacheFile.new(_directory,
|
207
|
+
generate_filename(@args, _extension),
|
208
|
+
coding: _encoding)
|
199
209
|
end
|
200
210
|
|
201
211
|
# Method specifies how to output report data
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'tempfile'
|
1
2
|
# coding: utf-8
|
2
3
|
module Resque
|
3
4
|
module Reports
|
@@ -33,17 +34,29 @@ module Resque
|
|
33
34
|
def open(force = false)
|
34
35
|
prepare_cache_dir
|
35
36
|
|
36
|
-
force ?
|
37
|
+
(force ? clear : return) if File.exists?(@filename)
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
with_tempfile do |tempfile|
|
40
|
+
yield tempfile
|
41
|
+
|
42
|
+
tempfile.close
|
43
|
+
FileUtils.cp(tempfile.path, @filename)
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
47
|
+
def clear
|
48
|
+
FileUtils.rm_f(@filename)
|
49
|
+
end
|
50
|
+
|
45
51
|
protected
|
46
52
|
|
53
|
+
def with_tempfile
|
54
|
+
yield(tempfile = Tempfile.new(Digest::MD5.hexdigest(@filename), :encoding => @coding))
|
55
|
+
ensure
|
56
|
+
tempfile.close unless tempfile.closed?
|
57
|
+
tempfile.try(:unlink)
|
58
|
+
end
|
59
|
+
|
47
60
|
def prepare_cache_dir
|
48
61
|
FileUtils.mkdir_p @dir # create folder if not exists
|
49
62
|
|
@@ -67,16 +80,6 @@ module Resque
|
|
67
80
|
.map { |fname| File.join(@dir, fname) if File.extname(fname) == @ext }
|
68
81
|
.compact
|
69
82
|
end
|
70
|
-
|
71
|
-
def remove_unfinished_on_error
|
72
|
-
yield
|
73
|
-
rescue => error
|
74
|
-
# remove everything that was written due to it inconsistance
|
75
|
-
FileUtils.rm_f @filename
|
76
|
-
|
77
|
-
# don't suppress any errors here
|
78
|
-
raise error
|
79
|
-
end
|
80
83
|
end
|
81
84
|
end
|
82
85
|
end
|
@@ -5,119 +5,125 @@ module Resque
|
|
5
5
|
module BatchedReport
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
included do
|
9
|
+
BATCH_SIZE = 10_000
|
10
|
+
end
|
11
|
+
|
12
|
+
# Internal: Подключение используемое для выполнения запросов
|
13
|
+
#
|
14
|
+
# Returns connection adapter
|
15
|
+
def connection
|
16
|
+
ActiveRecord::Base.connection
|
17
|
+
end
|
18
|
+
|
19
|
+
# Internal: Выполняет запрос отчета пачками и выполняет block для каждой пачки
|
20
|
+
# Переопредленный метод из Resque::Reports
|
21
|
+
#
|
22
|
+
# Returns Nothing
|
23
|
+
def data_each(force = false)
|
24
|
+
0.step(data_size, batch_size) do |batch_offset|
|
25
|
+
connection.execute(batched_query(batch_offset)).each do |element|
|
26
|
+
yield element
|
20
27
|
end
|
21
28
|
end
|
29
|
+
end
|
22
30
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
31
|
+
# Internal: Возвращает общее кол-во строк в отчете
|
32
|
+
# Переопредленный метод из Resque::Reports
|
33
|
+
#
|
34
|
+
# Returns Fixnum
|
35
|
+
def data_size
|
36
|
+
@data_size ||= connection.execute(count_query)[0]['count'].to_i
|
37
|
+
end
|
30
38
|
|
31
|
-
|
39
|
+
protected
|
32
40
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
41
|
+
# Internal: Возвращает отфильтрованный запрос отчета
|
42
|
+
#
|
43
|
+
# Returns Arel::SelectManager
|
44
|
+
def query
|
45
|
+
filter base_query
|
46
|
+
end
|
39
47
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
48
|
+
# Internal: Полезный метод для хранения Arel::Table объектов для запроса отчета
|
49
|
+
#
|
50
|
+
# Returns Hash, {:table_name => #<Arel::Table @name="table_name">, ...}
|
51
|
+
def tables
|
52
|
+
return @tables if defined? @tables
|
45
53
|
|
46
|
-
|
54
|
+
tables = models.map(&:arel_table)
|
47
55
|
|
48
|
-
|
49
|
-
|
56
|
+
@tables = tables.reduce({}) { |a, e| a.store(e.name, e) && a }.with_indifferent_access
|
57
|
+
end
|
50
58
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
+
# Internal: Полезный метод для join'а необходимых таблиц через Arel
|
60
|
+
#
|
61
|
+
# Returns Arel
|
62
|
+
def join_tables(source_table, *joins)
|
63
|
+
joins.inject(source_table) { |query, joined| query.join(joined[:table]).on(joined[:on]) }
|
64
|
+
end
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
+
# Internal: Размер пачки отчета
|
67
|
+
#
|
68
|
+
# Returns Fixnum
|
69
|
+
def batch_size
|
70
|
+
BATCH_SIZE
|
71
|
+
end
|
66
72
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
+
# Internal: Модели используемые в отчете
|
74
|
+
#
|
75
|
+
# Returns Array of Arel::Table
|
76
|
+
def models
|
77
|
+
fail NotImplementedError
|
78
|
+
end
|
73
79
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
+
# Internal: Основной запрос отчета (Arel)
|
81
|
+
#
|
82
|
+
# Returns Arel::SelectManager
|
83
|
+
def base_query
|
84
|
+
fail NotImplementedError
|
85
|
+
end
|
80
86
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
+
# Internal: Поля запрашиваемые отчетом
|
88
|
+
#
|
89
|
+
# Returns String (SQL)
|
90
|
+
def select
|
91
|
+
fail NotImplementedError
|
92
|
+
end
|
87
93
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
+
# Internal: Порядок строк отчета
|
95
|
+
#
|
96
|
+
# Returns String (SQL)
|
97
|
+
def order
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
alias_method :order_by, :order
|
94
101
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
102
|
+
# Internal: Фильтры отчета
|
103
|
+
#
|
104
|
+
# Returns Arel::SelectManager
|
105
|
+
def filter(query)
|
106
|
+
query
|
107
|
+
end
|
101
108
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
109
|
+
# Internal: Запрос количества строк в отчете
|
110
|
+
#
|
111
|
+
# Returns String (SQL)
|
112
|
+
def count_query
|
113
|
+
query.project(Arel.sql('COUNT(*) as count')).to_sql
|
114
|
+
end
|
108
115
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
116
|
+
# Internal: Запрос пачки строк отчета
|
117
|
+
#
|
118
|
+
# offset - Numeric, число строк на которое сдвигается запрос
|
119
|
+
#
|
120
|
+
# Returns String (SQL)
|
121
|
+
def batched_query(offset)
|
122
|
+
query.project(Arel.sql(select))
|
123
|
+
.take(batch_size)
|
124
|
+
.skip(offset)
|
125
|
+
.order(order_by)
|
126
|
+
.to_sql
|
121
127
|
end
|
122
128
|
end
|
123
129
|
end
|
@@ -14,10 +14,12 @@ module Resque
|
|
14
14
|
# end
|
15
15
|
module FilenameGen
|
16
16
|
|
17
|
+
DEFAULT_EXTENSION = 'txt'
|
18
|
+
|
17
19
|
private
|
18
20
|
|
19
21
|
def generate_filename(args, fextension)
|
20
|
-
"#{ hash(self.class.to_s, *args) }.#{ fextension }"
|
22
|
+
"#{ hash(self.class.to_s, *args) }.#{ fextension || DEFAULT_EXTENSION }"
|
21
23
|
end
|
22
24
|
|
23
25
|
def hash(*args)
|
@@ -28,6 +28,13 @@ module Resque
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def column(name, value, options = {})
|
31
|
+
if options[:skip_if].present?
|
32
|
+
if options[:skip_if].is_a?(Symbol)
|
33
|
+
return if @instance.send(options.delete(:skip_if))
|
34
|
+
elsif options[:skip_if].respond_to?(:call)
|
35
|
+
return if options.delete(:skip_if).call
|
36
|
+
end
|
37
|
+
end
|
31
38
|
add_column_header(name) || add_column_cell(value, options)
|
32
39
|
end
|
33
40
|
|
@@ -32,7 +32,7 @@ module Resque
|
|
32
32
|
base.send :include, EventCallbacks # event callbacks and handlers
|
33
33
|
base.send :include, EventTemplates # template events handling methods
|
34
34
|
base.send :include, Encodings # encoding constants
|
35
|
-
base.send :include, EnqueueToFix #
|
35
|
+
base.send :include, EnqueueToFix # enqueue task to exact queue
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
data/resque-reports.gemspec
CHANGED
@@ -18,12 +18,11 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ['lib']
|
20
20
|
|
21
|
-
gem.add_dependency 'resque-integration', '>= 0.
|
21
|
+
gem.add_dependency 'resque-integration', '>= 0.4.4'
|
22
22
|
gem.add_dependency 'activesupport' # избавиться от зависимости
|
23
23
|
|
24
|
-
gem.add_development_dependency
|
25
|
-
gem.add_development_dependency
|
24
|
+
gem.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
gem.add_development_dependency 'rake'
|
26
26
|
gem.add_development_dependency 'rspec', '>= 2.14.0'
|
27
|
-
gem.add_development_dependency 'rspec-given', '~> 3.0'
|
28
27
|
gem.add_development_dependency 'simplecov'
|
29
28
|
end
|
@@ -2,8 +2,6 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
require 'stringio'
|
4
4
|
|
5
|
-
require 'resque-reports'
|
6
|
-
|
7
5
|
class MyTypeReport < Resque::Reports::BaseReport
|
8
6
|
extension :type
|
9
7
|
|
@@ -51,15 +49,15 @@ describe 'Resque::Reports::BaseReport successor' do
|
|
51
49
|
let(:dummy) { Resque::Reports::Extensions::Dummy.new }
|
52
50
|
|
53
51
|
describe '#extension' do
|
54
|
-
before { File.
|
52
|
+
before { allow(File).to receive(:exists?).and_return(true) }
|
55
53
|
|
56
|
-
it { File.extname(my_report.filename).
|
54
|
+
it { expect(File.extname(my_report.filename)).to eq '.type' }
|
57
55
|
end
|
58
56
|
|
59
57
|
describe '#source' do
|
60
|
-
before { my_report.
|
58
|
+
before { allow(my_report).to receive(:select_data).and_return([dummy]) }
|
61
59
|
|
62
|
-
it { my_report.
|
60
|
+
it { expect(my_report).to receive(:select_data) }
|
63
61
|
|
64
62
|
after { my_report.build true }
|
65
63
|
end
|
@@ -68,32 +66,32 @@ describe 'Resque::Reports::BaseReport successor' do
|
|
68
66
|
subject { my_report.instance_variable_get(:@cache_file) }
|
69
67
|
let(:tmpdir) { File.join(Dir.tmpdir, 'resque-reports') }
|
70
68
|
|
71
|
-
it { subject.instance_variable_get(:@dir).
|
69
|
+
it { expect(subject.instance_variable_get(:@dir)).to eq tmpdir }
|
72
70
|
end
|
73
71
|
|
74
72
|
describe '#create' do
|
75
|
-
it { my_report.instance_variable_get(:@main_param).
|
73
|
+
it { expect(my_report.instance_variable_get(:@main_param)).to eq 'test' }
|
76
74
|
end
|
77
75
|
|
78
76
|
describe '#encoding' do
|
79
77
|
subject { my_report.instance_variable_get(:@cache_file) }
|
80
78
|
let(:utf_coding) { Resque::Reports::Extensions::Encodings::UTF8 }
|
81
79
|
|
82
|
-
it { subject.instance_variable_get(:@coding).
|
80
|
+
it { expect(subject.instance_variable_get(:@coding)).to eq utf_coding }
|
83
81
|
end
|
84
82
|
|
85
83
|
describe '#write' do
|
86
84
|
subject { MyReport.new('#write test') }
|
87
85
|
|
88
86
|
before do
|
89
|
-
subject.
|
90
|
-
subject.
|
91
|
-
subject.
|
87
|
+
allow(subject).to receive(:data_each) { |&block| block.call(dummy) }
|
88
|
+
allow(subject).to receive(:build_table_row).and_return(['row'])
|
89
|
+
allow(subject).to receive(:build_table_header).and_return(['header'])
|
92
90
|
|
93
91
|
subject.write(io)
|
94
92
|
end
|
95
93
|
|
96
|
-
it { io.string.
|
94
|
+
it { expect(io.string).to eq "header\r\nrow\r\n" }
|
97
95
|
end
|
98
96
|
|
99
97
|
describe '#bg_build' do
|
@@ -102,13 +100,10 @@ describe 'Resque::Reports::BaseReport successor' do
|
|
102
100
|
context 'when report is building twice' do
|
103
101
|
subject { MyReport.new('#bg_build test') }
|
104
102
|
|
105
|
-
before { job_class.
|
103
|
+
before { allow(job_class).to receive(:enqueue_to).and_return('job_id') }
|
106
104
|
|
107
105
|
it do
|
108
|
-
job_class
|
109
|
-
.should_receive(:enqueue_to).twice
|
110
|
-
#.with(:my_type_reports, 'MyReport', '["#bg_build test",true]')
|
111
|
-
|
106
|
+
expect(job_class).to receive(:enqueue_to).twice
|
112
107
|
end
|
113
108
|
|
114
109
|
after do
|
@@ -119,44 +114,41 @@ describe 'Resque::Reports::BaseReport successor' do
|
|
119
114
|
context 'when report is building' do
|
120
115
|
subject { MyReport.new('#bg_build test') }
|
121
116
|
|
122
|
-
before { job_class.
|
117
|
+
before { allow(job_class).to receive(:enqueue_to).and_return('job_id') }
|
123
118
|
|
124
|
-
it
|
125
|
-
job_class
|
126
|
-
.should_receive(:enqueue_to)
|
127
|
-
#.with(:my_type_reports, 'MyReport', '["#bg_build test",true]')
|
128
|
-
end
|
119
|
+
it { expect(job_class).to receive(:enqueue_to) }
|
129
120
|
|
130
|
-
after
|
121
|
+
after { subject.bg_build true }
|
131
122
|
end
|
132
123
|
|
133
124
|
context 'when report is not build yet' do
|
134
125
|
subject { MyReport.new('#bg_build test') }
|
135
126
|
|
136
127
|
before do
|
137
|
-
job_class.
|
128
|
+
allow(job_class).to receive(:enqueued?).and_return(double('Meta', meta_id: 'enqueued_job_id'))
|
138
129
|
end
|
139
130
|
|
140
|
-
it { subject.bg_build(true).
|
131
|
+
it { expect(subject.bg_build(true)).to eq 'enqueued_job_id' }
|
141
132
|
end
|
142
133
|
end
|
143
134
|
|
144
135
|
describe '#build' do
|
145
|
-
|
146
|
-
|
147
|
-
it { subject.should_receive(:decorate_second).exactly(3).times }
|
136
|
+
context 'when report decorated' do
|
137
|
+
subject { MyReport.new('#build test') }
|
148
138
|
|
149
|
-
|
139
|
+
it { expect(subject).to receive(:decorate_second).exactly(3).times }
|
150
140
|
|
141
|
+
after { subject.build true }
|
142
|
+
end
|
151
143
|
context 'when report was built' do
|
152
144
|
subject { MyReport.new('was built test') }
|
153
145
|
|
154
146
|
before { subject.build true }
|
155
147
|
|
156
|
-
|
148
|
+
it { expect(subject).to be_exists }
|
157
149
|
it do
|
158
|
-
File.read(subject.filename)
|
159
|
-
.
|
150
|
+
expect(File.read(subject.filename))
|
151
|
+
.to eq <<-REPORT.gsub(/^ {12}/, '')
|
160
152
|
First one|Second\r
|
161
153
|
one|one - is second\r
|
162
154
|
was built test|was built test - is second\r
|
@@ -168,7 +160,7 @@ describe 'Resque::Reports::BaseReport successor' do
|
|
168
160
|
describe '#data_each' do
|
169
161
|
subject { MyReport.new('#data_each test') }
|
170
162
|
|
171
|
-
it { subject.
|
163
|
+
it { expect(subject).to receive(:data_each) }
|
172
164
|
|
173
165
|
after { subject.write(io) }
|
174
166
|
end
|
@@ -176,7 +168,7 @@ describe 'Resque::Reports::BaseReport successor' do
|
|
176
168
|
describe '#build_table_header' do
|
177
169
|
subject { MyReport.new('#build_table_header test') }
|
178
170
|
|
179
|
-
it { subject.
|
171
|
+
it { expect(subject).to receive(:build_table_header) }
|
180
172
|
|
181
173
|
after { subject.write(io) }
|
182
174
|
end
|
@@ -184,7 +176,7 @@ describe 'Resque::Reports::BaseReport successor' do
|
|
184
176
|
describe '#build_table_row' do
|
185
177
|
subject { MyReport.new('#build_table_row test') }
|
186
178
|
|
187
|
-
it { subject.
|
179
|
+
it { expect(subject).to receive(:build_table_row).twice }
|
188
180
|
|
189
181
|
after { subject.write(io) }
|
190
182
|
end
|
@@ -57,7 +57,7 @@ describe 'Resque::Reports::CsvReport successor' do
|
|
57
57
|
subject { MyCsvDefaultsReport.new }
|
58
58
|
|
59
59
|
it 'sets csv_options defaults' do
|
60
|
-
subject.options.
|
60
|
+
expect(subject.options).to eq MyCsvReport::DEFAULT_CSV_OPTIONS
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -69,7 +69,7 @@ describe 'Resque::Reports::CsvReport successor' do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'merges csv_options with defaults' do
|
72
|
-
subject.options.
|
72
|
+
expect(subject.options).to eq my_options
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
@@ -78,12 +78,12 @@ describe 'Resque::Reports::CsvReport successor' do
|
|
78
78
|
context 'when report was built' do
|
79
79
|
subject { MyCsvReport.new('was built test') }
|
80
80
|
|
81
|
-
|
81
|
+
after { subject.build true }
|
82
82
|
|
83
|
-
|
83
|
+
it { expect(subject).to be_exists }
|
84
84
|
it do
|
85
|
-
File.read(subject.filename)
|
86
|
-
.
|
85
|
+
expect(File.read(subject.filename))
|
86
|
+
.to eq <<-CSV.gsub(/^ {12}/, '')
|
87
87
|
First one,Second,Third
|
88
88
|
decorated: one,was built test - is second,3'rd row element is: 3
|
89
89
|
CSV
|
@@ -32,10 +32,10 @@ describe Resque::Reports::ReportJob do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
describe '.execute' do
|
35
|
-
before { Reports::MyCsvReport.
|
35
|
+
before { allow(Reports::MyCsvReport).to receive(:new).and_return(my_report) }
|
36
36
|
|
37
37
|
context 'when building report' do
|
38
|
-
before { my_report.
|
38
|
+
before { allow(my_report).to receive(:build).and_return(nil) }
|
39
39
|
|
40
40
|
it do
|
41
41
|
expect(Reports::MyCsvReport)
|
@@ -60,24 +60,24 @@ describe Resque::Reports::ReportJob do
|
|
60
60
|
|
61
61
|
context 'when events are firing' do
|
62
62
|
before do
|
63
|
-
described_class.
|
64
|
-
described_class.get_meta.
|
63
|
+
allow(described_class).to receive(:get_meta).and_return({})
|
64
|
+
allow(described_class.get_meta).to receive(:save).and_return(true)
|
65
65
|
end
|
66
66
|
|
67
67
|
context 'when progress total is zero' do
|
68
68
|
before do
|
69
|
-
my_report.
|
70
|
-
my_report.
|
69
|
+
allow(my_report).to receive(:select_data).and_return([])
|
70
|
+
allow(my_report).to receive(:data_size).and_return(0)
|
71
71
|
end
|
72
72
|
|
73
|
-
it { described_class.
|
73
|
+
it { expect(described_class).to_not receive(:at) }
|
74
74
|
|
75
75
|
after { described_class.execute(*exec_params) }
|
76
76
|
end
|
77
77
|
|
78
78
|
context 'when works default handlers' do
|
79
79
|
context 'when error occurs' do
|
80
|
-
before { my_report.
|
80
|
+
before { allow(my_report).to receive(:build_table_row) { fail 'Custom error' } }
|
81
81
|
|
82
82
|
it do
|
83
83
|
expect { described_class.execute(*exec_params) }
|
@@ -86,7 +86,7 @@ describe Resque::Reports::ReportJob do
|
|
86
86
|
end
|
87
87
|
|
88
88
|
context 'when progress is changed' do
|
89
|
-
it { described_class.
|
89
|
+
it { expect(described_class).to receive(:at).with(2, 2, nil) }
|
90
90
|
|
91
91
|
after { described_class.execute(*exec_params) }
|
92
92
|
end
|
@@ -95,28 +95,21 @@ describe Resque::Reports::ReportJob do
|
|
95
95
|
context 'when works custom handlers' do
|
96
96
|
context 'when error occurs' do
|
97
97
|
before do
|
98
|
-
my_report.
|
99
|
-
my_report.
|
98
|
+
allow(my_report).to receive(:error_message) { |e| fail "Boom! #{e.message}" }
|
99
|
+
allow(my_report).to receive(:build_table_row) { fail 'Custom error' }
|
100
100
|
end
|
101
101
|
|
102
|
-
it
|
103
|
-
expect { described_class.execute(*exec_params) }
|
104
|
-
.to raise_error('Boom! Custom error')
|
105
|
-
end
|
102
|
+
it { expect { described_class.execute(*exec_params) }.to raise_error('Boom! Custom error') }
|
106
103
|
end
|
107
104
|
|
108
105
|
context 'when progress is changed' do
|
109
106
|
before do
|
110
|
-
my_report.
|
107
|
+
allow(my_report).to receive(:progress_message) do |progress, total|
|
111
108
|
"my progress: #{progress} / #{total}"
|
112
109
|
end
|
113
110
|
end
|
114
111
|
|
115
|
-
it
|
116
|
-
described_class
|
117
|
-
.should_receive(:at)
|
118
|
-
.with(2, 2, 'my progress: 2 / 2')
|
119
|
-
end
|
112
|
+
it { expect(described_class).to receive(:at).with(2, 2, 'my progress: 2 / 2') }
|
120
113
|
|
121
114
|
after { described_class.execute(*exec_params) }
|
122
115
|
end
|
@@ -125,14 +118,11 @@ describe Resque::Reports::ReportJob do
|
|
125
118
|
context 'when task is performed by resque' do
|
126
119
|
context 'when error occurs' do
|
127
120
|
before do
|
128
|
-
my_report.
|
129
|
-
my_report.
|
121
|
+
allow(my_report).to receive(:error_message) { |e| fail "Boom! #{e.message}" }
|
122
|
+
allow(my_report).to receive(:build_table_row) { fail 'Custom error' }
|
130
123
|
end
|
131
124
|
|
132
|
-
it
|
133
|
-
expect { described_class.execute(*exec_params) }
|
134
|
-
.to raise_error('Boom! Custom error')
|
135
|
-
end
|
125
|
+
it { expect { described_class.execute(*exec_params) }.to raise_error('Boom! Custom error') }
|
136
126
|
end
|
137
127
|
end
|
138
128
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,111 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-reports
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey D.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: resque-integration
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.4.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.4.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.3'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 2.14.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 2.14.0
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rspec-given
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ~>
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '3.0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ~>
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '3.0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: simplecov
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
|
-
- -
|
87
|
+
- - ">="
|
102
88
|
- !ruby/object:Gem::Version
|
103
89
|
version: '0'
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
|
-
- -
|
94
|
+
- - ">="
|
109
95
|
- !ruby/object:Gem::Version
|
110
96
|
version: '0'
|
111
97
|
description: Make your custom reports to CSV in background using Resque with simple
|
@@ -116,9 +102,9 @@ executables: []
|
|
116
102
|
extensions: []
|
117
103
|
extra_rdoc_files: []
|
118
104
|
files:
|
119
|
-
- .gitignore
|
120
|
-
- .rspec
|
121
|
-
- .rubocop.yml
|
105
|
+
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- ".rubocop.yml"
|
122
108
|
- Gemfile
|
123
109
|
- MIT-LICENSE
|
124
110
|
- README
|
@@ -155,12 +141,12 @@ require_paths:
|
|
155
141
|
- lib
|
156
142
|
required_ruby_version: !ruby/object:Gem::Requirement
|
157
143
|
requirements:
|
158
|
-
- -
|
144
|
+
- - ">="
|
159
145
|
- !ruby/object:Gem::Version
|
160
146
|
version: '0'
|
161
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
148
|
requirements:
|
163
|
-
- -
|
149
|
+
- - ">="
|
164
150
|
- !ruby/object:Gem::Version
|
165
151
|
version: '0'
|
166
152
|
requirements: []
|